Foundation utilities including hashing, async operations, regular expressions, i18n support, and URL slug generation. These utilities provide essential functionality used throughout the Docusaurus ecosystem.
/**
* Options for slugger functionality
*/
type SluggerOptions = {
maintainCase?: boolean;
};
/**
* Stateful slugger interface for generating unique slugs
*/
type Slugger = {
slug: (value: string, options?: SluggerOptions) => string;
};md5HashCreates MD5 hash of input string.
/**
* Creates MD5 hash of input string
* @param str - String to hash
* @returns MD5 hash as hexadecimal string
*/
function md5Hash(str: string): string;simpleHashCreates truncated MD5 hash of specified length.
/**
* Creates truncated MD5 hash of specified length
* @param str - String to hash
* @param length - Length of hash to return
* @returns Truncated MD5 hash string
*/
function simpleHash(str: string, length: number): string;docuHashGenerates kebab-case string with hash suffix, handling filesystem name length limits.
/**
* Generates kebab-case string with hash suffix
* @param strInput - Input string to process
* @param options - Hashing options
* @param options.hashExtra - Additional string for hash calculation (not in output)
* @param options.hashLength - Length of hash suffix (default: 3)
* @returns Kebab-case string with hash suffix
*/
function docuHash(
strInput: string,
options?: {
hashExtra?: string;
hashLength?: number;
}
): string;Usage Examples:
import { md5Hash, simpleHash, docuHash } from "@docusaurus/utils";
// Basic MD5 hashing
const hash = md5Hash("Hello, World!");
console.log(hash); // "65a8e27d8879283831b664bd8b7f0ad4"
// Truncated hash for short identifiers
const shortHash = simpleHash("content-identifier", 8);
console.log(shortHash); // "a1b2c3d4" (first 8 characters of MD5)
// Docusaurus-style hash for file names
const fileName = docuHash("My Very Long Document Title That Might Exceed Limits");
console.log(fileName); // "my-very-long-document-title-that-might-exceed-abc"
// With custom hash length and extra data
const customHash = docuHash("Document Title", {
hashExtra: "plugin-id-extra-data",
hashLength: 6
});
console.log(customHash); // "document-title-a1b2c3"mapAsyncSequentialSequential async Array.map where order matters - awaits each action before proceeding.
/**
* Sequential async Array.map where order matters
* @param array - Array of items to process sequentially
* @param action - Async function to apply to each item
* @returns Promise resolving to array of results in order
*/
function mapAsyncSequential<T, R>(
array: T[],
action: (t: T) => Promise<R>
): Promise<R[]>;findAsyncSequentialSequential async Array.find where order matters - returns first item matching predicate.
/**
* Sequential async Array.find where order matters
* @param array - Array of items to search sequentially
* @param predicate - Async predicate function
* @returns Promise resolving to first matching item or undefined
*/
function findAsyncSequential<T>(
array: T[],
predicate: (t: T) => Promise<boolean>
): Promise<T | undefined>;Usage Examples:
import { mapAsyncSequential, findAsyncSequential } from "@docusaurus/utils";
// Process files sequentially (important for rate limiting, file locks, etc.)
const files = ["file1.txt", "file2.txt", "file3.txt"];
const processedFiles = await mapAsyncSequential(files, async (file) => {
console.log(`Processing ${file}...`);
await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate work
return `processed-${file}`;
});
console.log(processedFiles); // ["processed-file1.txt", "processed-file2.txt", ...]
// Find first valid configuration file
const configFiles = ["docusaurus.config.js", "docusaurus.config.ts", "docusaurus.config.mjs"];
const validConfig = await findAsyncSequential(configFiles, async (configFile) => {
try {
const exists = await fs.access(configFile);
return true;
} catch {
return false;
}
});
console.log("Found config:", validConfig); // First existing config fileescapeRegexpEscapes string for safe use in regular expressions.
/**
* Escapes string for safe use in regular expressions
* @param string - String to escape
* @returns Escaped string safe for RegExp constructor
*/
function escapeRegexp(string: string): string;Usage Example:
import { escapeRegexp } from "@docusaurus/utils";
// Escape special regex characters
const userInput = "How much is $100 + $50?";
const escapedInput = escapeRegexp(userInput);
console.log(escapedInput); // "How much is \\$100 \\+ \\$50\\?"
// Use in regex construction
const searchTerm = "C++";
const escapedTerm = escapeRegexp(searchTerm);
const regex = new RegExp(escapedTerm, "gi");
const text = "I love C++ programming and C++ is great!";
const matches = text.match(regex);
console.log(matches); // ["C++", "C++"]createSluggerFactory function creating stateful slugger using github-slugger semantics.
/**
* Factory function creating stateful slugger using github-slugger semantics
* @returns Slugger instance with collision avoidance
*/
function createSlugger(): Slugger;Usage Examples:
import { createSlugger } from "@docusaurus/utils";
// Create slugger instance
const slugger = createSlugger();
// Generate unique slugs
const slug1 = slugger.slug("Getting Started");
console.log(slug1); // "getting-started"
const slug2 = slugger.slug("Getting Started"); // Duplicate!
console.log(slug2); // "getting-started-1" (collision avoided)
const slug3 = slugger.slug("Getting Started Again");
console.log(slug3); // "getting-started-again"
// With case preservation
const slug4 = slugger.slug("API Reference", { maintainCase: true });
console.log(slug4); // "API-Reference" (case maintained)
// Multiple sluggers maintain separate state
const slugger2 = createSlugger();
const freshSlug = slugger2.slug("Getting Started");
console.log(freshSlug); // "getting-started" (fresh instance, no collision)localizePathLocalizes a path by adding current locale (unless it's the default locale).
/**
* Localizes a path by adding current locale
* @param params - Localization parameters
* @param params.pathType - "fs" for filesystem paths, "url" for URL paths
* @param params.path - Path to be localized
* @param params.i18n - Current i18n context
* @param params.options - Localization options
* @param params.options.localizePath - Override default localization behavior
* @returns Localized path string
*/
function localizePath(params: {
pathType: "fs" | "url";
path: string;
i18n: I18nContext;
options?: {
localizePath?: boolean;
};
}): string;mergeTranslationsShallow-merges multiple translation file contents into one.
/**
* Shallow-merges multiple translation file contents into one
* @param contents - Array of translation file contents to merge
* @returns Merged translation file content
*/
function mergeTranslations(contents: TranslationFileContent[]): TranslationFileContent;updateTranslationFileMessagesUpdates all messages in a translation file using the provided update function.
/**
* Updates all messages in a translation file using the provided update function
* @param translationFile - Translation file to update
* @param updateMessage - Function to transform each message
* @returns Updated translation file
*/
function updateTranslationFileMessages(
translationFile: TranslationFile,
updateMessage: (message: string) => string
): TranslationFile;getPluginI18nPathConstructs plugin i18n path from localization directory, plugin name, and optional ID.
/**
* Constructs plugin i18n path from localization directory, plugin name, and optional ID
* @param params - Path construction parameters
* @param params.localizationDir - Base localization directory
* @param params.pluginName - Plugin name
* @param params.pluginId - Plugin instance ID (defaults to DEFAULT_PLUGIN_ID)
* @param params.subPaths - Additional path segments
* @returns Constructed i18n path
*/
function getPluginI18nPath(params: {
localizationDir: string;
pluginName: string;
pluginId?: string;
subPaths?: string[];
}): string;Usage Examples:
import {
localizePath,
mergeTranslations,
updateTranslationFileMessages,
getPluginI18nPath
} from "@docusaurus/utils";
// Localize paths based on current locale
const i18nContext = {
currentLocale: "fr",
defaultLocale: "en",
locales: ["en", "fr", "es"],
};
const localizedUrl = localizePath({
pathType: "url",
path: "/docs/intro",
i18n: i18nContext,
});
console.log(localizedUrl); // "/fr/docs/intro" (for French locale)
const defaultLocaleUrl = localizePath({
pathType: "url",
path: "/docs/intro",
i18n: { ...i18nContext, currentLocale: "en" },
});
console.log(defaultLocaleUrl); // "/docs/intro" (no prefix for default locale)
// Merge translation files
const baseTranslations = {
"welcome.title": "Welcome",
"nav.home": "Home",
};
const pluginTranslations = {
"plugin.title": "My Plugin",
"nav.home": "Homepage", // Override
};
const merged = mergeTranslations([baseTranslations, pluginTranslations]);
console.log(merged); // { "welcome.title": "Welcome", "nav.home": "Homepage", "plugin.title": "My Plugin" }
// Update translation messages
const translations = {
message: "Hello {{name}}!",
description: "A greeting message"
};
const updated = updateTranslationFileMessages(translations, (message) => {
return message.replace(/{{(\w+)}}/g, "{$1}"); // Convert placeholder format
});
console.log(updated.message); // "Hello {name}!"
// Get plugin i18n path
const pluginPath = getPluginI18nPath({
localizationDir: "/website/i18n/fr",
pluginName: "docusaurus-plugin-content-docs",
pluginId: "default",
subPaths: ["current"],
});
console.log(pluginPath); // "/website/i18n/fr/docusaurus-plugin-content-docs/default/current"