```compiler.js
// cat/src/compiler.js

const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');
const { parseComponent, parseScript, generateClassCode, transformMethodBody, generateDOMCode, sanitizeVariableName } = require('./component');
const { parsePageComponent, generatePageClassCode, generateRouterClassCode } = require('./page');
const { parseDocument } = require('htmlparser2');

/**
 * Detect used components in the provided HTML contents by parsing the HTML tags.
 * @param {Array<string>} htmlContents - Array of HTML file contents.
 * @param {Set<string>} availableComponents - Set of all available component tag names.
 * @returns {Set<string>} - Set of used component tag names.
 */
function detectUsedComponents(htmlContents, availableComponents) {
  const usedComponents = new Set();

  // Regex to match all tags in the HTML
  const tagRegex = /<\s*([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*>/g;

  htmlContents.forEach(content => {
    let match;
    while ((match = tagRegex.exec(content)) !== null) {
      let tag = match[1];
      if (availableComponents.has(tag)) {
        usedComponents.add(tag);
      }
    }
  });

  return usedComponents;
}

/**
 * Compiler Function
 * @param {string} indexPath - Path to the index.html file.
 * @returns {Promise<string>} - Compiled HTML content with component and page registrations.
 */
async function compile(indexPath) {
  // Read the index.html content
  let indexContent = await fs.readFile(indexPath, 'utf-8');

  // Define project root
  const projectRoot = path.dirname(indexPath);

  // -----------------------
  // Step 1: Process Components
  // -----------------------

  // Find all .comp.html files in the project directory
  const compFiles = glob.sync('**/*.comp.html', {
    cwd: projectRoot,
    absolute: true,
    ignore: ['node_modules/**', 'cat/**'] // Ignore node_modules and cat directory to prevent recursion
  });

  const componentMap = new Map(); // Map of tagName to compiled class code
  const parsedComponents = new Set(); // To track parsed components

  // Parse and compile each component file
  for (const file of compFiles) {
    try {
      const { tagName, html, script, style } = await parseComponent(file);

      if (!parsedComponents.has(tagName)) {
        // Parse script to extract properties and methods
        const { properties, methods } = parseScript(script);

        // Generate class code
        const classCode = generateClassCode({
          tagName,
          html,
          style,
          properties,
          methods,
        });

        componentMap.set(tagName, classCode);
        parsedComponents.add(tagName);

        console.log(`🔍 Parsed and compiled component: <${tagName}> from ${path.relative(projectRoot, file)}`);
      } else {
        console.log(`ℹ️  Component <${tagName}> from ${path.relative(projectRoot, file)} has already been parsed.`);
      }
    } catch (error) {
      console.error(`❌ Failed to parse ${file}: ${error.message}`);
    }
  }

  if (componentMap.size === 0) {
    console.warn('⚠️  No components found to compile.');
  }

  // -----------------------
  // Step 2: Process Pages
  // -----------------------

  // Find all .page.html files in the project directory
  const pageFiles = glob.sync('**/*.page.html', {
    cwd: projectRoot,
    absolute: true,
    ignore: ['node_modules/**', 'cat/**']
  });

  // Initialize pageCounter
  let pageCounter = 1;

  const pageClassMap = new Map(); // Map of route to page class details
  const pageHtmlContents = []; // For component usage detection
  let collectedPageStyles = ''; // Collect styles from all pages

  for (const file of pageFiles) {
    try {
      const { route, html, script, style } = await parsePageComponent(file);

      const className = `_Page${pageCounter++}`;

      // Parse script to extract properties and methods
      const { properties, methods } = parseScript(script);

      // Generate class code
      const classCode = generatePageClassCode({
        className,
        html,
        style,
        properties,
        methods,
      });

      pageClassMap.set(route, { className, classCode });

      console.log(`📄 Parsed and compiled page: ${className} for route &quot;${route}&quot; from ${path.relative(projectRoot, file)}`);

      // Collect html content
      pageHtmlContents.push(html);

      // Collect styles
      if (style) {
        collectedPageStyles += style + '\n';
      }

    } catch (error) {
      console.error(`❌ Failed to parse page ${file}: ${error.message}`);
    }
  }

  if (pageClassMap.size === 0) {
    console.warn('⚠️  No pages found to compile.');
  }

  // -----------------------
  // Step 3: Detect Used Components
  // -----------------------

  // Find all .html files in the project directory for usage detection
  const htmlFiles = glob.sync('**/*.html', {
    cwd: projectRoot,
    absolute: true,
    ignore: ['node_modules/**', 'cat/**']
  });

  const htmlContents = [];
  for (const file of htmlFiles) {
    try {
      const content = await fs.readFile(file, 'utf-8');
      htmlContents.push(content);
    } catch (error) {
      console.error(`❌ Failed to read HTML file ${file}: ${error.message}`);
    }
  }

  // Combine with pages' html content
  const allHtmlContents = htmlContents.concat(pageHtmlContents);

  // Detect which components are used across all HTML files and page html
  const availableComponents = new Set(componentMap.keys());
  const usedComponents = detectUsedComponents(allHtmlContents, availableComponents);

  if (usedComponents.size === 0) {
    console.warn('⚠️  No used components found in HTML files.');
  } else {
    console.log(`📦 Used components: ${[...usedComponents].join(', ')}`);
  }

  // -----------------------
  // Step 4: Verify <load> Tags
  // -----------------------

  // Find all <load route=&quot;...&quot;> and <load name=&quot;...&quot;/> tags in indexContent
  const loadTagRegex = /<load\s+[^>]*(route|name)=[&quot;']([^&quot;']+)[&quot;'][^>]*>/gi;
  const loadRoutes = [];
  let match;
  while ((match = loadTagRegex.exec(indexContent)) !== null) {
    const attrType = match[1];
    const value = match[2];
    if (attrType === 'route') {
      loadRoutes.push(value);
    }
  }

  // Verify that each load route exists in the pageClassMap
  loadRoutes.forEach(route => {
    if (!pageClassMap.has(route)) {
      console.error(`❌ No page found for route &quot;${route}&quot;. Please ensure a .page.html file exists with route=&quot;${route}&quot;.`);
    }
  });

  // -----------------------
  // Step 5: Inject Page Styles into <head>
  // -----------------------

  if (collectedPageStyles.trim()) {
    const styleTag = `<style>
