Обновление 3 : T. connecting genius people. В комментариях ermouth привел отличный пример и поделился кодом!
Обновление 2 : поставленную задачу расстановки мягких переносов грубо, но решает. Ждём исходники http://iproc.ru/interesting/hyphenation/test/
Обновление: всё плохо. Это firefox научился переносить по слогам. Пруф: http://habrahabr.ru/post/136336/
Броня по-прежнему крепка и в танке – наши… Быстры…
Спасибо @dkhasanshin – напомнил про супер-мега-прорывное и важное обновление в wordpress и в темах – теперь wp умеет переносить слова по слогам, оптимизируя заполнение блока текстом по ширине. Пока искал – нашел ещё пример от неизвестного мне автора, но результат воодушевляет: http://ermouth.livejournal.com/580905.html
Цитирую код ermouth:
var shy = function (s) {
return s
.replace(/\s+/g," ")
.replace(/^\s|\s$/g,"")
.replace(/([а-яё])([\.,;])([а-яё])/gi,"$1$2 $3")
.split(" ").map(function(w) {
return w
.replace(/^(верх|ниж|зад)(не)/i,"$1ᴥ$2ᴥ")
.replace(/^(су|ги)(пер)/i,"$1ᴥ$2ᴥ")
.replace(/^(над|под|пара|без|раз|суб|бес|за|пере)/i,"$1ᴥ")
.replace(/^([а-яё]+?[б-джзй-нп-тф-щ][аеёиоуыэюя])([аеёиоуыэюя][а-яё]+)/gi,"$1ᴥ$2")
.replace(/([аеёоуыэюя][б-джзй-нп-тф-щ][ъь])([б-джзй-нп-тф-щ][а-яё])/gi,"$1ᴥ$2")
.replace(/([аеёиоуыэюяйᴥ][б-джзй-нп-тф-щъь])([б-джзй-нп-тф-щ][б-джзй-нп-тф-щ]*?[аеёиоуыэюяй][а-яёᴥ]*?)/gi,"$1ᴥ$2")
.replace(/([а-яё]{2}[аеёиоуыэюя])([б-джзк-нп-тф-щ][а-щыэ-яё])/gi,"$1ᴥ$2")
.replace(/([а-яё]{2}[б-джзк-нп-тф-щ])([аеёиоуыэюя][а-яё])/gi,"$1ᴥ$2")
.replace(/(ᴥ)([б-джзй-нп-тф-щъь]+)$/i,"$2")
.replace(/(ᴥ)([ъьы])/gi,"$2")
.replace(/ᴥᴥ/gi,"ᴥ")
.replace(/ᴥ/g,"\u00ad")
}).join(" ")
};
Доработанный вариант (unicode!) использует sugar.js:
shy= function shy (s) {
var r1="$1ᴥ$2",r2=r1+"ᴥ";
return String(s)
.compact()
.replace(/([а-яё])([\.,;\?\!:])([а-яё])/gi,"$1$2 $3")
.words(function(w,ctr,a) {
if (w.length<6 || (ctr==a.length-1 && w.length<10)) return w;
var prefix="", postfix="";
if (/^[^a-z0-9а-яё]/i.test(w)) prefix=w.substr(0,1);
if (/[^a-z0-9а-яё]$/gi.test(w)) postfix=w.last();
return prefix+w
.replace(/^[^a-z0-9а-яё]|[^a-z0-9а-яё]$/gi,"")
//prefixes
.replace(/^(верх|ниж|зад)(не)/i,r2).replace(/^(су|ги)(пер)/i,r2)
.replace(/^(вяче|архан|про|вы|над|по(д)?|пара|бе[зс]о?|раз|суб|за|журна|долго|ре([ск])?|транс|энерго|прези|пере|(ста|ме)ро)/i,"$1ᴥ")
//hyphener
.replace(/([а-яё]{2,}?[б-джзй-нп-тф-щ][аеёиоуыэюя])([аеёиоуыэюя][а-яё]+)/gi,r1)
.replace(/^([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])/gi,"$1ᴥ$2ᴥ$3")
.replace(/([аеёоуыэюя][б-джзй-нп-тф-щ][ъь])([б-джзй-нп-тф-щ][а-яё])/gi,r1)
.replace(/([аеёиоуыэюяйᴥ][б-джзй-нп-тф-щ])([б-джзк-нп-тф-щ][а-яё]?[аеёиоуыэюяй][а-яёᴥ]?)/gi,r1)
.replace(/^([оау][зщжшцйс])(ᴥ)/gi,"$1")
.replace(/([а-яё]{2}[аеёиоуыэюя])([б-джзк-нп-тф-щ][а-щыэ-яё])/gi,r1)
.replace(/([а-яё]{2}[б-джзк-нп-тф-щ])([аеёиоуыэюя][а-яё])/gi,r1)
//correctors
.replace(/(ᴥ)([б-джзй-нп-тф-щъь]+)$/i,"$2")
.replace(/(ᴥ)([йъьы])/gi,"$2")
.replace(/(ᴥ)([а-яё][лнтс]+ь)/gi,"$2")
.replace(/(ᴥ)(кала|убить)$/gi,"$2")
.replace(/([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюяй]{2})$/gi,"ᴥ$1$3")
.replace(/(ᴥ)([б-джзк-нп-тф-щ])(ᴥ)([б-джзк-нп-тф-щ])/gi,"$1$2$4")
.replace(/^([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюя][б-джзк-нп-тф-щ])/gi,"$1ᴥ$2$4")
.replace(/([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюя][б-джзк-нп-тф-щ])$/gi,"$1ᴥ$2$4")
.replace(/([б-джзк-нп-тф-щ][аеёиоуыэюя][б-джзк-нп-тф-щ])(ᴥ)([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ][аеёиоуыэюя]ᴥ[б-джзк-нп-тф-щ])/gi,"$1$3ᴥ$4")
.replace(/([б-джзк-нп-тф-щ]{2})([б-джзк-нп-тф-щ][ие])(ᴥ)([тн])([тн])([аеёиоуыэюя][аеёиоуыэюяй]?)$/gi,"$1ᴥ$2$4ᴥ$5$6")
.replace(/([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ])(ᴥ)([аиоуыэ][б-джзк-нп-тф-щ])(ᴥ)/gi,"$1ᴥ$2$4$5") //тр-иб- 2 т-риб-
.replace(/ᴥ([б-джзк-нп-тф-щ]{2})ᴥ/gi,"$1ᴥ") // - согл согл -
.replace(/^([б-джзк-нп-тф-щ]{2,})ᴥ/gi,"$1") //2+согл в начале слова
.replace(/(ᴥ)([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ]{3})/gi,"$2$1$3") //средства, сопутству...
.replace(/([а-яё])\1ᴥ/gi,"$1ᴥ$1") //две одинаковых буквы
.replace(/ᴥ([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])ᴥ([аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])/gi,"ᴥ$1ᴥ$2$3ᴥ$4") // нан-ана 2 на-на-на
.replace(/^(ра)ᴥ(з)/i,"$1$2ᴥ")
.replace(/([б-джзк-нп-тф-щ])ᴥ([еу])([ежзц])ᴥ/,"ᴥ$1$2$3")
.replace(/([б-джзк-нп-тф-щ]{2})([б-джзк-нп-тф-щ])(ᴥ)([эуюяыое][б-джзк-нп-тф-щ])/gi,"$1ᴥ$2$4")
.replace(/ᴥᴥ/gi,"ᴥ")
.replace(/^([a-z0-9а-яё]{2})ᴥ(.+)$/gi,"$1$2")
.replace(/ᴥ/g,"\u00ad")+postfix;//\u00ad");
}).join(" ").replace(/\s—\s/g,"\u00a0– ");
};
Это то, как есть сейчас. Реально работает на dvinanews.ru. Для того, чтобы заработал в браузере, вам потребуется подключить Sugar.js.
Скорость – в районе мегабайта в секунду на i5.
shy= function shy (s) {
var r1="$1ᴥ$2",r2=r1+"ᴥ";
return String(s)
.compact()
.replace(/([а-яё])([\.,;\?\!:])([а-яё])/gi,"$1$2 $3")
.words(function(w,ctr,a) {
if (w.length<6 || (ctr==a.length-1 && w.length<10)) return w;
var prefix="", postfix="";
if (/^[^a-z0-9а-яё]/i.test(w)) prefix=w.substr(0,1);
if (/[^a-z0-9а-яё]$/gi.test(w)) postfix=w.last();
return prefix+w
.replace(/^[^a-z0-9а-яё]|[^a-z0-9а-яё]$/gi,"")
//prefixes
.replace(/^(верх|ниж|зад)(не)/i,r2).replace(/^(су|ги)(пер)/i,r2)
.replace(/^(вяче|архан|про|вы|над|по(д)?|пара|бе[зс]о?|раз|суб|за|журна|долго|ре([ск])?|транс|энерго|прези|пере|(ста|ме)ро)/i,"$1ᴥ")
//hyphener
.replace(/([а-яё]{2,}?[б-джзй-нп-тф-щ][аеёиоуыэюя])([аеёиоуыэюя][а-яё]+)/gi,r1)
.replace(/^([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])/gi,"$1ᴥ$2ᴥ$3")
.replace(/([аеёоуыэюя][б-джзй-нп-тф-щ][ъь])([б-джзй-нп-тф-щ][а-яё])/gi,r1)
.replace(/([аеёиоуыэюяйᴥ][б-джзй-нп-тф-щ])([б-джзк-нп-тф-щ][а-яё]?[аеёиоуыэюяй][а-яёᴥ]?)/gi,r1)
.replace(/^([оау][зщжшцйс])(ᴥ)/gi,"$1")
.replace(/([а-яё]{2}[аеёиоуыэюя])([б-джзк-нп-тф-щ][а-щыэ-яё])/gi,r1)
.replace(/([а-яё]{2}[б-джзк-нп-тф-щ])([аеёиоуыэюя][а-яё])/gi,r1)
//correctors
.replace(/(ᴥ)([б-джзй-нп-тф-щъь]+)$/i,"$2")
.replace(/(ᴥ)([йъьы])/gi,"$2")
.replace(/(ᴥ)([а-яё][лнтс]+ь)/gi,"$2")
.replace(/(ᴥ)(кала|убить)$/gi,"$2")
.replace(/([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюяй]{2})$/gi,"ᴥ$1$3")
.replace(/(ᴥ)([б-джзк-нп-тф-щ])(ᴥ)([б-джзк-нп-тф-щ])/gi,"$1$2$4")
.replace(/^([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюя][б-джзк-нп-тф-щ])/gi,"$1ᴥ$2$4")
.replace(/([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])(ᴥ)([аеёиоуыэюя][б-джзк-нп-тф-щ])$/gi,"$1ᴥ$2$4")
.replace(/([б-джзк-нп-тф-щ][аеёиоуыэюя][б-джзк-нп-тф-щ])(ᴥ)([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ][аеёиоуыэюя]ᴥ[б-джзк-нп-тф-щ])/gi,"$1$3ᴥ$4")
.replace(/([б-джзк-нп-тф-щ]{2})([б-джзк-нп-тф-щ][ие])(ᴥ)([тн])([тн])([аеёиоуыэюя][аеёиоуыэюяй]?)$/gi,"$1ᴥ$2$4ᴥ$5$6")
.replace(/([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ])(ᴥ)([аиоуыэ][б-джзк-нп-тф-щ])(ᴥ)/gi,"$1ᴥ$2$4$5") //тр-иб- 2 т-риб-
.replace(/ᴥ([б-джзк-нп-тф-щ]{2})ᴥ/gi,"$1ᴥ") // - согл согл -
.replace(/^([б-джзк-нп-тф-щ]{2,})ᴥ/gi,"$1") //2+согл в начале слова
.replace(/(ᴥ)([б-джзк-нп-тф-щ])([б-джзк-нп-тф-щ]{3})/gi,"$2$1$3") //средства, сопутству...
.replace(/([а-яё])\1ᴥ/gi,"$1ᴥ$1") //две одинаковых буквы
.replace(/ᴥ([б-джзк-нп-тф-щ][аеёиоуыэюя])([б-джзк-нп-тф-щ])ᴥ([аеёиоуыэюя])([б-джзк-нп-тф-щ][аеёиоуыэюя])/gi,"ᴥ$1ᴥ$2$3ᴥ$4") // нан-ана 2 на-на-на
.replace(/^(ра)ᴥ(з)/i,"$1$2ᴥ")
.replace(/([б-джзк-нп-тф-щ])ᴥ([еу])([ежзц])ᴥ/,"ᴥ$1$2$3")
.replace(/([б-джзк-нп-тф-щ]{2})([б-джзк-нп-тф-щ])(ᴥ)([эуюяыое][б-джзк-нп-тф-щ])/gi,"$1ᴥ$2$4")
.replace(/ᴥᴥ/gi,"ᴥ")
.replace(/^([a-z0-9а-яё]{2})ᴥ(.+)$/gi,"$1$2")
.replace(/ᴥ/g,"\u00ad")+postfix;//\u00ad");
}).join(" ").replace(/\s—\s/g,"\u00a0– ");
};
Пример впечатляет, браво!