or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-framework.mdindex.mdlayout-restoration.mdmime-rendering.mdservice-tokens.mdshell-management.mdstatus-management.mdurl-routing.mdutility-functions.md
tile.json

url-routing.mddocs/

0

# URL Routing

1

2

URL-based navigation system with pattern matching, command mapping, and programmatic route handling for single-page application behavior.

3

4

## Capabilities

5

6

### Router Class

7

8

Main router implementation providing URL routing with pattern matching and command execution for navigation within the application.

9

10

```typescript { .api }

11

/**

12

* URL routing implementation for applications

13

*/

14

class Router implements IRouter {

15

constructor(options: Router.IOptions);

16

17

/** The base URL for the router */

18

readonly base: string;

19

20

/** The command registry used by the router */

21

readonly commands: CommandRegistry;

22

23

/** The parsed current URL of the application */

24

readonly current: IRouter.ILocation;

25

26

/** A signal emitted when the router routes a route */

27

readonly routed: ISignal<this, IRouter.ILocation>;

28

29

/** Stop token for halting route matching chain */

30

readonly stop: Token<void>;

31

32

/**

33

* Navigate to a new path within the application

34

* @param path - The new path or empty string if redirecting to root

35

* @param options - The navigation options

36

*/

37

navigate(path: string, options?: IRouter.INavOptions): void;

38

39

/**

40

* Register a rule that maps a path pattern to a command

41

* @param options - The route registration options

42

* @returns A disposable that removes the registered rule from the router

43

*/

44

register(options: IRouter.IRegisterOptions): IDisposable;

45

46

/** Cause a hard reload of the document */

47

reload(): void;

48

49

/**

50

* Route the current URL

51

* @returns Promise that resolves when routing is complete

52

*/

53

route(): Promise<void>;

54

}

55

```

56

57

**Usage Examples:**

58

59

```typescript

60

import { Router, IRouter } from "@jupyterlab/application";

61

import { CommandRegistry } from "@lumino/commands";

62

63

// Create router

64

const commands = new CommandRegistry();

65

const router = new Router({

66

base: '/lab',

67

commands: commands

68

});

69

70

// Register commands first

71

commands.addCommand('app:open-file', {

72

execute: (args) => {

73

console.log('Opening file:', args.path);

74

}

75

});

76

77

commands.addCommand('app:show-help', {

78

execute: () => {

79

console.log('Showing help');

80

}

81

});

82

83

// Register route patterns

84

router.register({

85

command: 'app:open-file',

86

pattern: /^\/file\/(.+)$/,

87

rank: 10

88

});

89

90

router.register({

91

command: 'app:show-help',

92

pattern: /^\/help$/,

93

rank: 20

94

});

95

96

// Navigate programmatically

97

router.navigate('/file/notebook.ipynb');

98

router.navigate('/help');

99

100

// Listen to route changes

101

router.routed.connect((sender, location) => {

102

console.log('Routed to:', location.path);

103

});

104

105

// Current location info

106

console.log('Current path:', router.current.path);

107

console.log('Current hash:', router.current.hash);

108

```

109

110

### IRouter Interface

111

112

Service interface for URL routing functionality with dependency injection support.

113

114

```typescript { .api }

115

/**

116

* URL routing service interface

117

*/

118

interface IRouter {

119

/** The base URL for the router */

120

readonly base: string;

121

122

/** The command registry used by the router */

123

readonly commands: CommandRegistry;

124

125

/** The parsed current URL of the application */

126

readonly current: IRouter.ILocation;

127

128

/** A signal emitted when the router routes a route */

129

readonly routed: ISignal<IRouter, IRouter.ILocation>;

130

131

/** Stop token for halting route matching if returned from command */

132

readonly stop: Token<void>;

133

134

/**

135

* Navigate to a new path within the application

136

* @param path - The new path or empty string if redirecting to root

137

* @param options - The navigation options

138

*/

139

navigate(path: string, options?: IRouter.INavOptions): void;

140

141

/**

142

* Register a rule that maps a path pattern to a command

143

* @param options - The route registration options

144

* @returns A disposable that removes the registered rule from the router

145

*/

146

register(options: IRouter.IRegisterOptions): IDisposable;

147

148

/** Cause a hard reload of the document */

149

reload(): void;

150

151

/**

152

* Route the current URL

153

* @returns Promise that resolves when routing is complete

154

*

155

* #### Notes

156

* If a pattern is matched, its command will be invoked with arguments that

157

* match the `IRouter.ILocation` interface.

158

*/

159

route(): Promise<void>;

160

}

161

162

/**

163

* Service token for URL router

164

*/

165

const IRouter: Token<IRouter>;

166

```

167

168

**Usage in Plugins:**

169