${collectedPageStyles}
</style>
`;

    // Inject the style tag into <head>
    if (indexContent.includes('</head>')) {
      indexContent = indexContent.replace('</head>', `${styleTag}</head>`);
      console.log('🎨 Injected page styles into <head>.');
    } else {
      // If no </head> tag, prepend the styles
      indexContent = styleTag + '\n' + indexContent;
    }
  }

  // -----------------------
  // Step 6: Generate Registration Script
  // -----------------------

  const registrationScript = generateCompleteScript(componentMap, usedComponents, pageClassMap);

  // -----------------------
  // Step 7: Inject Registration Script
  // -----------------------

  if (registrationScript.trim()) {
    // Inject the registration script before the closing </body> tag
    const scriptTag = `<script>
${registrationScript}
</script>
`;

    if (indexContent.includes('</body>')) {
      indexContent = indexContent.replace('</body>', `${scriptTag}</body>`);
    } else {
      // If no </body> tag, append the script at the end
      indexContent += `\n${scriptTag}`;
    }
    console.log('📝 Injected component and page scripts.');
  }

  // -----------------------
  // Step 8: Return Compiled Content
  // -----------------------

  return indexContent;
}

/**
 * Generate the complete registration script for components and pages, including the Router class.
 * @param {Map<string, string>} componentsMap - Map of tagName to compiled class code.
 * @param {Set<string>} usedComponents - Set of used component tag names.
 * @param {Map<string, {className: string, classCode: string}>} pageClassMap - Map of route to page class details.
 * @returns {string} - Combined JavaScript code.
 */
function generateCompleteScript(componentsMap, usedComponents, pageClassMap) {
  let script = '';

  // Generate components' class definitions
  usedComponents.forEach(tagName => {
    const classCode = componentsMap.get(tagName);
    if (classCode) {
      script += `
${classCode}
    `;
    }
  });

  // Generate pages' class definitions
  pageClassMap.forEach(({ className, classCode }, route) => {
    script += `
