@digicroz/js-kit 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +87 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +83 -9
- package/dist/index.js.map +1 -1
- package/dist/name/index.cjs +61 -0
- package/dist/name/index.cjs.map +1 -0
- package/dist/name/index.d.cts +60 -0
- package/dist/name/index.d.ts +60 -0
- package/dist/name/index.js +55 -0
- package/dist/name/index.js.map +1 -0
- package/dist/slug/index.cjs +30 -8
- package/dist/slug/index.cjs.map +1 -1
- package/dist/slug/index.d.cts +23 -4
- package/dist/slug/index.d.ts +23 -4
- package/dist/slug/index.js +30 -8
- package/dist/slug/index.js.map +1 -1
- package/package.json +1 -1
package/dist/slug/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/slug/index.ts"],"names":[],"mappings":";;;AAiBO,SAAS,YAAY,IAAA,EAAuB;AACjD,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,KAAA;AAAA;AAOT,EAAA,MAAM,WAAA,GAAc,4BAAA;AAEpB,EAAA,OAAO,WAAA,CAAY,KAAK,IAAI,CAAA;AAC9B;AA0BO,SAAS,aAAA,CACd,IAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAI,GAAI,OAAA;AAE5B,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,EAAA;AAAA;AAGT,EAAA,OAAO,IAAA,CACJ,UAAS,CACT,WAAA,GACA,IAAA,EAAK,CAEL,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,oBAAoB,EAAE,CAAA,CAE9B,QAAQ,SAAA,EAAW,SAAS,EAE5B,OAAA,CAAQ,IAAI,MAAA,CAAO,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA,EAAG,EAAE,EAEpD,OAAA,CAAQ,IAAI,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA,EAAG,SAAS,EAEnD,OAAA,CAAQ,IAAI,OAAO,CAAA,CAAA,EAAI,SAAS,KAAK,SAAS,CAAA,EAAA,CAAA,EAAM,GAAG,CAAA,EAAG,EAAE,CAAA;AACjE;AAkBO,SAAS,kBAAA,CACd,QAAA,EACA,aAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAI,GAAI,OAAA;AAE5B,EAAA,IAAI,CAAC,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA,EAAG;AACrC,IAAA,OAAO,QAAA;AAAA;AAGT,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,aAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAElD,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,UAAU,CAAA,EAAG;AACzC,IAAA,OAAA,EAAA;AACA,IAAA,UAAA,GAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAAA;AAGhD,EAAA,OAAO,UAAA;AACT;AAqBO,SAAS,kBAAkB,OAAA,EAAkB;AAClD,EAAA,OAAO,CAAC,GAAA,KAAgB,WAAA,CAAY,GAAG,CAAA;AACzC;AAwBO,SAAS,iBAAiB,OAAA,EAAkC;AACjE,EAAA,OAAO,CAAC,GAAA,KAAgB,aAAA,CAAc,GAAA,EAAK,OAAO,CAAA;AACpD;AAmBO,IAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAA,EAAQ,CAAC,aAAA,KAA2B;AAElC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,gBAAA;AAAA,MACP,QAAA,EAAU,kBAA+B,CAAA;AAAA,MACzC,SAAS,aAAA,IAAiB;AAAA,KAC5B;AAAA;AAEJ;AAoBO,IAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA,EAI5B,SAAA,EAAW,CAAC,OAAA,KAAqC,gBAAA,CAAiB,OAAO;AAC3E","file":"index.cjs","sourcesContent":["/**\r\n * Checks if a string is a valid slug\r\n * A valid slug contains only lowercase alphanumeric characters and hyphens,\r\n * with no consecutive hyphens and no leading/trailing hyphens\r\n * \r\n * @param slug - The string to validate\r\n * @returns True if the string is a valid slug, false otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * isValidSlug('hello-world') // true\r\n * isValidSlug('hello--world') // false (consecutive hyphens)\r\n * isValidSlug('Hello-World') // false (uppercase)\r\n * isValidSlug('-hello-world') // false (leading hyphen)\r\n * isValidSlug('hello_world') // false (underscore not allowed)\r\n * ```\r\n */\r\nexport function isValidSlug(slug: string): boolean {\r\n if (!slug || typeof slug !== 'string') {\r\n return false;\r\n }\r\n\r\n // Check if slug matches the pattern:\r\n // - starts with alphanumeric\r\n // - ends with alphanumeric\r\n // - contains only lowercase alphanumeric and single hyphens\r\n const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n \r\n return slugPattern.test(slug);\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-safe slug\r\n * - Converts to lowercase\r\n * - Removes special characters\r\n * - Replaces spaces and underscores with hyphens\r\n * - Removes consecutive hyphens\r\n * - Trims leading and trailing hyphens\r\n * \r\n * @param text - The string to convert to a slug\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns A URL-safe slug\r\n * \r\n * @example\r\n * ```ts\r\n * convertToSlug('Hello World') // 'hello-world'\r\n * convertToSlug('Hello World!!!') // 'hello-world'\r\n * convertToSlug('Hello_World') // 'hello-world'\r\n * convertToSlug(' Hello World ') // 'hello-world'\r\n * convertToSlug('Hello---World') // 'hello-world'\r\n * convertToSlug('Café & Restaurant') // 'cafe-restaurant'\r\n * convertToSlug('Product #123') // 'product-123'\r\n * ```\r\n */\r\nexport function convertToSlug(\r\n text: string,\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!text || typeof text !== 'string') {\r\n return '';\r\n }\r\n\r\n return text\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n // Remove accents and diacritics\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n // Replace spaces, underscores, and other common separators with separator\r\n .replace(/[\\s_]+/g, separator)\r\n // Remove all non-alphanumeric characters except the separator\r\n .replace(new RegExp(`[^a-z0-9${separator}]`, 'g'), '')\r\n // Replace multiple consecutive separators with single separator\r\n .replace(new RegExp(`${separator}+`, 'g'), separator)\r\n // Remove leading and trailing separators\r\n .replace(new RegExp(`^${separator}+|${separator}+$`, 'g'), '');\r\n}\r\n\r\n/**\r\n * Generates a unique slug by appending a number if the slug already exists\r\n * \r\n * @param baseSlug - The base slug to make unique\r\n * @param existingSlugs - Array of existing slugs to check against\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use before the number (default: '-')\r\n * @returns A unique slug\r\n * \r\n * @example\r\n * ```ts\r\n * generateUniqueSlug('hello-world', ['hello-world']) // 'hello-world-1'\r\n * generateUniqueSlug('hello-world', ['hello-world', 'hello-world-1']) // 'hello-world-2'\r\n * generateUniqueSlug('hello-world', []) // 'hello-world'\r\n * ```\r\n */\r\nexport function generateUniqueSlug(\r\n baseSlug: string,\r\n existingSlugs: string[],\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!existingSlugs.includes(baseSlug)) {\r\n return baseSlug;\r\n }\r\n\r\n let counter = 1;\r\n let uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n\r\n while (existingSlugs.includes(uniqueSlug)) {\r\n counter++;\r\n uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n }\r\n\r\n return uniqueSlug;\r\n}\r\n\r\n/**\r\n * Creates a Zod refinement function for slug validation\r\n * Use with z.string().refine() or z.string().superRefine()\r\n * \r\n * @param message - Custom error message (optional)\r\n * @returns Refinement function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugValidation } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * slug: z.string().refine(zodSlugValidation(), {\r\n * message: 'Invalid slug format'\r\n * })\r\n * });\r\n * ```\r\n */\r\nexport function zodSlugValidation(message?: string) {\r\n return (val: string) => isValidSlug(val);\r\n}\r\n\r\n/**\r\n * Creates a Zod transform function that converts strings to slugs\r\n * Use with z.string().transform()\r\n * \r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns Transform function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugTransform } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(zodSlugTransform())\r\n * });\r\n * \r\n * schema.parse({ title: 'Hello', slug: 'Hello World!!!' })\r\n * // { title: 'Hello', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport function zodSlugTransform(options?: { separator?: string }) {\r\n return (val: string) => convertToSlug(val, options);\r\n}\r\n\r\n/**\r\n * Pre-configured Zod schema for slug validation\r\n * Validates that the string is a valid slug format\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { slugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * slug: slugSchema\r\n * });\r\n * \r\n * postSchema.parse({ slug: 'hello-world' }); // ✓ Valid\r\n * postSchema.parse({ slug: 'Hello World' }); // ✗ Invalid\r\n * ```\r\n */\r\nexport const slugSchema = {\r\n /**\r\n * Get a Zod string schema that validates slug format\r\n * Requires zod to be installed: npm install zod\r\n */\r\n create: (customMessage?: string) => {\r\n // Dynamic import to avoid making zod a required dependency\r\n return {\r\n _type: 'slug-validator' as const,\r\n validate: zodSlugValidation(customMessage),\r\n message: customMessage || 'Must be a valid slug (lowercase, alphanumeric, and hyphens only, no consecutive hyphens)'\r\n };\r\n }\r\n};\r\n\r\n/**\r\n * Pre-configured Zod schema that auto-converts strings to slugs\r\n * Automatically transforms any string input into a valid slug\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { autoSlugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(autoSlugSchema.transform())\r\n * });\r\n * \r\n * postSchema.parse({ title: 'My Post', slug: 'Hello World!!!' })\r\n * // { title: 'My Post', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport const autoSlugSchema = {\r\n /**\r\n * Get a transform function for Zod\r\n */\r\n transform: (options?: { separator?: string }) => zodSlugTransform(options)\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/slug/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Checks if a string is a valid slug\r\n * A valid slug contains only lowercase alphanumeric characters and hyphens,\r\n * with no consecutive hyphens and no leading/trailing hyphens\r\n * \r\n * @param slug - The string to validate\r\n * @returns True if the string is a valid slug, false otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * isValidSlug('hello-world') // true\r\n * isValidSlug('hello--world') // false (consecutive hyphens)\r\n * isValidSlug('Hello-World') // false (uppercase)\r\n * isValidSlug('-hello-world') // false (leading hyphen)\r\n * isValidSlug('hello_world') // false (underscore not allowed)\r\n * ```\r\n */\r\nexport function isValidSlug(\r\n slug: string,\r\n options: { allowDots?: boolean } = {}\r\n): boolean {\r\n if (!slug || typeof slug !== 'string') {\r\n return false;\r\n }\r\n\r\n const { allowDots = false } = options;\r\n\r\n // Check if slug matches the pattern:\r\n // - starts with alphanumeric\r\n // - ends with alphanumeric\r\n // - contains only lowercase alphanumeric and single hyphens (and dots if allowed)\r\n // - no consecutive separators (hyphens or dots)\r\n \r\n if (allowDots) {\r\n // pattern allowing dots:\r\n // starts with alphanumeric\r\n // middle: alphanumeric or single hyphen/dot followed by alphanumeric\r\n // ends with alphanumeric\r\n const slugWithDotsPattern = /^[a-z0-9]+(?:[-.][a-z0-9]+)*$/;\r\n return slugWithDotsPattern.test(slug);\r\n }\r\n\r\n const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n \r\n return slugPattern.test(slug);\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-safe slug\r\n * - Converts to lowercase\r\n * - Removes special characters\r\n * - Replaces spaces and underscores with hyphens\r\n * - Removes consecutive hyphens\r\n * - Trims leading and trailing hyphens\r\n * \r\n * @param text - The string to convert to a slug\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns A URL-safe slug\r\n * \r\n * @example\r\n * ```ts\r\n * convertToSlug('Hello World') // 'hello-world'\r\n * convertToSlug('Hello World!!!') // 'hello-world'\r\n * convertToSlug('Hello_World') // 'hello-world'\r\n * convertToSlug(' Hello World ') // 'hello-world'\r\n * convertToSlug('Hello---World') // 'hello-world'\r\n * convertToSlug('Café & Restaurant') // 'cafe-restaurant'\r\n * convertToSlug('Product #123') // 'product-123'\r\n * ```\r\n */\r\nexport function convertToSlug(\r\n text: string,\r\n options: { separator?: string; allowDots?: boolean } = {}\r\n): string {\r\n const { separator = '-', allowDots = false } = options;\r\n\r\n if (!text || typeof text !== 'string') {\r\n return '';\r\n }\r\n\r\n // Escape separator for use in regex char class\r\n const escapedSeparator = separator.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n\r\n let slug = text\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n // Remove accents and diacritics\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '');\r\n\r\n if (!allowDots) {\r\n // Replace dots with separator\r\n slug = slug.replace(/\\./g, separator);\r\n }\r\n\r\n slug = slug\r\n // Replace spaces, underscores with separator\r\n .replace(/[\\s_]+/g, separator)\r\n // Remove all non-alphanumeric characters except the separator (and dot if allowed)\r\n .replace(new RegExp(`[^a-z0-9${escapedSeparator}${allowDots ? '\\\\.' : ''}]`, 'g'), '');\r\n\r\n if (allowDots) {\r\n // Collapse consecutive separators/dots\r\n // If sequence contains a dot, we generally want to keep it as a dot (e.g. file.-extension -> file.extension)\r\n slug = slug.replace(new RegExp(`[${escapedSeparator}.]+`, 'g'), (match) => {\r\n return match.includes('.') ? '.' : separator;\r\n });\r\n } else {\r\n // Replace multiple consecutive separators with single separator\r\n slug = slug.replace(new RegExp(`${escapedSeparator}+`, 'g'), separator);\r\n }\r\n \r\n // Remove leading and trailing separators (and dots)\r\n const trimRegex = new RegExp(`^[${escapedSeparator}${allowDots ? '\\\\.' : ''}]+|[${escapedSeparator}${allowDots ? '\\\\.' : ''}]+$`, 'g');\r\n return slug.replace(trimRegex, '');\r\n}\r\n\r\n/**\r\n * Generates a unique slug by appending a number if the slug already exists\r\n * \r\n * @param baseSlug - The base slug to make unique\r\n * @param existingSlugs - Array of existing slugs to check against\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use before the number (default: '-')\r\n * @returns A unique slug\r\n * \r\n * @example\r\n * ```ts\r\n * generateUniqueSlug('hello-world', ['hello-world']) // 'hello-world-1'\r\n * generateUniqueSlug('hello-world', ['hello-world', 'hello-world-1']) // 'hello-world-2'\r\n * generateUniqueSlug('hello-world', []) // 'hello-world'\r\n * ```\r\n */\r\nexport function generateUniqueSlug(\r\n baseSlug: string,\r\n existingSlugs: string[],\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!existingSlugs.includes(baseSlug)) {\r\n return baseSlug;\r\n }\r\n\r\n let counter = 1;\r\n let uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n\r\n while (existingSlugs.includes(uniqueSlug)) {\r\n counter++;\r\n uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n }\r\n\r\n return uniqueSlug;\r\n}\r\n\r\n/**\r\n * Creates a Zod refinement function for slug validation\r\n * Use with z.string().refine() or z.string().superRefine()\r\n * \r\n * @param optionsOrMessage - Custom error message or options object\r\n * @returns Refinement function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugValidation } from '@digicroz/js-kit';\r\n * \r\n * // Basic usage\r\n * const schema = z.object({\r\n * slug: z.string().refine(zodSlugValidation(), {\r\n * message: 'Invalid slug format'\r\n * })\r\n * });\r\n * \r\n * // Allow dots (e.g. for filenames)\r\n * const fileSchema = z.object({\r\n * filename: z.string().refine(zodSlugValidation({ allowDots: true }), {\r\n * message: 'Invalid filename format'\r\n * })\r\n * });\r\n * ```\r\n */\r\nexport function zodSlugValidation(\r\n optionsOrMessage?: string | { message?: string; allowDots?: boolean }\r\n) {\r\n const options =\r\n typeof optionsOrMessage === 'string'\r\n ? { message: optionsOrMessage }\r\n : optionsOrMessage || {};\r\n \r\n return (val: string) => isValidSlug(val, { allowDots: options.allowDots });\r\n}\r\n\r\n/**\r\n * Creates a Zod transform function that converts strings to slugs\r\n * Use with z.string().transform()\r\n * \r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @param options.allowDots - Whether to allow dots in the slug (default: false)\r\n * @returns Transform function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugTransform } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(zodSlugTransform())\r\n * });\r\n * \r\n * schema.parse({ title: 'Hello', slug: 'Hello World!!!' })\r\n * // { title: 'Hello', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport function zodSlugTransform(options?: { separator?: string; allowDots?: boolean }) {\r\n return (val: string) => convertToSlug(val, options);\r\n}\r\n\r\n/**\r\n * Pre-configured Zod schema for slug validation\r\n * Validates that the string is a valid slug format\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { slugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * slug: slugSchema\r\n * });\r\n * \r\n * postSchema.parse({ slug: 'hello-world' }); // ✓ Valid\r\n * postSchema.parse({ slug: 'Hello World' }); // ✗ Invalid\r\n * ```\r\n */\r\nexport const slugSchema = {\r\n /**\r\n * Get a Zod string schema that validates slug format\r\n * Requires zod to be installed: npm install zod\r\n */\r\n create: (\r\n customMessageOrOptions?: string | { message?: string; allowDots?: boolean }\r\n ) => {\r\n // Dynamic import to avoid making zod a required dependency\r\n const options =\r\n typeof customMessageOrOptions === 'string'\r\n ? { message: customMessageOrOptions }\r\n : customMessageOrOptions || {};\r\n \r\n const message =\r\n options.message ||\r\n 'Must be a valid slug (lowercase, alphanumeric, and hyphens only, no consecutive hyphens)';\r\n\r\n return {\r\n _type: 'slug-validator' as const,\r\n validate: zodSlugValidation(options),\r\n message\r\n };\r\n }\r\n};\r\n\r\n/**\r\n * Pre-configured Zod schema that auto-converts strings to slugs\r\n * Automatically transforms any string input into a valid slug\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { autoSlugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(autoSlugSchema.transform())\r\n * });\r\n * \r\n * postSchema.parse({ title: 'My Post', slug: 'Hello World!!!' })\r\n * // { title: 'My Post', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport const autoSlugSchema = {\r\n /**\r\n * Get a transform function for Zod\r\n */\r\n transform: (options?: { separator?: string }) => zodSlugTransform(options)\r\n};\r\n"]}
|
package/dist/slug/index.d.cts
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
* isValidSlug('hello_world') // false (underscore not allowed)
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
|
-
declare function isValidSlug(slug: string
|
|
18
|
+
declare function isValidSlug(slug: string, options?: {
|
|
19
|
+
allowDots?: boolean;
|
|
20
|
+
}): boolean;
|
|
19
21
|
/**
|
|
20
22
|
* Converts a string to a URL-safe slug
|
|
21
23
|
* - Converts to lowercase
|
|
@@ -42,6 +44,7 @@ declare function isValidSlug(slug: string): boolean;
|
|
|
42
44
|
*/
|
|
43
45
|
declare function convertToSlug(text: string, options?: {
|
|
44
46
|
separator?: string;
|
|
47
|
+
allowDots?: boolean;
|
|
45
48
|
}): string;
|
|
46
49
|
/**
|
|
47
50
|
* Generates a unique slug by appending a number if the slug already exists
|
|
@@ -66,7 +69,7 @@ declare function generateUniqueSlug(baseSlug: string, existingSlugs: string[], o
|
|
|
66
69
|
* Creates a Zod refinement function for slug validation
|
|
67
70
|
* Use with z.string().refine() or z.string().superRefine()
|
|
68
71
|
*
|
|
69
|
-
* @param
|
|
72
|
+
* @param optionsOrMessage - Custom error message or options object
|
|
70
73
|
* @returns Refinement function for Zod
|
|
71
74
|
*
|
|
72
75
|
* @example
|
|
@@ -74,20 +77,32 @@ declare function generateUniqueSlug(baseSlug: string, existingSlugs: string[], o
|
|
|
74
77
|
* import { z } from 'zod';
|
|
75
78
|
* import { zodSlugValidation } from '@digicroz/js-kit';
|
|
76
79
|
*
|
|
80
|
+
* // Basic usage
|
|
77
81
|
* const schema = z.object({
|
|
78
82
|
* slug: z.string().refine(zodSlugValidation(), {
|
|
79
83
|
* message: 'Invalid slug format'
|
|
80
84
|
* })
|
|
81
85
|
* });
|
|
86
|
+
*
|
|
87
|
+
* // Allow dots (e.g. for filenames)
|
|
88
|
+
* const fileSchema = z.object({
|
|
89
|
+
* filename: z.string().refine(zodSlugValidation({ allowDots: true }), {
|
|
90
|
+
* message: 'Invalid filename format'
|
|
91
|
+
* })
|
|
92
|
+
* });
|
|
82
93
|
* ```
|
|
83
94
|
*/
|
|
84
|
-
declare function zodSlugValidation(
|
|
95
|
+
declare function zodSlugValidation(optionsOrMessage?: string | {
|
|
96
|
+
message?: string;
|
|
97
|
+
allowDots?: boolean;
|
|
98
|
+
}): (val: string) => boolean;
|
|
85
99
|
/**
|
|
86
100
|
* Creates a Zod transform function that converts strings to slugs
|
|
87
101
|
* Use with z.string().transform()
|
|
88
102
|
*
|
|
89
103
|
* @param options - Optional configuration
|
|
90
104
|
* @param options.separator - Character to use as separator (default: '-')
|
|
105
|
+
* @param options.allowDots - Whether to allow dots in the slug (default: false)
|
|
91
106
|
* @returns Transform function for Zod
|
|
92
107
|
*
|
|
93
108
|
* @example
|
|
@@ -106,6 +121,7 @@ declare function zodSlugValidation(message?: string): (val: string) => boolean;
|
|
|
106
121
|
*/
|
|
107
122
|
declare function zodSlugTransform(options?: {
|
|
108
123
|
separator?: string;
|
|
124
|
+
allowDots?: boolean;
|
|
109
125
|
}): (val: string) => string;
|
|
110
126
|
/**
|
|
111
127
|
* Pre-configured Zod schema for slug validation
|
|
@@ -129,7 +145,10 @@ declare const slugSchema: {
|
|
|
129
145
|
* Get a Zod string schema that validates slug format
|
|
130
146
|
* Requires zod to be installed: npm install zod
|
|
131
147
|
*/
|
|
132
|
-
create: (
|
|
148
|
+
create: (customMessageOrOptions?: string | {
|
|
149
|
+
message?: string;
|
|
150
|
+
allowDots?: boolean;
|
|
151
|
+
}) => {
|
|
133
152
|
_type: "slug-validator";
|
|
134
153
|
validate: (val: string) => boolean;
|
|
135
154
|
message: string;
|
package/dist/slug/index.d.ts
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
* isValidSlug('hello_world') // false (underscore not allowed)
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
|
-
declare function isValidSlug(slug: string
|
|
18
|
+
declare function isValidSlug(slug: string, options?: {
|
|
19
|
+
allowDots?: boolean;
|
|
20
|
+
}): boolean;
|
|
19
21
|
/**
|
|
20
22
|
* Converts a string to a URL-safe slug
|
|
21
23
|
* - Converts to lowercase
|
|
@@ -42,6 +44,7 @@ declare function isValidSlug(slug: string): boolean;
|
|
|
42
44
|
*/
|
|
43
45
|
declare function convertToSlug(text: string, options?: {
|
|
44
46
|
separator?: string;
|
|
47
|
+
allowDots?: boolean;
|
|
45
48
|
}): string;
|
|
46
49
|
/**
|
|
47
50
|
* Generates a unique slug by appending a number if the slug already exists
|
|
@@ -66,7 +69,7 @@ declare function generateUniqueSlug(baseSlug: string, existingSlugs: string[], o
|
|
|
66
69
|
* Creates a Zod refinement function for slug validation
|
|
67
70
|
* Use with z.string().refine() or z.string().superRefine()
|
|
68
71
|
*
|
|
69
|
-
* @param
|
|
72
|
+
* @param optionsOrMessage - Custom error message or options object
|
|
70
73
|
* @returns Refinement function for Zod
|
|
71
74
|
*
|
|
72
75
|
* @example
|
|
@@ -74,20 +77,32 @@ declare function generateUniqueSlug(baseSlug: string, existingSlugs: string[], o
|
|
|
74
77
|
* import { z } from 'zod';
|
|
75
78
|
* import { zodSlugValidation } from '@digicroz/js-kit';
|
|
76
79
|
*
|
|
80
|
+
* // Basic usage
|
|
77
81
|
* const schema = z.object({
|
|
78
82
|
* slug: z.string().refine(zodSlugValidation(), {
|
|
79
83
|
* message: 'Invalid slug format'
|
|
80
84
|
* })
|
|
81
85
|
* });
|
|
86
|
+
*
|
|
87
|
+
* // Allow dots (e.g. for filenames)
|
|
88
|
+
* const fileSchema = z.object({
|
|
89
|
+
* filename: z.string().refine(zodSlugValidation({ allowDots: true }), {
|
|
90
|
+
* message: 'Invalid filename format'
|
|
91
|
+
* })
|
|
92
|
+
* });
|
|
82
93
|
* ```
|
|
83
94
|
*/
|
|
84
|
-
declare function zodSlugValidation(
|
|
95
|
+
declare function zodSlugValidation(optionsOrMessage?: string | {
|
|
96
|
+
message?: string;
|
|
97
|
+
allowDots?: boolean;
|
|
98
|
+
}): (val: string) => boolean;
|
|
85
99
|
/**
|
|
86
100
|
* Creates a Zod transform function that converts strings to slugs
|
|
87
101
|
* Use with z.string().transform()
|
|
88
102
|
*
|
|
89
103
|
* @param options - Optional configuration
|
|
90
104
|
* @param options.separator - Character to use as separator (default: '-')
|
|
105
|
+
* @param options.allowDots - Whether to allow dots in the slug (default: false)
|
|
91
106
|
* @returns Transform function for Zod
|
|
92
107
|
*
|
|
93
108
|
* @example
|
|
@@ -106,6 +121,7 @@ declare function zodSlugValidation(message?: string): (val: string) => boolean;
|
|
|
106
121
|
*/
|
|
107
122
|
declare function zodSlugTransform(options?: {
|
|
108
123
|
separator?: string;
|
|
124
|
+
allowDots?: boolean;
|
|
109
125
|
}): (val: string) => string;
|
|
110
126
|
/**
|
|
111
127
|
* Pre-configured Zod schema for slug validation
|
|
@@ -129,7 +145,10 @@ declare const slugSchema: {
|
|
|
129
145
|
* Get a Zod string schema that validates slug format
|
|
130
146
|
* Requires zod to be installed: npm install zod
|
|
131
147
|
*/
|
|
132
|
-
create: (
|
|
148
|
+
create: (customMessageOrOptions?: string | {
|
|
149
|
+
message?: string;
|
|
150
|
+
allowDots?: boolean;
|
|
151
|
+
}) => {
|
|
133
152
|
_type: "slug-validator";
|
|
134
153
|
validate: (val: string) => boolean;
|
|
135
154
|
message: string;
|
package/dist/slug/index.js
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
// src/slug/index.ts
|
|
2
|
-
function isValidSlug(slug) {
|
|
2
|
+
function isValidSlug(slug, options = {}) {
|
|
3
3
|
if (!slug || typeof slug !== "string") {
|
|
4
4
|
return false;
|
|
5
5
|
}
|
|
6
|
+
const { allowDots = false } = options;
|
|
7
|
+
if (allowDots) {
|
|
8
|
+
const slugWithDotsPattern = /^[a-z0-9]+(?:[-.][a-z0-9]+)*$/;
|
|
9
|
+
return slugWithDotsPattern.test(slug);
|
|
10
|
+
}
|
|
6
11
|
const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
12
|
return slugPattern.test(slug);
|
|
8
13
|
}
|
|
9
14
|
function convertToSlug(text, options = {}) {
|
|
10
|
-
const { separator = "-" } = options;
|
|
15
|
+
const { separator = "-", allowDots = false } = options;
|
|
11
16
|
if (!text || typeof text !== "string") {
|
|
12
17
|
return "";
|
|
13
18
|
}
|
|
14
|
-
|
|
19
|
+
const escapedSeparator = separator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20
|
+
let slug = text.toString().toLowerCase().trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
21
|
+
if (!allowDots) {
|
|
22
|
+
slug = slug.replace(/\./g, separator);
|
|
23
|
+
}
|
|
24
|
+
slug = slug.replace(/[\s_]+/g, separator).replace(new RegExp(`[^a-z0-9${escapedSeparator}${allowDots ? "\\." : ""}]`, "g"), "");
|
|
25
|
+
if (allowDots) {
|
|
26
|
+
slug = slug.replace(new RegExp(`[${escapedSeparator}.]+`, "g"), (match) => {
|
|
27
|
+
return match.includes(".") ? "." : separator;
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
slug = slug.replace(new RegExp(`${escapedSeparator}+`, "g"), separator);
|
|
31
|
+
}
|
|
32
|
+
const trimRegex = new RegExp(`^[${escapedSeparator}${allowDots ? "\\." : ""}]+|[${escapedSeparator}${allowDots ? "\\." : ""}]+$`, "g");
|
|
33
|
+
return slug.replace(trimRegex, "");
|
|
15
34
|
}
|
|
16
35
|
function generateUniqueSlug(baseSlug, existingSlugs, options = {}) {
|
|
17
36
|
const { separator = "-" } = options;
|
|
@@ -26,8 +45,9 @@ function generateUniqueSlug(baseSlug, existingSlugs, options = {}) {
|
|
|
26
45
|
}
|
|
27
46
|
return uniqueSlug;
|
|
28
47
|
}
|
|
29
|
-
function zodSlugValidation(
|
|
30
|
-
|
|
48
|
+
function zodSlugValidation(optionsOrMessage) {
|
|
49
|
+
const options = typeof optionsOrMessage === "string" ? { } : optionsOrMessage || {};
|
|
50
|
+
return (val) => isValidSlug(val, { allowDots: options.allowDots });
|
|
31
51
|
}
|
|
32
52
|
function zodSlugTransform(options) {
|
|
33
53
|
return (val) => convertToSlug(val, options);
|
|
@@ -37,11 +57,13 @@ var slugSchema = {
|
|
|
37
57
|
* Get a Zod string schema that validates slug format
|
|
38
58
|
* Requires zod to be installed: npm install zod
|
|
39
59
|
*/
|
|
40
|
-
create: (
|
|
60
|
+
create: (customMessageOrOptions) => {
|
|
61
|
+
const options = typeof customMessageOrOptions === "string" ? { message: customMessageOrOptions } : customMessageOrOptions || {};
|
|
62
|
+
const message = options.message || "Must be a valid slug (lowercase, alphanumeric, and hyphens only, no consecutive hyphens)";
|
|
41
63
|
return {
|
|
42
64
|
_type: "slug-validator",
|
|
43
|
-
validate: zodSlugValidation(),
|
|
44
|
-
message
|
|
65
|
+
validate: zodSlugValidation(options),
|
|
66
|
+
message
|
|
45
67
|
};
|
|
46
68
|
}
|
|
47
69
|
};
|
package/dist/slug/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/slug/index.ts"],"names":[],"mappings":";AAiBO,SAAS,YAAY,IAAA,EAAuB;AACjD,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,KAAA;AAAA;AAOT,EAAA,MAAM,WAAA,GAAc,4BAAA;AAEpB,EAAA,OAAO,WAAA,CAAY,KAAK,IAAI,CAAA;AAC9B;AA0BO,SAAS,aAAA,CACd,IAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAI,GAAI,OAAA;AAE5B,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,EAAA;AAAA;AAGT,EAAA,OAAO,IAAA,CACJ,UAAS,CACT,WAAA,GACA,IAAA,EAAK,CAEL,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,oBAAoB,EAAE,CAAA,CAE9B,QAAQ,SAAA,EAAW,SAAS,EAE5B,OAAA,CAAQ,IAAI,MAAA,CAAO,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA,EAAG,EAAE,EAEpD,OAAA,CAAQ,IAAI,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA,EAAG,SAAS,EAEnD,OAAA,CAAQ,IAAI,OAAO,CAAA,CAAA,EAAI,SAAS,KAAK,SAAS,CAAA,EAAA,CAAA,EAAM,GAAG,CAAA,EAAG,EAAE,CAAA;AACjE;AAkBO,SAAS,kBAAA,CACd,QAAA,EACA,aAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAI,GAAI,OAAA;AAE5B,EAAA,IAAI,CAAC,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA,EAAG;AACrC,IAAA,OAAO,QAAA;AAAA;AAGT,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,aAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAElD,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,UAAU,CAAA,EAAG;AACzC,IAAA,OAAA,EAAA;AACA,IAAA,UAAA,GAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAAA;AAGhD,EAAA,OAAO,UAAA;AACT;AAqBO,SAAS,kBAAkB,OAAA,EAAkB;AAClD,EAAA,OAAO,CAAC,GAAA,KAAgB,WAAA,CAAY,GAAG,CAAA;AACzC;AAwBO,SAAS,iBAAiB,OAAA,EAAkC;AACjE,EAAA,OAAO,CAAC,GAAA,KAAgB,aAAA,CAAc,GAAA,EAAK,OAAO,CAAA;AACpD;AAmBO,IAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAA,EAAQ,CAAC,aAAA,KAA2B;AAElC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,gBAAA;AAAA,MACP,QAAA,EAAU,kBAA+B,CAAA;AAAA,MACzC,SAAS,aAAA,IAAiB;AAAA,KAC5B;AAAA;AAEJ;AAoBO,IAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA,EAI5B,SAAA,EAAW,CAAC,OAAA,KAAqC,gBAAA,CAAiB,OAAO;AAC3E","file":"index.js","sourcesContent":["/**\r\n * Checks if a string is a valid slug\r\n * A valid slug contains only lowercase alphanumeric characters and hyphens,\r\n * with no consecutive hyphens and no leading/trailing hyphens\r\n * \r\n * @param slug - The string to validate\r\n * @returns True if the string is a valid slug, false otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * isValidSlug('hello-world') // true\r\n * isValidSlug('hello--world') // false (consecutive hyphens)\r\n * isValidSlug('Hello-World') // false (uppercase)\r\n * isValidSlug('-hello-world') // false (leading hyphen)\r\n * isValidSlug('hello_world') // false (underscore not allowed)\r\n * ```\r\n */\r\nexport function isValidSlug(slug: string): boolean {\r\n if (!slug || typeof slug !== 'string') {\r\n return false;\r\n }\r\n\r\n // Check if slug matches the pattern:\r\n // - starts with alphanumeric\r\n // - ends with alphanumeric\r\n // - contains only lowercase alphanumeric and single hyphens\r\n const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n \r\n return slugPattern.test(slug);\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-safe slug\r\n * - Converts to lowercase\r\n * - Removes special characters\r\n * - Replaces spaces and underscores with hyphens\r\n * - Removes consecutive hyphens\r\n * - Trims leading and trailing hyphens\r\n * \r\n * @param text - The string to convert to a slug\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns A URL-safe slug\r\n * \r\n * @example\r\n * ```ts\r\n * convertToSlug('Hello World') // 'hello-world'\r\n * convertToSlug('Hello World!!!') // 'hello-world'\r\n * convertToSlug('Hello_World') // 'hello-world'\r\n * convertToSlug(' Hello World ') // 'hello-world'\r\n * convertToSlug('Hello---World') // 'hello-world'\r\n * convertToSlug('Café & Restaurant') // 'cafe-restaurant'\r\n * convertToSlug('Product #123') // 'product-123'\r\n * ```\r\n */\r\nexport function convertToSlug(\r\n text: string,\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!text || typeof text !== 'string') {\r\n return '';\r\n }\r\n\r\n return text\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n // Remove accents and diacritics\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n // Replace spaces, underscores, and other common separators with separator\r\n .replace(/[\\s_]+/g, separator)\r\n // Remove all non-alphanumeric characters except the separator\r\n .replace(new RegExp(`[^a-z0-9${separator}]`, 'g'), '')\r\n // Replace multiple consecutive separators with single separator\r\n .replace(new RegExp(`${separator}+`, 'g'), separator)\r\n // Remove leading and trailing separators\r\n .replace(new RegExp(`^${separator}+|${separator}+$`, 'g'), '');\r\n}\r\n\r\n/**\r\n * Generates a unique slug by appending a number if the slug already exists\r\n * \r\n * @param baseSlug - The base slug to make unique\r\n * @param existingSlugs - Array of existing slugs to check against\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use before the number (default: '-')\r\n * @returns A unique slug\r\n * \r\n * @example\r\n * ```ts\r\n * generateUniqueSlug('hello-world', ['hello-world']) // 'hello-world-1'\r\n * generateUniqueSlug('hello-world', ['hello-world', 'hello-world-1']) // 'hello-world-2'\r\n * generateUniqueSlug('hello-world', []) // 'hello-world'\r\n * ```\r\n */\r\nexport function generateUniqueSlug(\r\n baseSlug: string,\r\n existingSlugs: string[],\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!existingSlugs.includes(baseSlug)) {\r\n return baseSlug;\r\n }\r\n\r\n let counter = 1;\r\n let uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n\r\n while (existingSlugs.includes(uniqueSlug)) {\r\n counter++;\r\n uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n }\r\n\r\n return uniqueSlug;\r\n}\r\n\r\n/**\r\n * Creates a Zod refinement function for slug validation\r\n * Use with z.string().refine() or z.string().superRefine()\r\n * \r\n * @param message - Custom error message (optional)\r\n * @returns Refinement function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugValidation } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * slug: z.string().refine(zodSlugValidation(), {\r\n * message: 'Invalid slug format'\r\n * })\r\n * });\r\n * ```\r\n */\r\nexport function zodSlugValidation(message?: string) {\r\n return (val: string) => isValidSlug(val);\r\n}\r\n\r\n/**\r\n * Creates a Zod transform function that converts strings to slugs\r\n * Use with z.string().transform()\r\n * \r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns Transform function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugTransform } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(zodSlugTransform())\r\n * });\r\n * \r\n * schema.parse({ title: 'Hello', slug: 'Hello World!!!' })\r\n * // { title: 'Hello', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport function zodSlugTransform(options?: { separator?: string }) {\r\n return (val: string) => convertToSlug(val, options);\r\n}\r\n\r\n/**\r\n * Pre-configured Zod schema for slug validation\r\n * Validates that the string is a valid slug format\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { slugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * slug: slugSchema\r\n * });\r\n * \r\n * postSchema.parse({ slug: 'hello-world' }); // ✓ Valid\r\n * postSchema.parse({ slug: 'Hello World' }); // ✗ Invalid\r\n * ```\r\n */\r\nexport const slugSchema = {\r\n /**\r\n * Get a Zod string schema that validates slug format\r\n * Requires zod to be installed: npm install zod\r\n */\r\n create: (customMessage?: string) => {\r\n // Dynamic import to avoid making zod a required dependency\r\n return {\r\n _type: 'slug-validator' as const,\r\n validate: zodSlugValidation(customMessage),\r\n message: customMessage || 'Must be a valid slug (lowercase, alphanumeric, and hyphens only, no consecutive hyphens)'\r\n };\r\n }\r\n};\r\n\r\n/**\r\n * Pre-configured Zod schema that auto-converts strings to slugs\r\n * Automatically transforms any string input into a valid slug\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { autoSlugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(autoSlugSchema.transform())\r\n * });\r\n * \r\n * postSchema.parse({ title: 'My Post', slug: 'Hello World!!!' })\r\n * // { title: 'My Post', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport const autoSlugSchema = {\r\n /**\r\n * Get a transform function for Zod\r\n */\r\n transform: (options?: { separator?: string }) => zodSlugTransform(options)\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/slug/index.ts"],"names":[],"mappings":";AAiBO,SAAS,WAAA,CACd,IAAA,EACA,OAAA,GAAmC,EAAC,EAC3B;AACT,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,KAAA;AAAA;AAGT,EAAA,MAAM,EAAE,SAAA,GAAY,KAAA,EAAM,GAAI,OAAA;AAQ9B,EAAA,IAAI,SAAA,EAAW;AAKb,IAAA,MAAM,mBAAA,GAAsB,+BAAA;AAC5B,IAAA,OAAO,mBAAA,CAAoB,KAAK,IAAI,CAAA;AAAA;AAGtC,EAAA,MAAM,WAAA,GAAc,4BAAA;AAEpB,EAAA,OAAO,WAAA,CAAY,KAAK,IAAI,CAAA;AAC9B;AA0BO,SAAS,aAAA,CACd,IAAA,EACA,OAAA,GAAuD,EAAC,EAChD;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAK,SAAA,GAAY,OAAM,GAAI,OAAA;AAE/C,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,EAAA;AAAA;AAIT,EAAA,MAAM,gBAAA,GAAmB,SAAA,CAAU,OAAA,CAAQ,qBAAA,EAAuB,MAAM,CAAA;AAExE,EAAA,IAAI,IAAA,GAAO,IAAA,CACR,QAAA,EAAS,CACT,WAAA,EAAY,CACZ,IAAA,EAAK,CAEL,SAAA,CAAU,KAAK,CAAA,CACf,OAAA,CAAQ,oBAAoB,EAAE,CAAA;AAEjC,EAAA,IAAI,CAAC,SAAA,EAAW;AAEd,IAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,SAAS,CAAA;AAAA;AAGtC,EAAA,IAAA,GAAO,KAEJ,OAAA,CAAQ,SAAA,EAAW,SAAS,CAAA,CAE5B,QAAQ,IAAI,MAAA,CAAO,CAAA,QAAA,EAAW,gBAAgB,GAAG,SAAA,GAAY,KAAA,GAAQ,EAAE,CAAA,CAAA,CAAA,EAAK,GAAG,GAAG,EAAE,CAAA;AAEvF,EAAA,IAAI,SAAA,EAAW;AAGb,IAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,gBAAgB,CAAA,GAAA,CAAA,EAAO,GAAG,CAAA,EAAG,CAAC,KAAA,KAAU;AACzE,MAAA,OAAO,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA,GAAI,GAAA,GAAM,SAAA;AAAA,KACpC,CAAA;AAAA,GACH,MAAO;AAEL,IAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,IAAI,MAAA,CAAO,GAAG,gBAAgB,CAAA,CAAA,CAAA,EAAK,GAAG,CAAA,EAAG,SAAS,CAAA;AAAA;AAIxE,EAAA,MAAM,YAAY,IAAI,MAAA,CAAO,CAAA,EAAA,EAAK,gBAAgB,GAAG,SAAA,GAAY,KAAA,GAAQ,EAAE,CAAA,IAAA,EAAO,gBAAgB,CAAA,EAAG,SAAA,GAAY,KAAA,GAAQ,EAAE,OAAO,GAAG,CAAA;AACrI,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AACnC;AAkBO,SAAS,kBAAA,CACd,QAAA,EACA,aAAA,EACA,OAAA,GAAkC,EAAC,EAC3B;AACR,EAAA,MAAM,EAAE,SAAA,GAAY,GAAA,EAAI,GAAI,OAAA;AAE5B,EAAA,IAAI,CAAC,aAAA,CAAc,QAAA,CAAS,QAAQ,CAAA,EAAG;AACrC,IAAA,OAAO,QAAA;AAAA;AAGT,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,aAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAElD,EAAA,OAAO,aAAA,CAAc,QAAA,CAAS,UAAU,CAAA,EAAG;AACzC,IAAA,OAAA,EAAA;AACA,IAAA,UAAA,GAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,SAAS,GAAG,OAAO,CAAA,CAAA;AAAA;AAGhD,EAAA,OAAO,UAAA;AACT;AA6BO,SAAS,kBACd,gBAAA,EACA;AACA,EAAA,MAAM,OAAA,GACJ,OAAO,gBAAA,KAAqB,QAAA,GACxB,EAA4B,CAAA,GAC5B,gBAAA,IAAoB,EAAC;AAE3B,EAAA,OAAO,CAAC,QAAgB,WAAA,CAAY,GAAA,EAAK,EAAE,SAAA,EAAW,OAAA,CAAQ,WAAW,CAAA;AAC3E;AAyBO,SAAS,iBAAiB,OAAA,EAAuD;AACtF,EAAA,OAAO,CAAC,GAAA,KAAgB,aAAA,CAAc,GAAA,EAAK,OAAO,CAAA;AACpD;AAmBO,IAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAA,EAAQ,CACN,sBAAA,KACG;AAEH,IAAA,MAAM,OAAA,GACJ,OAAO,sBAAA,KAA2B,QAAA,GAC9B,EAAE,OAAA,EAAS,sBAAA,EAAuB,GAClC,sBAAA,IAA0B,EAAC;AAEjC,IAAA,MAAM,OAAA,GACJ,QAAQ,OAAA,IACR,0FAAA;AAEF,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,gBAAA;AAAA,MACP,QAAA,EAAU,kBAAkB,OAAO,CAAA;AAAA,MACnC;AAAA,KACF;AAAA;AAEJ;AAoBO,IAAM,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA,EAI5B,SAAA,EAAW,CAAC,OAAA,KAAqC,gBAAA,CAAiB,OAAO;AAC3E","file":"index.js","sourcesContent":["/**\r\n * Checks if a string is a valid slug\r\n * A valid slug contains only lowercase alphanumeric characters and hyphens,\r\n * with no consecutive hyphens and no leading/trailing hyphens\r\n * \r\n * @param slug - The string to validate\r\n * @returns True if the string is a valid slug, false otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * isValidSlug('hello-world') // true\r\n * isValidSlug('hello--world') // false (consecutive hyphens)\r\n * isValidSlug('Hello-World') // false (uppercase)\r\n * isValidSlug('-hello-world') // false (leading hyphen)\r\n * isValidSlug('hello_world') // false (underscore not allowed)\r\n * ```\r\n */\r\nexport function isValidSlug(\r\n slug: string,\r\n options: { allowDots?: boolean } = {}\r\n): boolean {\r\n if (!slug || typeof slug !== 'string') {\r\n return false;\r\n }\r\n\r\n const { allowDots = false } = options;\r\n\r\n // Check if slug matches the pattern:\r\n // - starts with alphanumeric\r\n // - ends with alphanumeric\r\n // - contains only lowercase alphanumeric and single hyphens (and dots if allowed)\r\n // - no consecutive separators (hyphens or dots)\r\n \r\n if (allowDots) {\r\n // pattern allowing dots:\r\n // starts with alphanumeric\r\n // middle: alphanumeric or single hyphen/dot followed by alphanumeric\r\n // ends with alphanumeric\r\n const slugWithDotsPattern = /^[a-z0-9]+(?:[-.][a-z0-9]+)*$/;\r\n return slugWithDotsPattern.test(slug);\r\n }\r\n\r\n const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\r\n \r\n return slugPattern.test(slug);\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-safe slug\r\n * - Converts to lowercase\r\n * - Removes special characters\r\n * - Replaces spaces and underscores with hyphens\r\n * - Removes consecutive hyphens\r\n * - Trims leading and trailing hyphens\r\n * \r\n * @param text - The string to convert to a slug\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @returns A URL-safe slug\r\n * \r\n * @example\r\n * ```ts\r\n * convertToSlug('Hello World') // 'hello-world'\r\n * convertToSlug('Hello World!!!') // 'hello-world'\r\n * convertToSlug('Hello_World') // 'hello-world'\r\n * convertToSlug(' Hello World ') // 'hello-world'\r\n * convertToSlug('Hello---World') // 'hello-world'\r\n * convertToSlug('Café & Restaurant') // 'cafe-restaurant'\r\n * convertToSlug('Product #123') // 'product-123'\r\n * ```\r\n */\r\nexport function convertToSlug(\r\n text: string,\r\n options: { separator?: string; allowDots?: boolean } = {}\r\n): string {\r\n const { separator = '-', allowDots = false } = options;\r\n\r\n if (!text || typeof text !== 'string') {\r\n return '';\r\n }\r\n\r\n // Escape separator for use in regex char class\r\n const escapedSeparator = separator.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n\r\n let slug = text\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n // Remove accents and diacritics\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '');\r\n\r\n if (!allowDots) {\r\n // Replace dots with separator\r\n slug = slug.replace(/\\./g, separator);\r\n }\r\n\r\n slug = slug\r\n // Replace spaces, underscores with separator\r\n .replace(/[\\s_]+/g, separator)\r\n // Remove all non-alphanumeric characters except the separator (and dot if allowed)\r\n .replace(new RegExp(`[^a-z0-9${escapedSeparator}${allowDots ? '\\\\.' : ''}]`, 'g'), '');\r\n\r\n if (allowDots) {\r\n // Collapse consecutive separators/dots\r\n // If sequence contains a dot, we generally want to keep it as a dot (e.g. file.-extension -> file.extension)\r\n slug = slug.replace(new RegExp(`[${escapedSeparator}.]+`, 'g'), (match) => {\r\n return match.includes('.') ? '.' : separator;\r\n });\r\n } else {\r\n // Replace multiple consecutive separators with single separator\r\n slug = slug.replace(new RegExp(`${escapedSeparator}+`, 'g'), separator);\r\n }\r\n \r\n // Remove leading and trailing separators (and dots)\r\n const trimRegex = new RegExp(`^[${escapedSeparator}${allowDots ? '\\\\.' : ''}]+|[${escapedSeparator}${allowDots ? '\\\\.' : ''}]+$`, 'g');\r\n return slug.replace(trimRegex, '');\r\n}\r\n\r\n/**\r\n * Generates a unique slug by appending a number if the slug already exists\r\n * \r\n * @param baseSlug - The base slug to make unique\r\n * @param existingSlugs - Array of existing slugs to check against\r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use before the number (default: '-')\r\n * @returns A unique slug\r\n * \r\n * @example\r\n * ```ts\r\n * generateUniqueSlug('hello-world', ['hello-world']) // 'hello-world-1'\r\n * generateUniqueSlug('hello-world', ['hello-world', 'hello-world-1']) // 'hello-world-2'\r\n * generateUniqueSlug('hello-world', []) // 'hello-world'\r\n * ```\r\n */\r\nexport function generateUniqueSlug(\r\n baseSlug: string,\r\n existingSlugs: string[],\r\n options: { separator?: string } = {}\r\n): string {\r\n const { separator = '-' } = options;\r\n\r\n if (!existingSlugs.includes(baseSlug)) {\r\n return baseSlug;\r\n }\r\n\r\n let counter = 1;\r\n let uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n\r\n while (existingSlugs.includes(uniqueSlug)) {\r\n counter++;\r\n uniqueSlug = `${baseSlug}${separator}${counter}`;\r\n }\r\n\r\n return uniqueSlug;\r\n}\r\n\r\n/**\r\n * Creates a Zod refinement function for slug validation\r\n * Use with z.string().refine() or z.string().superRefine()\r\n * \r\n * @param optionsOrMessage - Custom error message or options object\r\n * @returns Refinement function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugValidation } from '@digicroz/js-kit';\r\n * \r\n * // Basic usage\r\n * const schema = z.object({\r\n * slug: z.string().refine(zodSlugValidation(), {\r\n * message: 'Invalid slug format'\r\n * })\r\n * });\r\n * \r\n * // Allow dots (e.g. for filenames)\r\n * const fileSchema = z.object({\r\n * filename: z.string().refine(zodSlugValidation({ allowDots: true }), {\r\n * message: 'Invalid filename format'\r\n * })\r\n * });\r\n * ```\r\n */\r\nexport function zodSlugValidation(\r\n optionsOrMessage?: string | { message?: string; allowDots?: boolean }\r\n) {\r\n const options =\r\n typeof optionsOrMessage === 'string'\r\n ? { message: optionsOrMessage }\r\n : optionsOrMessage || {};\r\n \r\n return (val: string) => isValidSlug(val, { allowDots: options.allowDots });\r\n}\r\n\r\n/**\r\n * Creates a Zod transform function that converts strings to slugs\r\n * Use with z.string().transform()\r\n * \r\n * @param options - Optional configuration\r\n * @param options.separator - Character to use as separator (default: '-')\r\n * @param options.allowDots - Whether to allow dots in the slug (default: false)\r\n * @returns Transform function for Zod\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { zodSlugTransform } from '@digicroz/js-kit';\r\n * \r\n * const schema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(zodSlugTransform())\r\n * });\r\n * \r\n * schema.parse({ title: 'Hello', slug: 'Hello World!!!' })\r\n * // { title: 'Hello', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport function zodSlugTransform(options?: { separator?: string; allowDots?: boolean }) {\r\n return (val: string) => convertToSlug(val, options);\r\n}\r\n\r\n/**\r\n * Pre-configured Zod schema for slug validation\r\n * Validates that the string is a valid slug format\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { slugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * slug: slugSchema\r\n * });\r\n * \r\n * postSchema.parse({ slug: 'hello-world' }); // ✓ Valid\r\n * postSchema.parse({ slug: 'Hello World' }); // ✗ Invalid\r\n * ```\r\n */\r\nexport const slugSchema = {\r\n /**\r\n * Get a Zod string schema that validates slug format\r\n * Requires zod to be installed: npm install zod\r\n */\r\n create: (\r\n customMessageOrOptions?: string | { message?: string; allowDots?: boolean }\r\n ) => {\r\n // Dynamic import to avoid making zod a required dependency\r\n const options =\r\n typeof customMessageOrOptions === 'string'\r\n ? { message: customMessageOrOptions }\r\n : customMessageOrOptions || {};\r\n \r\n const message =\r\n options.message ||\r\n 'Must be a valid slug (lowercase, alphanumeric, and hyphens only, no consecutive hyphens)';\r\n\r\n return {\r\n _type: 'slug-validator' as const,\r\n validate: zodSlugValidation(options),\r\n message\r\n };\r\n }\r\n};\r\n\r\n/**\r\n * Pre-configured Zod schema that auto-converts strings to slugs\r\n * Automatically transforms any string input into a valid slug\r\n * \r\n * @example\r\n * ```ts\r\n * import { z } from 'zod';\r\n * import { autoSlugSchema } from '@digicroz/js-kit';\r\n * \r\n * const postSchema = z.object({\r\n * title: z.string(),\r\n * slug: z.string().transform(autoSlugSchema.transform())\r\n * });\r\n * \r\n * postSchema.parse({ title: 'My Post', slug: 'Hello World!!!' })\r\n * // { title: 'My Post', slug: 'hello-world' }\r\n * ```\r\n */\r\nexport const autoSlugSchema = {\r\n /**\r\n * Get a transform function for Zod\r\n */\r\n transform: (options?: { separator?: string }) => zodSlugTransform(options)\r\n};\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digicroz/js-kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Modern TypeScript utility library with tree-shaking support - Array, String, Number, Sleep, and Time utilities for JavaScript and TypeScript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|