170

```typescript

171

import { IRouter } from "@jupyterlab/application";

172

import { JupyterFrontEndPlugin } from "@jupyterlab/application";

173

174

const routingPlugin: JupyterFrontEndPlugin<void> = {

175

id: 'my-routing-plugin',

176

autoStart: true,

177

requires: [IRouter],

178

activate: (app, router: IRouter) => {

179

// Register routes for this plugin

180

const disposable = router.register({

181

command: 'myapp:handle-route',

182

pattern: /^\/myapp\/(.+)$/,

183

rank: 100

184

});

185

186

// Listen to route changes

187

router.routed.connect((sender, location) => {

188

if (location.path.startsWith('/myapp/')) {

189

console.log('My app route activated');

190

}

191

});

192

193

// Clean up on plugin disposal

194

return disposable;

195

}

196

};

197

```

198

199

### Location Interface

200

201

Information about the current URL location including parsed components.

202

203

```typescript { .api }

204

/**

205

* The parsed location currently being routed

206

*/

207

interface IRouter.ILocation extends ReadonlyPartialJSONObject {

208

/** The location hash */

209

hash: string;

210

211

/** The path that matched a routing pattern */

212

path: string;

213

214

/**

215

* The request being routed with the router `base` omitted

216

*

217

* #### Notes

218

* This field includes the query string and hash, if they exist.

219

*/

220

request: string;

221

222

/**

223

* The search element, including leading question mark (`'?'`), if any,

224

* of the path.

225

*/

226

search?: string;

227

}

228

```

229

230

**Usage Examples:**

231

232

```typescript

233

// Accessing location information

234

const currentLocation = router.current;

235

236

console.log('Full request:', currentLocation.request);

237

console.log('Path only:', currentLocation.path);

238

console.log('Hash:', currentLocation.hash);

239

console.log('Query string:', currentLocation.search);

240

241

// Example values for URL: /lab/tree/notebooks?filter=python#section1

242

// base: '/lab'

243

// request: '/tree/notebooks?filter=python#section1'

244

// path: '/tree/notebooks'

245

// search: '?filter=python'

246

// hash: '#section1'

247

```

248

249

### Navigation Options

250

251

Options for controlling navigation behavior and routing.

252

253

```typescript { .api }

254

/**

255

* The options passed into a navigation request

256

*/

257

interface IRouter.INavOptions {

258

/**

259

* Whether the navigation should be hard URL change instead of an HTML

260

* history API change.

261

*/

262

hard?: boolean;

263

264

/**

265

* Should the routing stage be skipped when navigating? This will simply rewrite the URL

266

* and push the new state to the history API, no routing commands will be triggered.

267

*/

268

skipRouting?: boolean;

269

}

270

```

271

272

**Usage Examples:**

273

274

```typescript

275

// Soft navigation (default) - uses HTML5 history API

276

router.navigate('/new-path');

277

278

// Hard navigation - causes full page reload

279

router.navigate('/new-path', { hard: true });

280

281

// Skip routing - just update URL without triggering commands

282

router.navigate('/new-path', { skipRouting: true });

283

284

// Combined options

285

router.navigate('/external-link', {

286

hard: true,

287

skipRouting: false

288

});

289

```

290

291

### Route Registration

292

293

System for mapping URL patterns to commands with configurable priority.

294

295

```typescript { .api }

296

/**

297

* The specification for registering a route with the router

298

*/

299

interface IRouter.IRegisterOptions {

300

/** The command string that will be invoked upon matching */

301

command: string;

302

303

/** The regular expression that will be matched against URLs */

304

pattern: RegExp;

305

306

/**

307

* The rank order of the registered rule. A lower rank denotes a higher

308

* priority. The default rank is `100`.

309

*/

310

rank?: number;

311

}

312

```

313

314

**Usage Examples:**

315

316

```typescript

317

// High priority route (lower rank = higher priority)

318

router.register({

319

command: 'app:admin-panel',

320

pattern: /^\/admin\/(.*)$/,

321

rank: 1

322

});

323

324

// Medium priority route

325

router.register({

326

command: 'app:open-notebook',

327

pattern: /^\/notebooks\/(.+\.ipynb)$/,

328

rank: 50

329

});

330

331

// Default priority route (rank defaults to 100)

332

router.register({

333

command: 'app:catch-all',

334

pattern: /^\/(.*)$/

335

});

336

337

// Route with capture groups

338

router.register({

339

command: 'app:user-profile',

340

pattern: /^\/users\/([^\/]+)(?:\/(.+))?$/,

341

rank: 25

342

});

343

344

// Command handler receives location as arguments

345

commands.addCommand('app:user-profile', {

346

execute: (args: IRouter.ILocation) => {

347

// Access path parts via regex match

348

const match = args.path.match(/^\/users\/([^\/]+)(?:\/(.+))?$/);

349

if (match) {

350

const [, username, subpath] = match;

351

console.log('User:', username, 'Subpath:', subpath);

352

}

353

}

354

});

355

```