${classCode}
    `;
  });

  // Generate Router class code
  script += generateRouterClassCode(pageClassMap);

  return script;
}

module.exports = { compile };
```

```component.js
// cat/src/component.js

const fs = require('fs-extra');
const path = require('path');
const acorn = require('acorn'); // Import Acorn for JavaScript parsing
const { parseDocument } = require('htmlparser2');

/**
 * Parse a component file to extract tagName, HTML, script, and style sections.
 * @param {string} filePath - Path to the .comp.html file.
 * @returns {Promise<{ tagName: string, html: string, script: string, style: string }>} - Component details.
 */
async function parseComponent(filePath) {
  const content = await fs.readFile(filePath, 'utf-8');

  // Extract the outermost tag name and inner HTML
  const componentRegex = /<([\w-]+)>([\s\S]*?)<\/\1>/;
  const componentMatch = content.match(componentRegex);

  if (!componentMatch) {
    throw new Error(`Invalid component structure in ${path.basename(filePath)}`);
  }

  const tagName = componentMatch[1];
  let innerContent = componentMatch[2];

  // Extract all <script> sections
  const scriptRegex = /<script>([\s\S]*?)<\/script>/g;
  let scriptContent = '';
  let scriptMatch;
  while ((scriptMatch = scriptRegex.exec(content)) !== null) {
    scriptContent += scriptMatch[1].trim() + '\n';
  }

  // Extract all <style> sections
  const styleRegex = /<style>([\s\S]*?)<\/style>/g;
  let styleContent = '';
  let styleMatch;
  while ((styleMatch = styleRegex.exec(content)) !== null) {
    styleContent += styleMatch[1].trim() + '\n';
  }

  // Remove all <script> and <style> tags from innerContent
  innerContent = innerContent
    .replace(scriptRegex, '')
    .replace(styleRegex, '')
    .trim();

  return {
    tagName,
    html: innerContent,
    script: scriptContent,
    style: styleContent,
  };
}

/**
 * Parse the script content to extract properties and methods.
 * @param {string} script - The script content.
 * @returns {{ properties: Array, methods: Array }} - Parsed properties and methods.
 */
function parseScript(script) {
  const properties = [];
  const methods = [];

  try {
    // Parse the script content into an AST
    const ast = acorn.parse(script, { ecmaVersion: 2020, locations: true });

    ast.body.forEach(node => {
      if (node.type === 'VariableDeclaration') {
        node.declarations.forEach(declarator => {
          if (declarator.id.type === 'Identifier') {
            const varName = declarator.id.name;
            const varValue = script.substring(declarator.init.start, declarator.init.end);
            properties.push({ name: varName, value: varValue });
          }
        });
      } else if (node.type === 'FunctionDeclaration') {
        const funcName = node.id.name;
        const params = node.params.map(param => script.substring(param.start, param.end)).join(', ');
        const body = script.substring(node.body.start, node.body.end);
        methods.push({ name: funcName, params, body });
      }
    });
  } catch (error) {
    console.error(`Error parsing script: ${error.message}`);
  }

  return { properties, methods };
}

/**
 * Convert a kebab-case or other tag name to PascalCase for class naming.
 * @param {string} tagName - The custom element tag name.
 * @returns {string} - PascalCase string.
 */
function toPascalCase(tagName) {
  return tagName
    .split('-')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join('');
}

/**
 * Escape backticks in templates to avoid breaking template literals.
 * @param {string} str - The template string.
 * @returns {string} - Escaped string.
 */
function escapeBackticks(str) {
  return str.replace(/`/g, '\\`');
}

/**
 * Sanitize a string to be a valid JavaScript identifier.
 * @param {string} name - The original name.
 * @returns {string} - Sanitized identifier.
 */
function sanitizeVariableName(name) {
  // Replace invalid characters with underscores
  let sanitized = name.replace(/[^A-Za-z0-9_$]/g, '_');
  // If the name starts with a digit, prefix with underscore
  if (/^\d/.test(sanitized)) {
    sanitized = '_' + sanitized;
  }
  return sanitized;
}

/**
 * Generate the class code for the component.
 * @param {object} component - Component details.
 * @returns {string} - The compiled class code.
 */
