or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collection-operations.mdcontent-matching.mdcore-matching.mdindex.mdmatcher-creation.mdregex-compilation.md

matcher-creation.mddocs/

0

# Matcher Creation and Capture

1

2

Factory functions for creating reusable matchers and extracting pattern captures. These functions provide advanced pattern matching capabilities for performance optimization and pattern extraction.

3

4

## Capabilities

5

6

### Matcher Function Creation

7

8

Create reusable matcher functions from glob patterns for repeated matching operations.

9

10

```javascript { .api }

11

/**

12

* Create a reusable matcher function from a glob pattern

13

* @param {String} pattern - Glob pattern to create matcher function for

14

* @param {Object} options - Optional configuration for pattern compilation

15

* @returns {Function} Matcher function that takes string and returns boolean

16

*/

17

nanomatch.matcher(pattern, options);

18

19

/**

20

* Matcher function signature returned by nanomatch.matcher()

21

* @param {String} str - String to test against the compiled pattern

22

* @returns {Boolean} True if string matches the pattern, false otherwise

23

*/

24

type MatcherFunction = (str: string) => boolean;

25

```

26

27

**Usage Examples:**

28

29

```javascript

30

const nanomatch = require('nanomatch');

31

32

// Create reusable matchers for performance

33

const isJavaScript = nanomatch.matcher('*.js');

34

const isComponent = nanomatch.matcher('*.component.*');

35

const isInSrc = nanomatch.matcher('src/**');

36

37

// Use matchers repeatedly

38

console.log(isJavaScript('app.js')); //=> true

39

console.log(isJavaScript('styles.css')); //=> false

40

console.log(isComponent('user.component.ts')); //=> true

41

console.log(isInSrc('src/app/main.ts')); //=> true

42

43

// Matcher with options

44

const isCaseInsensitiveJS = nanomatch.matcher('*.js', { nocase: true });

45

console.log(isCaseInsensitiveJS('App.JS')); //=> true

46

47

// Complex patterns

48

const isTestFile = nanomatch.matcher('**/*.{test,spec}.{js,ts}');

49

console.log(isTestFile('src/utils.test.js')); //=> true

50

console.log(isTestFile('lib/component.spec.ts')); //=> true

51

52

// Negation patterns in matchers

53

const isNotNodeModules = nanomatch.matcher('!**/node_modules/**');

54

console.log(isNotNodeModules('src/app.js')); //=> true

55

console.log(isNotNodeModules('node_modules/lib/dep.js')); //=> false

56

57

// Using matchers with arrays

58

const files = ['app.js', 'styles.css', 'component.ts', 'test.spec.js'];

59

const jsFiles = files.filter(isJavaScript);

60

console.log(jsFiles); //=> ['app.js']

61

62

// Benchmark performance benefit

63

const pattern = '**/*.{js,ts,jsx,tsx}';

64

const filesToTest = [/* thousands of file paths */];

65

66

// Slow: recompiling pattern each time

67

filesToTest.forEach(file => {

68

if (nanomatch.isMatch(file, pattern)) {

69

// process file

70

}

71

});

72

73

// Fast: compile once, use many times

74

const isSourceFile = nanomatch.matcher(pattern);

75

filesToTest.forEach(file => {

76

if (isSourceFile(file)) {

77

// process file

78

}

79

});

80

```

81

82

### Pattern Capture Extraction

83

84

Extract captured groups from glob pattern matches for parsing and information extraction.

85

86

```javascript { .api }

87

/**

88

* Extract captures from a pattern match

89

* @param {String} pattern - Glob pattern with capture groups (parentheses)

90

* @param {String} string - String to match and extract captures from

91

* @param {Object} options - Optional configuration for pattern matching

92

* @returns {Array|null} Array of captured groups or null if no match

93

*/

94

nanomatch.capture(pattern, string, options);

95

```

96

97

**Usage Examples:**

98

99

```javascript

100

const nanomatch = require('nanomatch');

101

102

// Basic capture with wildcards

103

console.log(nanomatch.capture('*.js', 'app.js'));

104

//=> ['app'] (captures the * part)

105

106

console.log(nanomatch.capture('*.js', 'styles.css'));

107

//=> null (no match)

108

109

// Multiple captures

110

console.log(nanomatch.capture('src/*/*.js', 'src/components/button.js'));

111

//=> ['components', 'button'] (captures both * parts)

112

113

// Directory and filename parsing

114

const pathPattern = '**/(*).(*).js';

115

console.log(nanomatch.capture(pathPattern, 'src/components/user.component.js'));

116

//=> ['user', 'component'] (captures name and type)

117

118

// Version string parsing

119

const versionPattern = 'v(*).(*).(*)-*';

120

console.log(nanomatch.capture(versionPattern, 'v1.2.3-beta'));

121

//=> ['1', '2', '3'] (captures major, minor, patch)

122

123

// URL-like pattern parsing

124

const routePattern = '/api/(*)/(*)/';

125

console.log(nanomatch.capture(routePattern, '/api/users/123/'));

126

//=> ['users', '123'] (captures resource and id)

127

128

// No captures in pattern

129

console.log(nanomatch.capture('*.js', 'app.js'));

130

//=> [] (pattern has no explicit capture groups)

131

132

// Empty captures

133

console.log(nanomatch.capture('prefix-*-suffix', 'prefix--suffix'));

134

//=> [''] (captures empty string between dashes)

135

136

// Nested directory capture

137

const nestedPattern = 'src/(**)/(*).(*)';

138

console.log(nanomatch.capture(nestedPattern, 'src/components/ui/button.component.tsx'));

139

//=> ['components/ui', 'button', 'component'] (captures path, name, type)

140

```

141

142

## Advanced Usage Patterns

143

