or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-usage.mdcore-parsing.mddom-visualization.mdformat-support.mdindex.mdstream-processing.md
tile.json

dom-visualization.mddocs/

0

# DOM Visualization

1

2

Browser-specific functionality for creating interactive ASN.1 structure visualizations with DOM elements and context menus.

3

4

## Capabilities

5

6

### ASN1DOM Class

7

8

Extended ASN.1 parser with DOM rendering capabilities for web browsers, providing interactive tree views of ASN.1 structures.

9

10

```javascript { .api }

11

/**

12

* ASN.1 parser with DOM rendering capabilities

13

* Extends ASN1 class with browser-specific visualization methods

14

*/

15

class ASN1DOM extends ASN1 {

16

/**

17

* Generate DOM element representation of ASN.1 structure

18

* Creates an interactive tree view with expandable/collapsible nodes

19

* @param spaces - Indentation string for formatting (optional)

20

* @returns HTML list item element representing the ASN.1 structure

21

*/

22

toDOM(spaces?: string): HTMLLIElement;

23

24

/**

25

* Generate hexadecimal DOM display with formatting and highlighting

26

* @param start - Starting position for hex display (optional)

27

* @param trimmedHex - Whether to trim hex display for large content (optional)

28

* @returns HTML element containing formatted hex dump

29

*/

30

toHexDOM(start?: number, trimmedHex?: boolean): HTMLElement;

31

}

32

```

33

34

**Usage Examples:**

35

36

```javascript

37

import { ASN1DOM } from '@lapo/asn1js/dom.js';

38

import { Base64 } from '@lapo/asn1js/base64.js';

39

40

// Parse certificate and create DOM visualization

41

const certPem = `-----BEGIN CERTIFICATE-----

42

MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3YkQOL4OqPlzJGPbhUKZ

43

...

44

-----END CERTIFICATE-----`;

45

46

const certData = Base64.unarmor(certPem);

47

const cert = ASN1DOM.decode(certData);

48

49

// Create DOM tree view

50

const treeContainer = document.getElementById('asn1-tree');

51

const ul = document.createElement('ul');

52

ul.className = 'treecollapse';

53

ul.appendChild(cert.toDOM());

54

treeContainer.appendChild(ul);

55

56

// Create hex dump view

57

const hexContainer = document.getElementById('hex-dump');

58

hexContainer.appendChild(cert.toHexDOM(undefined, true));

59

60

// Access the ASN1 object from DOM elements

61

ul.addEventListener('click', (event) => {

62

const listItem = event.target.closest('li');

63

if (listItem && listItem.asn1) {

64

console.log('Clicked ASN.1 element:', listItem.asn1.typeName());

65

console.log('Content:', listItem.asn1.content(100));

66

}

67

});

68

```

69

70

### Context Menu Integration

71

72

Utility function for binding context menus to ASN.1 DOM elements.

73

74

```javascript { .api }

75

/**

76

* Bind context menu functionality to DOM nodes

77

* Adds right-click context menu with ASN.1-specific options

78

* @param node - DOM node to bind context menu to

79

*/

80

function bindContextMenu(node: HTMLElement): void;

81

```

82

83

**Usage Examples:**

84

85

```javascript

86

import { ASN1DOM } from '@lapo/asn1js/dom.js';

87

import { bindContextMenu } from '@lapo/asn1js/context.js';

88

import { Hex } from '@lapo/asn1js/hex.js';

89

90

// Create ASN.1 structure with context menu

91

const data = Hex.decode('300C06032B6570050000');

92

const asn1 = ASN1DOM.decode(data);

93

94

const domElement = asn1.toDOM();

95

bindContextMenu(domElement);

96

97

// Add to page

98

document.body.appendChild(domElement);

99

100

// Context menu will provide options like:

101

// - Copy hex value

102

// - Copy base64 value

103

// - Show OID description (for OID elements)

104

// - Export structure

105

```

106

107

### Complete Web Interface Example

108

109

Example showing how to build a complete ASN.1 viewer web interface.

110

111

```javascript

112

import { ASN1DOM } from '@lapo/asn1js/dom.js';

113

import { Base64 } from '@lapo/asn1js/base64.js';

114

import { Hex } from '@lapo/asn1js/hex.js';

115

import { bindContextMenu } from '@lapo/asn1js/context.js';

116

117

class ASN1Viewer {

118

constructor(containerElement) {

119

this.container = containerElement;

120

this.setupUI();

121

}

122

123

setupUI() {

124

this.container.innerHTML = `

125

<div class="asn1-viewer">

126

<div class="controls">

127

<textarea id="input" placeholder="Paste PEM, Base64, or Hex data here..."></textarea>

128

<button id="decode">Decode</button>

129

<button id="clear">Clear</button>

130

</div>

131

<div class="output">

132

<div id="tree-view" class="tree-container"></div>

133

<div id="hex-view" class="hex-container"></div>

134

</div>

135

</div>

136

