From 3e5b4fc30498860e5c7813056918e4f468017eb9 Mon Sep 17 00:00:00 2001 From: gtom Date: Tue, 23 Jun 2026 22:51:55 +0200 Subject: [PATCH] webui: Render hex strings using IdentifierComponent in json-tree Implements automatic detection of hex strings within the JSON tree viewer and uses the `app-identifier` component to format them (e.g., with ASCII/text decoding). This improves the readability of Kea DHCP hex values, such as options payloads or flex-id, etc. - Added `isHexString()` detection logic to JsonTreeComponent. - Imported and embedded IdentifierComponent into json-tree templates. - Added unit tests for hexadecimal pattern matching. --- .../app/json-tree/json-tree.component.html | 11 +++++-- .../app/json-tree/json-tree.component.spec.ts | 30 +++++++++++++++++++ .../src/app/json-tree/json-tree.component.ts | 22 +++++++++++++- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/webui/src/app/json-tree/json-tree.component.html b/webui/src/app/json-tree/json-tree.component.html index 5e4f54ebe..2f86bd845 100644 --- a/webui/src/app/json-tree/json-tree.component.html +++ b/webui/src/app/json-tree/json-tree.component.html @@ -91,9 +91,14 @@ }" > - {{ - value + '' - }} + + + + + + {{ value + '' }} + + diff --git a/webui/src/app/json-tree/json-tree.component.spec.ts b/webui/src/app/json-tree/json-tree.component.spec.ts index 50f2c36b0..de7de715b 100644 --- a/webui/src/app/json-tree/json-tree.component.spec.ts +++ b/webui/src/app/json-tree/json-tree.component.spec.ts @@ -763,4 +763,34 @@ describe('JsonTreeComponent-ExternalTemplates', () => { const content = nativeElement.textContent expect(content).toBe('biz') }) + + + describe('hex to ascii', () => { + it('should correctly identify hex strings', () => { + component.value = null + expect(component.isHexString()).toBeFalse() + + component.value = '123' + expect(component.isHexString()).toBeFalse() + + component.value = '1234' + expect(component.isHexString()).toBeFalse() + + component.value = '0x1234' + expect(component.isHexString()).toBeTrue() + + component.value = 'abcdef' + expect(component.isHexString()).toBeTrue() + + // Hex string from kea dhcp + component.value = '00020000000005830100000038383A32383A66623A35663A38353A32630000' + expect(component.isHexString()).toBeTrue() + + // Decimal looking string should not be considered hex unless prefixed + component.value = '1928374612341234' + expect(component.isHexString()).toBeFalse() + }) + + + }) }) diff --git a/webui/src/app/json-tree/json-tree.component.ts b/webui/src/app/json-tree/json-tree.component.ts index 7b5d8312c..87a7ef517 100644 --- a/webui/src/app/json-tree/json-tree.component.ts +++ b/webui/src/app/json-tree/json-tree.component.ts @@ -2,6 +2,7 @@ import { KeyValue, NgIf, NgClass, NgTemplateOutlet, NgFor, SlicePipe, KeyValuePi import { Component, Input, TemplateRef } from '@angular/core' import { Paginator } from 'primeng/paginator' import { InputText } from 'primeng/inputtext' +import { IdentifierComponent } from '../identifier/identifier.component' /** * Typing for page changed event of PrimeNG navigation. @@ -31,7 +32,7 @@ interface PageChangedEvent { selector: 'app-json-tree', templateUrl: './json-tree.component.html', styleUrls: ['./json-tree.component.sass'], - imports: [NgIf, NgClass, NgTemplateOutlet, NgFor, Paginator, InputText, SlicePipe, KeyValuePipe], + imports: [NgIf, NgClass, NgTemplateOutlet, NgFor, Paginator, InputText, SlicePipe, KeyValuePipe, IdentifierComponent], }) export class JsonTreeComponent { private _value: any = null @@ -616,4 +617,23 @@ export class JsonTreeComponent { areChildrenLoading() { return this._childrenLoading } + + /** + * Determines whether the evaluated value is a hexadecimal string. + * + * It checks if it contains only hexadecimal characters, its length is + * even and greater than 0. The value can contain an optional '0x' prefix. + */ + isHexString(): boolean { + if (!this.isString()) { + return false + } + const hex = this._value.replace(/^0x/i, '') + // Exclude strings that are just decimal numbers unless they start with 0x + if (!/^0x/i.test(this._value) && /^\d+$/.test(hex)) { + return false + } + // At least 4 characters long (2 hex bytes) to reduce false positives + return hex.length > 3 && hex.length % 2 === 0 && /^[0-9a-fA-F]+$/.test(hex) + } }