or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

attributes-properties.mddom-elements.mdindex.mdnode-types.mdparsing.mdquery-selection.md

query-selection.mddocs/

0

# Query & Selection

1

2

Powerful element querying capabilities using CSS selectors, tag names, IDs, and DOM traversal methods for finding and navigating HTML elements within the parsed DOM tree.

3

4

## Capabilities

5

6

### CSS Selector Queries

7

8

Query elements using standard CSS selector syntax with support for classes, IDs, attributes, and combinators.

9

10

```typescript { .api }

11

/** Find first element matching CSS selector */

12

querySelector(selector: string): HTMLElement | null;

13

14

/** Find all elements matching CSS selector */

15

querySelectorAll(selector: string): HTMLElement[];

16

```

17

18

**Supported CSS Selectors:**

19

20

- **Type selectors**: `div`, `p`, `span`

21

- **Class selectors**: `.class-name`, `.multiple.classes`

22

- **ID selectors**: `#element-id`

23

- **Attribute selectors**: `[attr]`, `[attr=value]`, `[attr*=value]`

24

- **Descendant combinators**: `div p`, `.parent .child`

25

- **Child combinators**: `div > p`

26

- **Adjacent sibling**: `h1 + p`

27

- **Pseudo-selectors**: `:first-child`, `:last-child`, `:nth-child()`

28

29

**Usage Examples:**

30

31

```typescript

32

import { parse } from "node-html-parser";

33

34

const html = `

35

<div class="container">

36

<header id="main-header">

37

<h1>Title</h1>

38

<nav class="menu">

39

<ul>

40

<li><a href="/home">Home</a></li>

41

<li><a href="/about" class="active">About</a></li>

42

</ul>

43

</nav>

44

</header>

45

<main>

46

<p class="intro">Introduction text</p>

47

<article data-id="123">

48

<h2>Article Title</h2>

49

<p>Article content</p>

50

</article>

51

</main>

52

</div>`;

53

54

const root = parse(html);

55

56

// Basic selectors

57

const header = root.querySelector('#main-header');

58

const intro = root.querySelector('.intro');

59

const articles = root.querySelectorAll('article');

60

61

// Compound selectors

62

const activeLink = root.querySelector('a.active');

63

const navLinks = root.querySelectorAll('nav a');

64

65

// Attribute selectors

66

const dataElement = root.querySelector('[data-id]');

67

const specificData = root.querySelector('[data-id="123"]');

68

69

// Descendant selectors

70

const headerTitle = root.querySelector('header h1');

71

const listItems = root.querySelectorAll('ul li');

72

73

// Child selectors

74

const directChildren = root.querySelectorAll('.container > header');

75

76

// Multiple results

77

const allParagraphs = root.querySelectorAll('p');

78

allParagraphs.forEach(p => console.log(p.text));

79

```

80

81

### Element Queries by Tag

82

83

Find elements by their HTML tag name with wildcard support.

84

85

```typescript { .api }

86

/**

87

* Find all elements with specified tag name

88

* @param tagName - Tag name to search for, or '*' for all elements

89

* @returns Array of matching HTMLElements

90

*/

91

getElementsByTagName(tagName: string): HTMLElement[];

92

```

93

94

**Usage Examples:**

95

96

```typescript

97

const root = parse(`

98

<div>

99

<p>First paragraph</p>

100

<span>Span content</span>

101

<p>Second paragraph</p>

102

</div>

103

`);

104

105

// Find by specific tag

106

const paragraphs = root.getElementsByTagName('p');

107

console.log(paragraphs.length); // 2

108

109

// Find all elements

110

const allElements = root.getElementsByTagName('*');

111

console.log(allElements.length); // 4 (div, p, span, p)

112

113

// Case insensitive

114

const divs = root.getElementsByTagName('DIV');

115

console.log(divs.length); // 1

116

```

117

118

### Element Query by ID

119

120

Find a single element by its ID attribute.

121

122

```typescript { .api }

123

/**

124

* Find element with specified ID

125

* @param id - ID value to search for

126

* @returns HTMLElement with matching ID, or null if not found

127

*/

128

getElementById(id: string): HTMLElement | null;

129

```

130

131

**Usage Examples:**

132

133

```typescript

134

const root = parse(`

135

<div>

136

<header id="main-header">Header</header>

137

<section id="content">

138

<p id="intro">Introduction</p>

139

</section>

140

</div>

141

