render method

Future<void> render()

Implementation

Future<void> render() async {
  String tpl = await template;

  // Content Slot (modificado para preservar el contenido)
  tpl = tpl.replaceAllMapped(
    RegExp(r'<@View\s*/>'),
    (match) => '<div data-slot="content"></div>',
  );

  // Inserciones
  tpl = tpl.replaceAllMapped(
    RegExp(
      r'<([A-Z][A-Za-z0-9_-]*)((?:\s+[a-zA-Z0-9_-]+(?:="[^"]*"|\{\{[^}]*\}\})?)*)?\s*\/>',
    ),
    (match) {
      final componentName = match.group(1)!;
      final propsString = match.group(2) ?? '';

      // Extraer props del string de atributos
      final extractedProps = <String, String>{};
      final propsRegex = RegExp(
        r'([a-zA-Z0-9_-]+)(?:="([^"]*)"|=(\{\{[^}]*\}\}))?',
      );

      for (final prop in propsRegex.allMatches(propsString)) {
        final name = prop.group(1)!;
        final value = prop.group(2) ?? prop.group(3) ?? '';
        extractedProps[name] = value;
      }

      // Crear el div con data-insert y los props extraídos
      final attrs = extractedProps.entries
          .map((e) => '${e.key}="${e.value}"')
          .join(' ');

      return '<div data-insert="$componentName" $attrs></div>';
    },
  );

  final Template jinjaTemplate = jinjaEnv.fromString(tpl);
  final String processedTemplate = jinjaTemplate.render(renderContext);
  host.setHTMLUnsafe(processedTemplate.toJS);

  // CSS por clase (usando _safeId)
  final String? css = await style;
  if (css != null && css.isNotEmpty) {
    final String styleId = "style-${_safeId(runtimeType.toString())}";
    if (document.head?.querySelector("#$styleId") == null) {
      final HTMLStyleElement styleElement = HTMLStyleElement()
        ..id = styleId
        ..textContent = css;
      document.head?.append(styleElement);
    }
  }

  // Manejar slots con contenido
  if (props.containsKey('content')) {
    final Element? contentSlot = host.querySelector('[data-slot="content"]');
    if (contentSlot != null) {
      // ignore: invalid_runtime_check_with_js_interop_types
      if (props['content'] is HTMLElement) {
        contentSlot.replaceWith(props['content'] as HTMLElement);
      }
    }
  }

  // Otros slots
  final Map<String, dynamic> values = Map<String, dynamic>.from(props);
  values.remove('content'); // Ya manejamos el slot de contenido
  values.forEach((String key, dynamic value) {
    // ignore: invalid_runtime_check_with_js_interop_types
    if (value is HTMLElement) {
      final Element? placeholder = host.querySelector('[data-slot="$key"]');
      if (placeholder != null) placeholder.replaceWith(value);
    }
  });

  _bindEvents();
  await _resolveInserts();
  afterRender();
}