`;

137

138

this.inputArea = this.container.querySelector('#input');

139

this.treeView = this.container.querySelector('#tree-view');

140

this.hexView = this.container.querySelector('#hex-view');

141

142

this.container.querySelector('#decode').onclick = () => this.decode();

143

this.container.querySelector('#clear').onclick = () => this.clear();

144

}

145

146

decode() {

147

try {

148

const input = this.inputArea.value.trim();

149

if (!input) return;

150

151

let binaryData;

152

153

// Auto-detect format

154

if (/^[0-9A-Fa-f\s]+$/.test(input)) {

155

binaryData = Hex.decode(input);

156

} else {

157

binaryData = Base64.unarmor(input);

158

}

159

160

const asn1 = ASN1DOM.decode(binaryData);

161

this.displayStructure(asn1);

162

163

} catch (error) {

164

this.showError(error.message);

165

}

166

}

167

168

displayStructure(asn1) {

169

// Clear previous content

170

this.treeView.innerHTML = '';

171

this.hexView.innerHTML = '';

172

173

// Create tree view

174

const ul = document.createElement('ul');

175

ul.className = 'treecollapse';

176

const li = asn1.toDOM();

177

bindContextMenu(li);

178

ul.appendChild(li);

179

this.treeView.appendChild(ul);

180

181

// Create hex view

182

const hexElement = asn1.toHexDOM(undefined, true);

183

this.hexView.appendChild(hexElement);

184

185

// Add click handlers for tree navigation

186

this.addTreeInteractivity(ul);

187

}

188

189

addTreeInteractivity(treeElement) {

190

treeElement.addEventListener('click', (event) => {

191

const target = event.target;

192

193

// Toggle collapse/expand

194

if (target.classList.contains('toggle')) {

195

const li = target.closest('li');

196

li.classList.toggle('collapsed');

197

event.stopPropagation();

198

return;

199

}

200

201

// Highlight selected element

202

treeElement.querySelectorAll('li.selected').forEach(el => {

203

el.classList.remove('selected');

204

});

205

206

const li = target.closest('li');

207

if (li && li.asn1) {

208

li.classList.add('selected');

209

this.showElementDetails(li.asn1);

210

}

211

});

212

}

213

214

showElementDetails(asn1) {

215

// Show detailed information about the selected element

216

const details = {

217

type: asn1.typeName(),

218

position: `${asn1.posStart()}-${asn1.posEnd()}`,

219

length: asn1.length,

220

content: asn1.content(200)

221

};

222

223

console.log('Selected ASN.1 element:', details);

224

225

// Could update a details panel in the UI

226

// this.updateDetailsPanel(details);

227

}

228

229

showError(message) {

230

this.treeView.innerHTML = `<div class="error">Error: ${message}</div>`;

231

this.hexView.innerHTML = '';

232

}

233

234

clear() {

235

this.inputArea.value = '';

236

this.treeView.innerHTML = '';

237

this.hexView.innerHTML = '';

238

}

239

}

240

241

// Usage

242

const viewerContainer = document.getElementById('asn1-viewer-container');

243

const viewer = new ASN1Viewer(viewerContainer);

244

```

245

246

### CSS Styling for ASN.1 DOM Elements

247

248

Recommended CSS classes for styling ASN.1 DOM visualizations.

249

250

```css

251

/* Tree view styling */

252

.treecollapse {

253

font-family: monospace;

254

font-size: 12px;

255

list-style: none;

256

padding-left: 0;

257

}

258

259

.treecollapse li {

260

margin: 2px 0;

261

padding-left: 16px;

262

position: relative;

263

}

264

265

.treecollapse li:before {

266

content: "▼";

267

position: absolute;

268

left: 0;

269

cursor: pointer;

270

color: #666;

271

}

272

273

.treecollapse li.collapsed:before {

274

content: "▶";

275

}

276

277

.treecollapse li.collapsed > ul {

278

display: none;

279

}

280

281

/* ASN.1 element styling */

282

.head {

283

cursor: pointer;

284

}

285

286

.head:hover {

287

background-color: #f0f0f0;

288

}

289

290

.selected .head {

291

background-color: #e6f3ff;

292

}

293

294

/* Type and content styling */

295

.name.id {

296

color: #0066cc;

297

font-weight: bold;

298

}

299

300

.name.type {

301

color: #006600;

302

}

303

304

.preview {

305

color: #666;

306

font-style: italic;

307

}

308

309

.oid.description {

310

color: #8b4513;

311

font-size: 11px;

312

}

313

314

/* Hex view styling */

315

.hex-container {

316

font-family: monospace;

317

font-size: 11px;

318

white-space: pre;

319

background-color: #f8f8f8;

320

padding: 10px;

321

border: 1px solid #ddd;

322

overflow: auto;

323

}

324

325

.hex-address {

326

color: #666;

327

}

328

329

.hex-bytes {

330

color: #000;

331

}

332

333

.hex-ascii {

334

color: #0066cc;

335

}

336

337

/* Error styling */

338

.error {

339

color: #cc0000;

340

background-color: #ffe6e6;

341

padding: 10px;

342

border: 1px solid #cc0000;

343

border-radius: 4px;

344

}

345

```