URI Slug function composition

Partial Application + Composition by reduce (pipe use another direction of functions in arguments). Added trace utility function to inspect execution of composed functions.

by AntowaKartowa

HTML

<div class="container">
	<div class="input">
		<input type="text" name="text-for-slug" id="field"> 
		<button id="generate">Получить slug</button>
	</div>
	<div id="result"></div>
</div>

CSS

body {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	margin: 0;
	width: 100vw;
	height: 100vh;
}

.container {
	position: relative;
}

.input {
	text-align: center;
}

#result {
	margin: 10px 0;
	font-style: 14px;
	line-height: 21px;
	height: 21px;
}

JavaScript

const partial = (fn, ...args) => fn.length > args.length ? partial.bind(null, fn, ...args) : fn(...args);
const pipe = (...fns) => x => fns.reduce((val, fn) => fn(val), x);

const partialJoin = partial((str, arr) => arr.join(str));
const partialSplit = partial((splitBy, str) => str.split(splitBy));

const toLowerCase = str => str.toLowerCase();
const trim = str => str.trim();

// utility function to inspect composed functions
const trace = partial((label, x) => {
	console.log(`=== ${label}: «${x}»`);
	return x;
});


const translitLower = function(text) {
	text = text
    .replace(/\u042A/g, '')
    .replace(/\u0451/g, 'yo')
    .replace(/\u0439/g, 'i')
    .replace(/\u0446/g, 'ts')
    .replace(/\u0443/g, 'u')
    .replace(/\u043A/g, 'k')
    .replace(/\u0435/g, 'e')
    .replace(/\u043D/g, 'n')
    .replace(/\u0433/g, 'g')
    .replace(/\u0448/g, 'sh')
    .replace(/\u0449/g, 'sch')
    .replace(/\u0437/g, 'z')
    .replace(/\u0445/g, 'h')
    .replace(/\u044A/g, "'")
    .replace(/\u0410/g, 'a')
    .replace(/\u0444/g, 'f')
    .replace(/\u044B/g, 'i')
    .replace(/\u0432/g, 'v')
    .replace(/\u0430/g, 'a')
    .replace(/\u043F/g, 'p')
    .replace(/\u0440/g, 'r')
    .replace(/\u043E/g, 'o')
    .replace(/\u043B/g, 'l')
    .replace(/\u0434/g, 'd')
    .replace(/\u0436/g, 'zh')
    .replace(/\u044D/g, 'e')
    .replace(/\u042C/g, "'")
    .replace(/\u044F/g, 'ya')
    .replace(/\u0447/g, 'ch')
    .replace(/\u0441/g, 's')
    .replace(/\u043C/g, 'm')
    .replace(/\u0438/g, 'i')
    .replace(/\u0442/g, 't')
    .replace(/\u044C/g, "'")
    .replace(/\u0431/g, 'b')
    .replace(/\u044E/g, 'yu');

	return text;
};

const toSlug = pipe(
	trace('input'),
	trim,
	trace('trim'),
	toLowerCase,
	trace('lower case'),
	translitLower,
	trace('translit'),
	partialSplit(' '),
	partialJoin('-'),
	trace('joined with dashes'),
  encodeURIComponent
);


// ---

generate.onclick = () => result.innerText = toSlug(field.value);