356

357

### Constructor Options

358

359

Configuration for creating Router instances.

360

361

```typescript { .api }

362

namespace Router {

363

/**

364

* Constructor options for Router

365

*/

366

interface IOptions {

367

/** Base URL path for the router */

368

base: string;

369

370

/** Command registry to use for route commands */

371

commands: CommandRegistry;

372

}

373

}

374

```

375

376

**Usage Examples:**

377

378

```typescript

379

import { Router } from "@jupyterlab/application";

380

import { CommandRegistry } from "@lumino/commands";

381

382

// Basic router setup

383

const commands = new CommandRegistry();

384

const router = new Router({

385

base: window.location.pathname,

386

commands: commands

387

});

388

389

// Router with custom base

390

const labRouter = new Router({

391

base: '/lab',

392

commands: commands

393

});

394

395

// Router for development

396

const devRouter = new Router({

397

base: process.env.NODE_ENV === 'development' ? '/dev' : '/app',

398

commands: commands

399

});

400

```

401

402

### Advanced Routing Patterns

403

404

Complex routing scenarios and patterns for real-world applications.

405

406

```typescript { .api }

407

// Advanced routing patterns

408

interface AdvancedRoutingPatterns {

409

/** File path routing with extension matching */

410

fileRouting: RegExp; // /^\/files\/(.+\.(py|js|ts|md))$/

411

412

/** Nested resource routing */

413

nestedRouting: RegExp; // /^\/workspaces\/([^\/]+)\/files\/(.+)$/

414

415

/** Optional parameters */

416

optionalParams: RegExp; // /^\/search(?:\/(.+))?$/

417

418

/** Query parameter handling */

419

queryParams: RegExp; // /^\/results/

420

}

421

```

422

423

**Complete Routing Example:**

424

425

```typescript

426

import { Router, IRouter } from "@jupyterlab/application";

427

import { CommandRegistry } from "@lumino/commands";

428

429

// Complete routing setup

430

function setupRouting(commands: CommandRegistry): Router {

431

const router = new Router({

432

base: '/app',

433

commands: commands

434

});

435

436

// Define commands

437

commands.addCommand('app:home', {

438

execute: () => console.log('Home page')

439

});

440

441

commands.addCommand('app:open-file', {

442

execute: (args: IRouter.ILocation) => {

443

const match = args.path.match(/^\/files\/(.+)$/);

444

if (match) {

445

const filePath = decodeURIComponent(match[1]);

446

console.log('Opening file:', filePath);

447

}

448

}

449

});

450

451

commands.addCommand('app:search', {

452

execute: (args: IRouter.ILocation) => {

453

const searchParams = new URLSearchParams(args.search || '');

454

const query = searchParams.get('q') || '';

455

console.log('Searching for:', query);

456

}

457

});

458

459

// Register routes with priorities

460

const disposables = [

461

// High priority exact matches

462

router.register({

463

command: 'app:home',

464

pattern: /^\/$/,

465

rank: 1

466

}),

467

468

// Medium priority with parameters

469

router.register({

470

command: 'app:open-file',

471

pattern: /^\/files\/(.+)$/,

472

rank: 50

473

}),

474

475

router.register({

476

command: 'app:search',

477

pattern: /^\/search$/,

478

rank: 50

479

})

480

];

481

482

// Navigation helpers

483

const navigateToFile = (path: string) => {

484

router.navigate(`/files/${encodeURIComponent(path)}`);

485

};

486

487

const navigateToSearch = (query: string) => {

488

router.navigate(`/search?q=${encodeURIComponent(query)}`);

489

};

490

491

// Route change logging

492

router.routed.connect((sender, location) => {

493

console.log(`Routed to: ${location.path}`, location);

494

});

495

496

return router;

497

}

498

```

499

500

## Error Handling

501

502

Handling routing errors and edge cases.

503

504

```typescript

505

// Error handling in route commands

506

commands.addCommand('app:error-prone-route', {

507

execute: async (args: IRouter.ILocation) => {

508

try {

509

// Route handling that might fail

510

await handleRoute(args);

511

} catch (error) {

512

console.error('Route handling failed:', error);

513

// Navigate to error page or show notification

514

router.navigate('/error');

515

}

516

}

517

});

518

519

// Graceful fallback routing

520

router.register({

521

command: 'app:not-found',

522

pattern: /.*/, // Matches everything

523

rank: 1000 // Lowest priority (highest rank)

524

});

525

```