function generateClassCode({ tagName, html, style, properties, methods }) {
  const className = toPascalCase(tagName);
  let classCode = `class ${className} extends HTMLElement {
    constructor() {
      super();
  `;

  // Initialize properties
  properties.forEach(prop => {
    classCode += `    this._${prop.name} = ${prop.value};
  `;
  });

  classCode += `
      this.attachShadow({ mode: 'open' });
      this._buildDOM();
    }

    _buildDOM() {
      const fragment = document.createDocumentFragment();
  `;

  // Add styles
  if (style) {
    classCode += `    const style = document.createElement('style');
      style.textContent = \`
  ${style}
      \`;
      fragment.appendChild(style);

  `;
  }

  // Generate DOM creation code
  const { code: domCode, cachedNodes, eventListeners } = generateDOMCode(html);
  classCode += domCode;

  classCode += `
      this.shadowRoot.appendChild(fragment);
    }
  `;

  // connectedCallback
  classCode += `
    connectedCallback() {
  `;
  
  // Attach event listeners
  if (eventListeners &amp;&amp; eventListeners.length > 0) {
    eventListeners.forEach(listener => {
      classCode += `    this.${listener.elementVarName}.addEventListener('${listener.event}', this.${listener.handlerName}.bind(this));
  `;
    });
  }

  classCode += `  }

    disconnectedCallback() {
  `;

  // Remove event listeners
  if (eventListeners &amp;&amp; eventListeners.length > 0) {
    eventListeners.forEach(listener => {
      classCode += `    this.${listener.elementVarName}.removeEventListener('${listener.event}', this.${listener.handlerName}.bind(this));
  `;
    });
  }

  classCode += `  }
  `;

  // Generate getters and setters
  Object.keys(cachedNodes).forEach(propName => {
    const nodes = cachedNodes[propName];

    classCode += `
    get ${propName}() { return this._${propName}; }
    set ${propName}(value) {
      if (this._${propName} !== value) {
        this._${propName} = value;
  `;
    
    nodes.forEach(node => {
      if (node.type === 'text') {
        classCode += `      this.${node.varName}.textContent = ${node.expression};
  `;
      } else if (node.type === 'attribute') {
        classCode += `      this.${node.elementVarName}.setAttribute('${node.attrName}', ${node.expression});
  `;
      }
    });

    classCode += `    }
    }
  `;
  });

  // Add methods
  methods.forEach(method => {
    const transformedBody = transformMethodBody(method.body, properties.map(p => p.name));
    classCode += `
    ${method.name}(${method.params}) {
  ${transformedBody}
    }
  `;
  });

  classCode += `}
    
  customElements.define('${tagName}', ${className});
  `;

  return classCode;
}

/**
 * Transform method body to replace variable references with 'this.' prefix.
 * @param {string} body - The method body.
 * @param {Array<string>} propNames - The property names to replace.
 * @returns {string} - The transformed method body.
 */
function transformMethodBody(body, propNames) {
  let transformedBody = body;

  propNames.forEach(propName => {
    // Replace assignments like 'propName = value;' with 'this.propName = value;'
    const assignRegex = new RegExp(`([^\\.\\w$])${propName}\\s*=`, 'g');
    transformedBody = transformedBody.replace(assignRegex, `$1this.${propName} =`);

    // Replace variable references with 'this.propName'
    const varRegex = new RegExp(`([^\\.\\w$])${propName}([^\\w$])`, 'g');
    transformedBody = transformedBody.replace(varRegex, `$1this.${propName}$2`);
  });

  // Ensure braces are correctly balanced and formatted
  transformedBody = transformedBody.trim();

  // Remove extra outer braces if they exist
  if (transformedBody.startsWith('{') &amp;&amp; transformedBody.endsWith('}')) {
    transformedBody = transformedBody.slice(1, -1).trim();
  }

  // Properly indent the method body
  transformedBody = transformedBody
    .split('\n')
    .map(line => '    ' + line.trim())
    .join('\n');

  return transformedBody;
}

/**
 * Generate DOM creation code from HTML using htmlparser2.
 * @param {string} html - The inner HTML string of the component.
 * @returns {object} - Object containing generated code, cached nodes, and event listeners.
 */
