Created
June 6, 2025 07:50
-
-
Save mike-at-redspace/a9c5d6e456b49ad90f935d57d98da6c9 to your computer and use it in GitHub Desktop.
Reusable Slug Generator with Stop Word & Format Options
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A simple, customizable slug generator for browser-based inputs. | |
* | |
* Features: | |
* - Optionally lowercases text | |
* - Removes special characters | |
* - Filters out stop words | |
* - Removes numeric digits | |
* - Supports dash or underscore delimiters | |
* - Copy-to-clipboard functionality | |
*/ | |
// Common English stop words to filter out | |
const STOP_WORDS = new Set([ | |
'a', 'an', 'the', 'and', 'or', 'but', 'for', 'nor', 'on', 'at', 'to', 'by', | |
'in', 'of', 'is', 'are', 'am', 'was', 'were', 'be', 'been', 'being', | |
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'shall', 'should', | |
'may', 'might', 'must', 'can', 'could', 'with', 'from', 'as', 'this', 'that', | |
'these', 'those', 'they', 'them', 'their', 'we', 'us', 'our', 'i', 'me', 'my', | |
'he', 'him', 'his', 'she', 'her', 'it', 'its', 'you', 'your' | |
]) | |
// DOM references | |
const titleInput = document.getElementById('title-input') | |
const slugOutput = document.getElementById('slug-output') | |
const copyButton = document.getElementById('copy-button') | |
/** | |
* Transforms a string into a URL-friendly slug based on active options. | |
* @param {string} text - The original input string | |
* @param {Object} options - Customization options | |
* @returns {string} - The generated slug | |
*/ | |
function createSlug(text, options = {}) { | |
const { | |
lowercase = false, | |
removeSpecial = false, | |
removeStopWords = false, | |
removeNumbers = false, | |
delimiter = '-' | |
} = options | |
if (!text) return '' | |
let result = text | |
if (lowercase) { | |
result = result.toLowerCase() | |
} | |
if (removeSpecial) { | |
result = result.replace(/[^\w\s-]/g, '') | |
} | |
if (removeStopWords) { | |
result = result | |
.split(' ') | |
.filter(word => !STOP_WORDS.has(word.toLowerCase())) | |
.join(' ') | |
} | |
if (removeNumbers) { | |
result = result.replace(/[0-9]/g, '') | |
} | |
result = result.trim().replace(/\s+/g, delimiter) | |
result = result | |
.replace(new RegExp(`${delimiter}+`, 'g'), delimiter) | |
.replace(new RegExp(`^${delimiter}|${delimiter}$`, 'g'), '') | |
return result | |
} | |
/** | |
* Reads the UI controls and generates a new slug in the output field. | |
*/ | |
function generateSlugFromInput() { | |
const slug = createSlug(titleInput.value, { | |
lowercase: document.getElementById('lowercase').checked, | |
removeSpecial: document.getElementById('remove-special').checked, | |
removeStopWords: document.getElementById('remove-stop').checked, | |
removeNumbers: document.getElementById('remove-numbers').checked, | |
delimiter: document.getElementById('dash-delimiter').checked ? '-' : '_', | |
}) | |
slugOutput.value = slug | |
} | |
/** | |
* Copies the slug to the clipboard and shows feedback. | |
*/ | |
function copySlugToClipboard() { | |
slugOutput.select() | |
document.execCommand('copy') | |
copyButton.textContent = 'Copied!' | |
setTimeout(() => (copyButton.textContent = 'Copy to Clipboard'), 1500) | |
} | |
// --- Event Bindings --- | |
titleInput.addEventListener('input', generateSlugFromInput) | |
document | |
.querySelectorAll('input[type="radio"], input[type="checkbox"]') | |
.forEach(input => input.addEventListener('change', generateSlugFromInput)) | |
copyButton.addEventListener('click', copySlugToClipboard) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment