Home / File/ priority.ts — astro Source File

priority.ts — astro Source File

Architecture documentation for priority.ts, a typescript file in the astro codebase. 1 imports, 0 dependents.

File typescript CoreAstro RoutingSystem 1 imports 1 functions

Entity Profile

Dependency Diagram

graph LR
  eb0295fb_0f16_eb12_dcf0_e9ede8e7d690["priority.ts"]
  10d4e39f_edb6_3e34_aa93_ae1211e7da05["../types/public/internal.js"]
  eb0295fb_0f16_eb12_dcf0_e9ede8e7d690 --> 10d4e39f_edb6_3e34_aa93_ae1211e7da05
  style eb0295fb_0f16_eb12_dcf0_e9ede8e7d690 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

import type { RouteData } from '../../types/public/internal.js';

/**
 * Comparator for sorting routes in resolution order.
 *
 * The routes are sorted in by the following rules in order, following the first rule that
 * applies:
 * - More specific routes are sorted before less specific routes. Here, "specific" means
 *   the number of segments in the route, so a parent route is always sorted after its children.
 *   For example, `/foo/bar` is sorted before `/foo`.
 *   Index routes, originating from a file named `index.astro`, are considered to have one more
 *   segment than the URL they represent.
 * - Static routes are sorted before dynamic routes.
 *   For example, `/foo/bar` is sorted before `/foo/[bar]`.
 * - Dynamic routes with single parameters are sorted before dynamic routes with rest parameters.
 *   For example, `/foo/[bar]` is sorted before `/foo/[...bar]`.
 * - Prerendered routes are sorted before non-prerendered routes.
 * - Endpoints are sorted before pages.
 *   For example, a file `/foo.ts` is sorted before `/bar.astro`.
 * - If both routes are equal regarding all previous conditions, they are sorted alphabetically.
 *   For example, `/bar` is sorted before `/foo`.
 *   The definition of "alphabetically" is dependent on the default locale of the running system.
 */
export function routeComparator(a: RouteData, b: RouteData) {
	const commonLength = Math.min(a.segments.length, b.segments.length);

	for (let index = 0; index < commonLength; index++) {
		const aSegment = a.segments[index];
		const bSegment = b.segments[index];

		const aIsStatic = aSegment.every((part) => !part.dynamic && !part.spread);
		const bIsStatic = bSegment.every((part) => !part.dynamic && !part.spread);

		if (aIsStatic && bIsStatic) {
			// Both segments are static, they are sorted alphabetically if they are different
			const aContent = aSegment.map((part) => part.content).join('');
			const bContent = bSegment.map((part) => part.content).join('');

			if (aContent !== bContent) {
				return aContent.localeCompare(bContent);
			}
		}

		// Sort static routes before dynamic routes
		if (aIsStatic !== bIsStatic) {
			return aIsStatic ? -1 : 1;
		}

		const aAllDynamic = aSegment.every((part) => part.dynamic);
		const bAllDynamic = bSegment.every((part) => part.dynamic);

		// Some route might have partial dynamic segments, e.g. game-[title].astro
		// These routes should have higher priority against route that have **only** dynamic segments, e.g. [title].astro
		if (aAllDynamic !== bAllDynamic) {
			return aAllDynamic ? 1 : -1;
		}

		const aHasSpread = aSegment.some((part) => part.spread);
		const bHasSpread = bSegment.some((part) => part.spread);

		// Sort dynamic routes with rest parameters after dynamic routes with single parameters
		// (also after static, but that is already covered by the previous condition)
		if (aHasSpread !== bHasSpread) {
			return aHasSpread ? 1 : -1;
		}
	}

	const aLength = a.segments.length;
	const bLength = b.segments.length;

	if (aLength !== bLength) {
		const aEndsInRest = a.segments.at(-1)?.some((part) => part.spread);
		const bEndsInRest = b.segments.at(-1)?.some((part) => part.spread);

		if (aEndsInRest !== bEndsInRest && Math.abs(aLength - bLength) === 1) {
			// If only one of the routes ends in a rest parameter
			// and the difference in length is exactly 1
			// and the shorter route is the one that ends in a rest parameter
			// the shorter route is considered more specific.
			// I.e. `/foo` is considered more specific than `/foo/[...bar]`
			if (aLength > bLength && aEndsInRest) {
				// b: /foo
				// a: /foo/[...bar]
				return 1;
			}

			if (bLength > aLength && bEndsInRest) {
				// a: /foo
				// b: /foo/[...bar]
				return -1;
			}
		}

		// Sort routes by length
		return aLength > bLength ? -1 : 1;
	}

	// Sort endpoints before pages
	if ((a.type === 'endpoint') !== (b.type === 'endpoint')) {
		return a.type === 'endpoint' ? -1 : 1;
	}

	// Both routes have segments with the same properties
	return a.route.localeCompare(b.route);
}

Domain

Subdomains

Functions

Dependencies

  • ../types/public/internal.js

Frequently Asked Questions

What does priority.ts do?
priority.ts is a source file in the astro codebase, written in typescript. It belongs to the CoreAstro domain, RoutingSystem subdomain.
What functions are defined in priority.ts?
priority.ts defines 1 function(s): routeComparator.
What does priority.ts depend on?
priority.ts imports 1 module(s): ../types/public/internal.js.
Where is priority.ts in the architecture?
priority.ts is located at packages/astro/src/core/routing/priority.ts (domain: CoreAstro, subdomain: RoutingSystem, directory: packages/astro/src/core/routing).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free