function generateDOMCode(html) {
  const dom = parseDocument(html).children; // Array of DOM nodes

  let code = '';
  let varCounter = 0;
  const cachedNodes = {}; // For properties to nodes
  const eventListeners = [];

  function traverse(node, parentVarName) {
    if (node.type === 'tag') {
      const sanitizedTagName = sanitizeVariableName(node.name);
      const varName = sanitizedTagName + ++varCounter;

      // Decide whether to assign to 'this.' or 'const'
      let declaration;
      if (needsReference(node)) {
        declaration = `this.${varName}`;
      } else {
        declaration = `const ${varName}`;
      }

      const varReference = declaration.replace(/^const /, '');
      code += `    ${declaration} = document.createElement('${node.name}');
  `;

      // Handle attributes
      const attribs = node.attribs || {};
      for (let [attrName, attrValue] of Object.entries(attribs)) {
        if (attrName === 'class' || attrName === 'style' || attrName.startsWith('data-') || attrName === 'id' || attrName === 'src' || attrName === 'alt') {
          // Handle attributes with embedded expressions
          const { expression, propNames } = generateAttributeExpression(attrValue);
          code += `    ${varReference}.setAttribute('${attrName}', ${expression});
  `;

          // Cache nodes for reactive updates
          propNames.forEach(propName => {
            if (!cachedNodes[propName]) cachedNodes[propName] = [];
            cachedNodes[propName].push({
              type: 'attribute',
              elementVarName: varReference.replace(/^this\./, ''),
              attrName: attrName,
              expression: generateAttributeExpression(attrValue).expression,
            });
          });
        } else if (attrName.startsWith('on')) {
          // Event listener
          const event = attrName.substring(2);
          const handlerName = attrValue.replace(/\(\)$/, '').trim();
          eventListeners.push({ elementVarName: varReference.replace(/^this\./, ''), event, handlerName });
        } else {
          // For other attributes
          code += `    ${varReference}.setAttribute('${attrName}', '${attrValue}');
  `;
        }
      }

      // Append to parent
      const parentRef = parentVarName ? parentVarName : 'fragment';
      code += `    ${parentRef}.appendChild(${varReference});
  `;

      // Traverse children
      if (node.children &amp;&amp; node.children.length) {
        for (let child of node.children) {
          traverse(child, varReference);
        }
      }
    } else if (node.type === 'text') {
      const textContent = node.data;

      if (textContent.trim()) {
        // Handle text nodes with expressions
        const { expression, propNames } = generateTextExpression(textContent);

        const varName = 'textNode' + ++varCounter;

        // Decide whether to assign to 'this.' or 'const'
        let declaration;
        if (expression.includes('this._')) {
          declaration = `this.${varName}`;
        } else {
          declaration = `const ${varName}`;
        }

        const varReference = declaration.replace(/^const /, '');
        code += `    ${declaration} = document.createTextNode(${expression});
  `;
        code += `    ${parentVarName}.appendChild(${varReference});
  `;

        // Cache nodes for reactive updates
        propNames.forEach(propName => {
          if (!cachedNodes[propName]) cachedNodes[propName] = [];
          cachedNodes[propName].push({
            type: 'text',
            varName: varReference.replace(/^this\./, ''),
            expression: generateTextExpression(textContent).expression,
          });
        });
      }
    }
  }

  function needsReference(node) {
    // Determines if the element needs to be assigned to 'this.'
    // Elements that are:
    // - Targets of event listeners
    // - Contain reactive expressions
    // Need to be accessible outside of _buildDOM
    if (node.attribs) {
      const hasEventListener = Object.keys(node.attribs).some(attr => attr.startsWith('on'));
      const hasReactiveAttr = Object.values(node.attribs).some(value => /\{([\w$]+)\}/.test(value));
      if (hasEventListener || hasReactiveAttr) {
        return true;
      }
    }

    if (node.children &amp;&amp; node.children.some(child => child.type === 'text' &amp;&amp; /\{([\w$]+)\}/.test(child.data))) {
      return true;
    }

    return false;
  }

  function generateTextExpression(textContent) {
    const exprRegex = /\{([\w$]+)\}/g;
    let segments = [];
    let propNames = [];
    let lastIndex = 0;
    let match;

    while ((match = exprRegex.exec(textContent)) !== null) {
      if (match.index > lastIndex) {
        segments.push(JSON.stringify(textContent.slice(lastIndex, match.index)));
      }
      segments.push(`this._${match[1]}`);
      propNames.push(match[1]);
      lastIndex = exprRegex.lastIndex;
    }

    if (lastIndex < textContent.length) {
      segments.push(JSON.stringify(textContent.slice(lastIndex)));
    }

    return {
      expression: segments.join(' + '),
      propNames,
    };
  }

  function generateAttributeExpression(attrValue) {
    const exprRegex = /\{([\w$]+)\}/g;
    let segments = [];
    let propNames = [];
    let lastIndex = 0;
    let match;

    while ((match = exprRegex.exec(attrValue)) !== null) {
      if (match.index > lastIndex) {
        segments.push(JSON.stringify(attrValue.slice(lastIndex, match.index)));
      }
      segments.push(`this._${match[1]}`);
      propNames.push(match[1]);
      lastIndex = exprRegex.lastIndex;
    }

    if (lastIndex < attrValue.length) {
      segments.push(JSON.stringify(attrValue.slice(lastIndex)));
    }

    return {
      expression: segments.join(' + '),
      propNames,
    };
  }

  dom.forEach(node => traverse(node, null));

  return { code, cachedNodes, eventListeners };
}

