Skip to content

Instantly share code, notes, and snippets.

@tinovyatkin
Created April 7, 2025 07:54
Show Gist options
  • Save tinovyatkin/a256bdd3e572aff8b43eb66adfc93b77 to your computer and use it in GitHub Desktop.
Save tinovyatkin/a256bdd3e572aff8b43eb66adfc93b77 to your computer and use it in GitHub Desktop.
/**
* Finds the common directory path prefix for a list of file paths.
* Returns a path ending with '/' or empty string if no common prefix exists.
*
* @param files - An iterable of file paths to process
* @returns The common directory prefix ending with '/' or empty string
*/
export function findCommonPathPrefix(files: Iterable<string>): string {
const iter = Iterator.from(files);
// Check for empty iterable
const first = iter.next();
if (first.done) return '';
// Check for single element iterable
const second = iter.next();
if (second.done) {
const lastSlash = first.value.lastIndexOf('/');
return lastSlash >= 0 ? first.value.substring(0, lastSlash + 1) : '';
}
// Find common prefix between first two paths
let commonPrefix = '';
let lastSlash = -1;
const secondIterator = Iterator.from(second.value);
for (const char of Iterator.from(first.value)) {
if (char === '/') lastSlash = commonPrefix.length;
const secondChar = secondIterator.next();
if (secondChar.done) break;
if (char.localeCompare(secondChar.value, undefined, { sensitivity: 'accent' }) !== 0) {
break;
}
commonPrefix += char;
}
commonPrefix = lastSlash >= 0 ? commonPrefix.substring(0, lastSlash + 1) : '';
// Return empty if no common directory or just root directory
if (!commonPrefix || commonPrefix === '/') return commonPrefix;
// If no more elements, return the common prefix
const next = iter.next();
if (next.done) return commonPrefix;
// Continue recursively with the current common prefix and remaining elements
return findCommonPathPrefix(
(function* (): Iterable<string> {
yield commonPrefix;
yield next.value;
yield* iter;
})(),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment