Markdown Converter
Agent skill for markdown-converter
This project contains a Home Assistant Lovelace card that implements press-and-hold functionality with a flexible action system.
Sign in to like and favorite skills
This project contains a Home Assistant Lovelace card that implements press-and-hold functionality with a flexible action system.
Type: Home Assistant Custom Lovelace Card Framework: LitElement (Lit 2.0) with TypeScript Build System: Rollup with TypeScript plugin Package Manager: pnpm Target: Home Assistant Frontend Integration
The card implements a domain-aware action system that automatically selects appropriate default actions:
button.press service (not toggle)Users can override default behavior with four action types:
custom-card-helpers for proper action dispatchingsrc/ ├── press-and-hold-button-card.ts # Main card component ├── press-and-hold-button-card-editor.ts # Configuration UI editor ├── constants.ts # Default configuration values └── build-info.ts # Build timestamp injection dist/ └── hacs-nerdo-ux.js # Built output for Home Assistant test.html # Standalone test environment
handleActionhandleActionThe editor uses dynamic schema building to show/hide fields based on action selection:
call-service actiondist/hacs-nerdo-ux.js)pnpm run buildexecuteAction() methodcss template literaltest.html for immediate feedbackThe
test.html file provides a complete standalone testing environment that simulates the Home Assistant frontend without requiring a full HA installation. This is essential for rapid development and debugging.
hass object simulation with entity statesSince the card uses Shadow DOM (LitElement), testing the button requires accessing the shadow root:
test.html in browser// Get the card element const card = document.getElementById('testCard'); // Access the button through shadow DOM const button = card.shadowRoot.querySelector('.button'); // Simulate pointer down event const pointerDownEvent = new PointerEvent('pointerdown', { pointerId: 1, clientX: 947, clientY: 888, bubbles: true }); button.dispatchEvent(pointerDownEvent); // Wait for hold duration, then trigger pointer up setTimeout(() => { const pointerUpEvent = new PointerEvent('pointerup', { pointerId: 1, clientX: 947, clientY: 888, bubbles: true }); button.dispatchEvent(pointerUpEvent); }, 1200); // Wait longer than hold duration
The project uses Playwright for automated testing:
// Navigate to test page await page.goto('file:///path/to/test.html'); // Access shadow DOM and simulate press-hold await page.evaluate(() => { const card = document.getElementById('testCard'); const button = card.shadowRoot.querySelector('.button'); // Dispatch pointer events button.dispatchEvent(new PointerEvent('pointerdown', { pointerId: 1, clientX: 947, clientY: 888, bubbles: true })); setTimeout(() => { button.dispatchEvent(new PointerEvent('pointerup', { pointerId: 1, clientX: 947, clientY: 888, bubbles: true })); }, 1200); });
The test environment includes various entity types:
// Button entity (tests smart default press action) 'button.ratgdo_door': { entity_id: 'button.ratgdo_door', state: 'idle', attributes: { friendly_name: 'Ratgdo Door Button', icon: 'mdi:garage-variant' } } // Switch entity (tests toggle action) 'switch.test': { entity_id: 'switch.test', state: 'off', attributes: { friendly_name: 'Test Switch', icon: 'mdi:lightbulb' } }
// Mock callService function handles all Home Assistant service calls callService: function(domain, service, data) { data = data || {}; // Null safety for console error prevention const entityId = data.entity_id || data.entity; // Log the service call log(`Called service: ${domain}.${service} on ${entityId || 'no entity'}`); // Update mock entity states based on service // Supports press, toggle, turn_on, turn_off, etc. }
// Intercepts handleAction calls from custom-card-helpers window.handleAction = function(element, hass, config, actionType) { // Parse action configuration and execute appropriate mock behavior // Supports all action types: toggle, call-service, more-info }
light.turn_on with JSON dataThe mock environment has been hardened to prevent console errors:
callService function: data = data || {}data.entity_id || data.entityThis guide provides context for future development and maintenance of the press-and-hold button card system.