sourcehypertextpublicsandboxhyphhyphen-test.js

const patternToPoints = pattern => {
	let points = [];
	pattern.split("").forEach(glyph => {
		if (glyph.match(/[0-9]/)) {
			points.pop();
			points.push(+glyph);
		} else {
			points.push(0);
		}
	});

	return points;
};

const mergeBreakpoints = (wordPoints, patternPoints, endIdx) => {
	const startIdx = endIdx - patternPoints.length;
	for (idx = 0; idx < patternPoints.length; idx++) {
		wordPoints[startIdx + idx] = Math.max(
			wordPoints[startIdx + idx],
			patternPoints[idx]
		);
	}
};

const hyphenateWord = (word, patterns) => {
	if (word.length < 5) {
		return word;
	}

	let breakpoints = new Array(word.length).fill(0);

	for (letter = 2; letter <= word.length; letter++) {
		const fragment = word.slice(0, letter);
		let matches = patterns.general.filter(pattern =>
			fragment.match(pattern[0])
		);
		if (letter == word.length) {
			matches.push(
				...patterns.final.filter(pattern => fragment.match(pattern[0]))
			);
		}

		for (const matchedPattern of matches) {
			mergeBreakpoints(
				breakpoints,
				patternToPoints(matchedPattern[1]),
				letter
			);
		}
	}

	breakpoints[0] = 0;
	breakpoints[breakpoints.length - 1] = 0;
	breakpoints[breakpoints.length - 2] = 0;

	const breakpointIndices = breakpoints
		.map((el, idx) => (el % 2 ? idx + 1 : 0))
		.filter(el => el != 0);

	let hyphenated = [];
	for (idx = 0; idx <= breakpointIndices.length; idx++) {
		if (idx == 0) {
			hyphenated.push(word.slice(0, breakpointIndices[idx]));
		} else if (idx == breakpointIndices.length) {
			hyphenated.push(word.slice(breakpointIndices[idx - 1]));
		} else {
			hyphenated.push(
				word.slice(breakpointIndices[idx - 1], breakpointIndices[idx])
			);
		}
	}

	return hyphenated.join("\u00AD");
};