module.exports = {
  parseComponent,
  parseScript,
  toPascalCase,
  escapeBackticks,
  generateClassCode,
  transformMethodBody,
  generateDOMCode,
  sanitizeVariableName // Exported for reuse in page.js
};
```

```page.js
// cat/src/page.js

const fs = require('fs-extra');
const path = require('path');
const acorn = require('acorn'); // Import Acorn for JavaScript parsing
const { parseDocument } = require('htmlparser2');
const { generateDOMCode, transformMethodBody, parseScript, sanitizeVariableName } = require('./component'); // Reuse functions from component.js

/**
 * Parse a page file to extract route, HTML, script, and style sections.
 * @param {string} filePath - Path to the .page.html file.
 * @returns {Promise<{ route: string, html: string, script: string, style: string }>} - Page details.
 */
async function parsePageComponent(filePath) {
  const content = await fs.readFile(filePath, 'utf-8');

  // Extract the <page> tag with route attribute
  const pageRegex = /<page\s+[^>]*route=[&quot;']([^&quot;']+)[&quot;'][^>]*>([\s\S]*?)<\/page>/;
  const pageMatch = content.match(pageRegex);

  if (!pageMatch) {
    throw new Error(`Invalid page structure or missing route attribute in ${path.basename(filePath)}`);
  }

  const route = pageMatch[1];
  let innerContent = pageMatch[2];

  // Extract all <script> sections
  const scriptRegex = /<script>([\s\S]*?)<\/script>/g;
  let scriptContent = '';
  let scriptMatch;
  while ((scriptMatch = scriptRegex.exec(content)) !== null) {
    scriptContent += scriptMatch[1].trim() + '\n';
  }

  // Extract all <style> sections
  const styleRegex = /<style>([\s\S]*?)<\/style>/g;
  let styleContent = '';
  let styleMatch;
  while ((styleMatch = styleRegex.exec(content)) !== null) {
    styleContent += styleMatch[1].trim() + '\n';
  }

  // Remove all <script> and <style> tags from innerContent
  innerContent = innerContent
    .replace(scriptRegex, '')
    .replace(styleRegex, '')
    .trim();

  return {
    route,
    html: innerContent,
    script: scriptContent,
    style: styleContent,
  };
}

/**
 * Generate the class code for the page.
 * @param {object} page - Page details.
 * @returns {string} - The compiled class code.
 */
