@@ -287,14 +287,23 @@ export class UriTemplate {
287287 let queryPart : string ;
288288
289289 if ( hasLiteralQuery ) {
290- // Match the path regex against the full URI without a trailing
291- // anchor, then treat everything after the match as the remaining
292- // query string to parse for {?...}/{&...} expressions.
290+ // Match the path regex against the full URI. The lookahead
291+ // assertion ensures the literal portion ends exactly at a
292+ // query-param separator, fragment, or end-of-string, so a
293+ // template like `?id=1` does not spuriously prefix-match
294+ // `?id=100`.
295+ pattern += '(?=[&#]|$)' ;
293296 UriTemplate . validateLength ( pattern , MAX_REGEX_LENGTH , 'Generated regex pattern' ) ;
294297 const regex = new RegExp ( pattern ) ;
295298 match = uri . match ( regex ) ;
296299 if ( ! match ) return null ;
297- queryPart = uri . slice ( match [ 0 ] . length ) . replace ( / ^ & / , '' ) ;
300+ // Everything after the match is the remaining query string to
301+ // parse for {?...}/{&...} expressions. Strip any fragment and
302+ // the leading `&` separator first.
303+ let rest = uri . slice ( match [ 0 ] . length ) ;
304+ const hashIndex = rest . indexOf ( '#' ) ;
305+ if ( hashIndex !== - 1 ) rest = rest . slice ( 0 , hashIndex ) ;
306+ queryPart = rest . replace ( / ^ & / , '' ) ;
298307 } else {
299308 // Split URI into path and query parts at the first '?'
300309 const queryIndex = uri . indexOf ( '?' ) ;
0 commit comments