docusaurus/packages/docusaurus-utils/src/hashUtils.ts

55 lines
1.8 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {createHash} from 'crypto';
import _ from 'lodash';
import {shortName, isNameTooLong} from './pathUtils';
/** Thin wrapper around `crypto.createHash("md5")`. */
export function md5Hash(str: string): string {
return createHash('md5').update(str).digest('hex');
}
/** Creates an MD5 hash and truncates it to the given length. */
export function simpleHash(str: string, length: number): string {
return md5Hash(str).substring(0, length);
}
// Based on https://github.com/gatsbyjs/gatsby/pull/21518/files
/**
* Given an input string, convert to kebab-case and append a hash, avoiding name
* collision. Also removes part of the string if its larger than the allowed
* filename per OS, avoiding `ERRNAMETOOLONG` error.
*/
export function docuHash(
strInput: string,
options?: {
// String that contributes to the hash value
// but does not contribute to the returned string
hashExtra?: string;
// Length of the hash to append
hashLength?: number;
},
): string {
// TODO check this historical behavior
// I'm not sure it makes sense to keep it...
if (strInput === '/' && typeof options?.hashExtra === 'undefined') {
return 'index';
}
const str = strInput === '/' ? 'index' : strInput;
const hashExtra = options?.hashExtra ?? '';
const hashLength = options?.hashLength ?? 3;
const stringToHash = str + hashExtra;
const shortHash = simpleHash(stringToHash, hashLength);
const parsedPath = `${_.kebabCase(str)}-${shortHash}`;
if (isNameTooLong(parsedPath)) {
return `${shortName(_.kebabCase(str))}-${shortHash}`;
}
return parsedPath;
}