// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.// This module is browser compatible. import{CHAR_DOT}from"../_common/constants.ts";import{ assertPath }from"../_common/assert_path.ts";import{ isPosixPathSeparator }from"./_util.ts"; /** * Return the extension of the `path` with leading period. * * @example * ```ts * import { extname } from "https://deno.land/std@$STD_VERSION/path/extname.ts"; * * console.log(extname("/home/user/Documents/")); // "" * console.log(extname("/home/user/Documents/image.png")); // ".png" * ``` * * @param path with extension * @returns extension (ex. for `file.ts` returns `.ts`) */exportfunctionextname(path:string):string{assertPath(path); let startDot =-1;let startPart =0;let end =-1;let matchedSlash =true;// Track the state of characters (if any) we see before our first dot and// after any path separator we findlet preDotState =0;for(let i = path.length-1; i >=0;--i){const code = path.charCodeAt(i);if(isPosixPathSeparator(code)){// If we reached a path separator that was not part of a set of path// separators at the end of the string, stop nowif(!matchedSlash){ startPart = i +1;break;}continue;}if(end ===-1){// We saw the first non-path separator, mark this as the end of our// extension matchedSlash =false; end = i +1;}if(code ===CHAR_DOT){// If this is our first dot, mark it as the start of our extensionif(startDot ===-1) startDot = i;elseif(preDotState !==1) preDotState =1;}elseif(startDot !==-1){// We saw a non-dot and non-path separator before our dot, so we should// have a good chance at having a non-empty extension preDotState =-1;}} if( startDot ===-1|| end ===-1||// We saw a non-dot character immediately before the dot preDotState ===0||// The (right-most) trimmed path component is exactly '..'(preDotState ===1&& startDot === end -1&& startDot === startPart +1)){return"";}return path.slice(startDot, end);}