JavaScript method that returns the file extension of the given path, from the last occurrence of the period.
/**
* Returns the extension of the path, from the last occurrence of the `.`
* (period) character to end of string in the last portion of the path. If there
* is no `.` in the last portion of the path, or if there are no `.` characters
* other than the first character of the basename of path, an empty string is
* returned.
*
* Clone of https://nodejs.org/api/path.html#path_path_extname_path
*
* @param {string} path
* @return {string}
*/
const getFileExtension = path => {
if (typeof path !== "string") path = `${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 find
let preDotState = 0;
for (let i = path.length - 1; i >= 0; --i) {
const code = path.charCodeAt(i);
if (code === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!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 === 46 /*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1) startDot = i;
else if (preDotState !== 1) preDotState = 1;
} else if (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);
};
//
// Examples:
getFileExtension("file"); // ""
getFileExtension(null); // ""
getFileExtension(""); // ""
getFileExtension("--"); // ""
getFileExtension("file.ext"); // ".ext"
getFileExtension("/root/path/file.ext"); // ".ext"
getFileExtension("C:/file.ext"); // ".ext"
getFileExtension("<path>:/file.ext"); // ".ext"
getFileExtension("https://example.com/file.ext"); // ".ext"
getFileExtension("https://example.com/file.ext?param=value"); // ".ext?param=value"