`);

142

143

const header = root.getElementById('main-header');

144

const intro = root.getElementById('intro');

145

const missing = root.getElementById('not-found'); // null

146

147

console.log(header?.tagName); // "HEADER"

148

console.log(intro?.text); // "Introduction"

149

```

150

151

### Ancestor Traversal

152

153

Find the closest ancestor element matching a CSS selector.

154

155

```typescript { .api }

156

/**

157

* Traverse up the DOM tree to find closest ancestor matching selector

158

* @param selector - CSS selector to match against ancestors

159

* @returns Closest matching ancestor HTMLElement, or null if none found

160

*/

161

closest(selector: string): HTMLElement | null;

162

```

163

164

**Usage Examples:**

165

166

```typescript

167

const root = parse(`

168

<article class="post">

169

<header>

170

<h1>Title</h1>

171

</header>

172

<div class="content">

173

<p>

174

<em id="emphasis">emphasized text</em>

175

</p>

176

</div>

177

</article>

178

`);

179

180

const emphasis = root.getElementById('emphasis');

181

182

// Find closest paragraph

183

const paragraph = emphasis.closest('p');

184

console.log(paragraph?.tagName); // "P"

185

186

// Find closest article

187

const article = emphasis.closest('article');

188

console.log(article?.classList.contains('post')); // true

189

190

// Find closest with class

191

const content = emphasis.closest('.content');

192

console.log(content?.tagName); // "DIV"

193

194

// No match

195

const missing = emphasis.closest('table'); // null

196

```

197

198

## Advanced Query Patterns

199

200

### Chaining Queries

201

202

Combine multiple query methods for complex element finding:

203

204

```typescript

205

const root = parse(`

206

<div class="app">

207

<nav class="sidebar">

208

<ul class="menu">

209

<li><a href="/dashboard" class="active">Dashboard</a></li>

210

<li><a href="/settings">Settings</a></li>

211

</ul>

212

</nav>

213

</div>

214

`);

215

216

// Chain queries

217

const activeLink = root

218

.querySelector('.sidebar')

219

?.querySelector('.menu')

220

?.querySelector('a.active');

221

222

console.log(activeLink?.text); // "Dashboard"

223

224

// Alternative approach

225

const menu = root.querySelector('.menu');

226

const activeItem = menu?.querySelector('.active');

227

```

228

229

### Iterating Query Results

230

231

Work with multiple elements returned by queries:

232

233

```typescript

234

const root = parse(`

235

<table>

236

<tr><td>Name</td><td>Age</td></tr>

237

<tr><td>Alice</td><td>25</td></tr>

238

<tr><td>Bob</td><td>30</td></tr>

239

</table>

240

`);

241

242

// Process all rows

243

const rows = root.querySelectorAll('tr');

244

rows.forEach((row, index) => {

245

const cells = row.querySelectorAll('td');

246

console.log(`Row ${index}:`, cells.map(cell => cell.text));

247

});

248

249

// Filter results

250

const dataCells = root.querySelectorAll('td');

251

const ages = dataCells

252

.filter(cell => !isNaN(Number(cell.text)))

253

.map(cell => Number(cell.text));

254

255

console.log('Ages:', ages); // [25, 30]

256

```

257

258

### Conditional Queries

259

260

Handle cases where elements might not exist:

261

262

```typescript

263

const root = parse('<div><p>Content</p></div>');

264

265

// Safe querying with optional chaining

266

const text = root.querySelector('section')?.querySelector('p')?.text ?? 'Default';

267

268

// Explicit null checks

269

const section = root.querySelector('section');

270

if (section) {

271

const paragraph = section.querySelector('p');

272

if (paragraph) {

273

console.log(paragraph.text);

274

}

275

}

276

277

// Using || for defaults

278

const title = root.querySelector('h1')?.text || 'No title found';

279

```

280

281

### Query Performance Tips

282

283

- **Specific selectors**: Use IDs and specific classes when possible

284

- **Limit scope**: Query from specific parent elements rather than root

285

- **Cache results**: Store frequently accessed elements in variables

286

- **Batch operations**: Collect all needed elements before processing

287

288

```typescript

289

// Good: Specific and scoped

290

const sidebar = root.getElementById('sidebar');

291

const menuItems = sidebar?.querySelectorAll('li') ?? [];

292

293

// Less optimal: Broad queries

294

const allItems = root.querySelectorAll('li'); // Searches entire document

295

296

// Cache frequently used elements

297

const header = root.querySelector('header');

298

if (header) {

299

const nav = header.querySelector('nav');

300

const logo = header.querySelector('.logo');

301

// Use cached elements for multiple operations

302

}

303

```