function generatePageClassCode({ className, html, style, properties, methods }) {
  let classCode = `class ${className} {
      constructor() {
    `;

  // Initialize properties
  properties.forEach(prop => {
    classCode += `    this._${prop.name} = ${prop.value};
    `;
  });

  classCode += `
        this._element = null;
        this._cachedNodes = {};
        this._eventListeners = [];
        this._buildDOM();
      }

      _buildDOM() {
        const fragment = document.createDocumentFragment();
    `;

  // Generate DOM creation code
  const { code: domCode, cachedNodes, eventListeners } = generateDOMCode(html);
  classCode += domCode;

  classCode += `
        this._element = fragment;
      }
    `;

  // Generate getters and setters
  if (cachedNodes) {
    Object.keys(cachedNodes).forEach(propName => {
      const nodes = cachedNodes[propName];

      classCode += `
      get ${propName}() { return this._${propName}; }
      set ${propName}(value) {
        if (this._${propName} !== value) {
          this._${propName} = value;
    `;

      nodes.forEach(node => {
        if (node.type === 'text') {
          classCode += `      this.${node.varName}.textContent = ${node.expression};
    `;
        } else if (node.type === 'attribute') {
          classCode += `      this.${node.elementVarName}.setAttribute('${node.attrName}', ${node.expression});
    `;
        }
      });

      classCode += `    }
      }
    `;
    });
  }

  // Add methods
  methods.forEach(method => {
    const transformedBody = transformMethodBody(method.body, properties.map(p => p.name));
    classCode += `
      ${method.name}(${method.params}) {
    ${transformedBody}
      }
    `;
  });

  // Add mount and unmount methods
  classCode += `
      mount(container) {
        if (!this._element) {
          this._buildDOM();
        }
        // Clear the container and append the page content
        container.innerHTML = '';
        container.appendChild(this._element);
  
        // Attach event listeners
    `;

  if (eventListeners &amp;&amp; eventListeners.length > 0) {
    eventListeners.forEach(listener => {
      classCode += `      this.${listener.elementVarName}.addEventListener('${listener.event}', this.${listener.handlerName}.bind(this));
    `;
    });
  }

  classCode += `
      }

      unmount() {
        if (this._element &amp;&amp; this._element.parentNode) {
          // Remove event listeners
    `;

  if (eventListeners &amp;&amp; eventListeners.length > 0) {
    eventListeners.forEach(listener => {
      classCode += `        this.${listener.elementVarName}.removeEventListener('${listener.event}', this.${listener.handlerName}.bind(this));
    `;
    });
  }

  classCode += `
          // Remove the element from the container
          // Since we're clearing the container's innerHTML in mount, this may not be necessary
        }
      }
    `;

  classCode += `}
  `;

  return classCode;
}

/**
 * Generate the Router class code.
 * @param {Map<string, {className: string, classCode: string}>} pageClassMap - Map of route to page class details.
 * @returns {string} - The Router class code.
 */