144

### Performance Optimization with Matchers

145

146

```javascript

147

const nanomatch = require('nanomatch');

148

149

// Scenario: Processing large file lists with multiple pattern checks

150

const files = [

151

'src/app.js', 'src/utils.js', 'lib/helper.js',

152

'test/app.test.js', 'test/utils.spec.js',

153

'docs/readme.md', 'config/webpack.js'

154

];

155

156

// Inefficient: recompiling patterns

157

function processFilesSlowly(files) {

158

const results = { source: [], tests: [], configs: [] };

159

160

files.forEach(file => {

161

if (nanomatch.isMatch(file, 'src/**/*.js')) {

162

results.source.push(file);

163

}

164

if (nanomatch.isMatch(file, '**/*.{test,spec}.js')) {

165

results.tests.push(file);

166

}

167

if (nanomatch.isMatch(file, 'config/**')) {

168

results.configs.push(file);

169

}

170

});

171

172

return results;

173

}

174

175

// Efficient: pre-compiled matchers

176

function processFilesQuickly(files) {

177

const isSource = nanomatch.matcher('src/**/*.js');

178

const isTest = nanomatch.matcher('**/*.{test,spec}.js');

179

const isConfig = nanomatch.matcher('config/**');

180

181

const results = { source: [], tests: [], configs: [] };

182

183

files.forEach(file => {

184

if (isSource(file)) results.source.push(file);

185

if (isTest(file)) results.tests.push(file);

186

if (isConfig(file)) results.configs.push(file);

187

});

188

189

return results;

190

}

191

```

192

193

### Information Extraction with Captures

194

195

```javascript

196

const nanomatch = require('nanomatch');

197

198

// File path parsing

199

function parseFilePath(filePath) {

200

// Extract directory, name, and extension

201

const captures = nanomatch.capture('(**)/(*).(*)' , filePath);

202

if (!captures) return null;

203

204

const [directory, name, extension] = captures;

205

return { directory, name, extension };

206

}

207

208

console.log(parseFilePath('src/components/button.tsx'));

209

//=> { directory: 'src/components', name: 'button', extension: 'tsx' }

210

211

// API route parsing

212

function parseApiRoute(route) {

213

const captures = nanomatch.capture('/api/v(*)/(*)/(*)', route);

214

if (!captures) return null;

215

216

const [version, resource, id] = captures;

217

return { version, resource, id: id || null };

218

}

219

220

console.log(parseApiRoute('/api/v1/users/123'));

221

//=> { version: '1', resource: 'users', id: '123' }

222

223

console.log(parseApiRoute('/api/v2/posts/'));

224

//=> { version: '2', resource: 'posts', id: '' }

225

226

// Configuration key parsing

227

function parseConfigKey(key) {

228

const captures = nanomatch.capture('(*).(*).(*)', key);

229

if (!captures) return null;

230

231

const [service, environment, setting] = captures;

232

return { service, environment, setting };

233

}

234

235

console.log(parseConfigKey('database.production.host'));

236

//=> { service: 'database', environment: 'production', setting: 'host' }

237

238

// Build artifact parsing

239

function parseBuildArtifact(filename) {

240

const captures = nanomatch.capture('(*)-v(*)-(*)-(*).*', filename);

241

if (!captures) return null;

242

243

const [name, version, platform, arch] = captures;

244

return { name, version, platform, arch };

245

}

246

247

console.log(parseBuildArtifact('myapp-v1.2.3-linux-x64.tar.gz'));

248

//=> { name: 'myapp', version: '1.2.3', platform: 'linux', arch: 'x64' }

249

```

250

251

## Matcher Function Properties

252

253

```javascript

254

const nanomatch = require('nanomatch');

255

256

// Matchers have additional properties for debugging

257

const matcher = nanomatch.matcher('src/**/*.{js,ts}');

258

259

// Access compilation result (non-enumerable property)

260

console.log(matcher.result);

261

//=> { output: '...', ast: {...}, ... } (compilation details)

262

263

// Matcher functions are memoized

264

const matcher1 = nanomatch.matcher('*.js');

265

const matcher2 = nanomatch.matcher('*.js');

266

console.log(matcher1 === matcher2); //=> true (same cached function)

267

268

// Different options create different matchers

269

const matcher3 = nanomatch.matcher('*.js', { nocase: true });

270

console.log(matcher1 === matcher3); //=> false (different options)

271

```

272

273

## Error Handling

274

275

```javascript

276

const nanomatch = require('nanomatch');

277

278

// Invalid pattern types

279

try {

280

nanomatch.matcher(123);

281

} catch (error) {

282

console.log(error.message);

283

//=> 'expected pattern to be an array, string or regex'

284

}

285

286

try {

287

nanomatch.matcher(null);

288

} catch (error) {

289

console.log(error.message);

290

//=> 'expected pattern to be an array, string or regex'

291

}

292

293

// Empty patterns

294

const emptyMatcher = nanomatch.matcher('');

295

console.log(emptyMatcher('anything')); //=> false

296

297

// Capture with non-matching patterns

298

console.log(nanomatch.capture('*.js', 'style.css')); //=> null

299

300

// Empty string inputs

301

console.log(nanomatch.capture('*', '')); //=> [''] (captures empty string)

302

console.log(nanomatch.capture('', 'test')); //=> null (empty pattern doesn't match)

303

```

304

305

## Memory and Performance Considerations

306

307

- Matcher functions are cached globally - identical patterns with identical options return the same function instance

308

- Use matchers when you need to test the same pattern against many strings

309

- Captures are not cached - each call recomputes the match and extractions

310

- Matchers include compiled regex and metadata, so they use more memory than simple functions

311

- For one-off matching, `isMatch()` may be more efficient than creating a matcher