function generateRouterClassCode(pageClassMap) {
  // Generate list of routes and page class names
  let routesArray = [];

  pageClassMap.forEach(({ className }, route) => {
    routesArray.push(`{ route: '${route}', pageClass: ${className} }`);
  });

  const routesList = `[${routesArray.join(', ')}]`;

  let routerClassCode = `
class Router {
  constructor() {
    this.routes = ${routesList};
    this.containers = {}; // Cache for load containers
    this.pageInstances = {}; // Cache for mounted page instances per container
    document.addEventListener('DOMContentLoaded', () => {
      this.initializeLoadContainers();
      this.setupRouteHandlers();
      this.loadDefaultContent();
    });
  }

  initializeLoadContainers() {
    const loadTags = document.querySelectorAll('load');
    loadTags.forEach(loadTag => {
      const loadName = loadTag.getAttribute('name');
      const route = loadTag.getAttribute('route');
      if (loadName) {
        // This load acts as a wrapper
        const wrapper = document.createElement('div');
        wrapper.setAttribute('data-load-name', loadName);
        loadTag.replaceWith(wrapper);
        this.containers[loadName] = wrapper;

        // If route is specified, load the page into the wrapper
        if (route) {
          this.loadContentIntoContainer(route, loadName);
        }
      } else if (route) {
        // This load should be replaced immediately by the page content
        const routeEntry = this.routes.find(r => r.route === route);
        if (routeEntry) {
          const pageInstance = new routeEntry.pageClass();
          pageInstance._element = null; // Ensure the DOM is built fresh
          pageInstance._buildDOM();
          loadTag.replaceWith(pageInstance._element);
        } else {
          console.warn(\`No page found for route &quot;\${route}&quot;\`);
        }
      } else {
        console.warn('<load> tag must have either a name or a route attribute.');
      }
    });
  }

  setupRouteHandlers() {
    const routeElements = document.querySelectorAll('[route][load]');
    routeElements.forEach(element => {
      element.addEventListener('click', (event) => {
        event.preventDefault();
        const route = element.getAttribute('route');
        const loadName = element.getAttribute('load');
        this.loadContentIntoContainer(route, loadName);
        this.updateCurrentAttribute(element, loadName);
      });
    });
  }

  loadContentIntoContainer(route, loadName) {
    const container = this.containers[loadName];
    if (!container) {
      console.warn(\`No container found with name &quot;\${loadName}&quot;\`);
      return;
    }

    const routeEntry = this.routes.find(r => r.route === route);
    if (routeEntry) {
      // Unmount previous page instance if exists
      const prevInstance = this.pageInstances[loadName];
      if (prevInstance) {
        prevInstance.unmount();
      }
      const pageInstance = new routeEntry.pageClass();
      pageInstance.mount(container);
      this.pageInstances[loadName] = pageInstance;
    } else {
      console.warn(\`No page found for route &quot;\${route}&quot;\`);
    }
  }

  loadDefaultContent() {
    // For each container, find the element with 'current' attribute
    for (const loadName in this.containers) {
      const container = this.containers[loadName];
      const currentElement = document.querySelector(\`[route][load=&quot;\${loadName}&quot;][current]\`);
      if (currentElement) {
        const route = currentElement.getAttribute('route');
        this.loadContentIntoContainer(route, loadName);
      } else if (!container.innerHTML.trim()) {
        // If container is empty and no current element, you may define a default route
      }
    }
  }

  updateCurrentAttribute(clickedElement, loadName) {
    // Remove 'current' attribute from all elements with the same loadName
    const elements = document.querySelectorAll(\`[route][load=&quot;\${loadName}&quot;]\`);
    elements.forEach(el => {
      el.removeAttribute('current');
    });

    // Add 'current' attribute to the clicked element
    clickedElement.setAttribute('current', '');
  }
}

const appRouter = new Router();
`;

  return routerClassCode;
}

module.exports = {
  parsePageComponent,
  parseScript,
  generatePageClassCode,
  generateRouterClassCode
};
```

Current Issue: There are issues with the `<load>` tag, including incorrect compilation and non-functional behavior.

Context:
The `<load>` tag serves two main purposes:
1. As an instruction to the Router to replace itself with the content of the page targeted by the `route` attribute.
   - For this functionality, the `<load>` tag should only have the `route` attribute and must not include a `name` attribute.
   - Example usage:
     ```html
     index.html
     <load route="/hello/world" />
     ```
   - After Router execution:
     ```html
     index.html
     <h1> Hello world </h1>
     ```

2. As a wrapper that dynamically loads page content within itself.
   - This mode is used for switching between pages dynamically.
   - To function as a wrapper or switcher, the `<load>` tag must include a `name` attribute, which defines its behavior.
   - Pages intended to load inside the wrapper are specified by elements using both `route` and `load` attributes.
   - The `load` attribute targets a `<load name="...">` tag with the corresponding name.
   - When a user interacts with an element using these attributes, it triggers the `_buildDOM` function to populate the wrapper with the specified page's content.
   - If an element with `route` and `load` attributes also includes a `current` attribute, it indicates to the Router that this page should be the default or the next to render.
   - Example usage:
     ```html
     index.html
     <div load="container" route="/counters" current>Counters</div>
     <div load="container" route="/settings">Settings</div>
     <load name="container" />
     ```
   - After Router execution:
     ```html
     index.html
     <div>
       <!-- The `<load>` tag is replaced by the Router with a `<div>` wrapper, utilizing cached nodes to minimize attribute setup. -->
       <my-counter>...</my-counter>
     </div>
     ```

These adjustments clarify the proper usage and expected behaviors of the `<load>` tag in different contexts. Evaluate the current code, and from there integrate this behavior, make sure everything it's wired correctly, and that works as described on the context. Output the updated files, without cuts, or abbreviations.