19.08.2018, 23:05
|
Интересующийся
|
|
Регистрация: 12.08.2018
Сообщений: 18
|
|
Найти все блоки текста между символами и запомнить их индексы
Всем привет.
Возникла у меня такая задача, необходимо найти в строке текста, все отрезки текста которые находятся между символами [color=ЦВЕТ]текст текст текст[/color], запомнить индекс начала текста ( без блока [color=ЦВЕТ]!) между этими символами и индекс конца, записать значение с цветом которое стоит после color= и удалить из текста этот блок оставив лишь текст между ним.
Суть примерно такая
Изначальный текст
Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.
Надо что бы эта строка превратилась в
Оооочень большая строка текста, выделенный текст, еще всякий текст текст текст еще выделенный текст! Ну и тд.
и после ее обработки на выходе получался примерно вот такой массив с информацией
// для каждого блока создаётся объект с данными его позиционирования и цвета
// тут хранится позиция начала текста БЕЗ блока [color] и позиция окончания
var array_action = [
{index_start_action: 31, index_end_action: 47, color: "красный"}, // индексы с отрезком текста - выделенный текст
{index_start_action: 78, index_end_action: 98, color: "зелёный"} // индексы с отрезком текста - еще выделенный текст
]
И еще момент, нужен только чистый JS, никаких плагинов библиотек и тд!
Пожалуйста помогите с решением! Сам уже кучу времени убил, но ничего толкового пока что не получилось...
|
|
19.08.2018, 23:25
|
Интересующийся
|
|
Регистрация: 12.08.2018
Сообщений: 18
|
|
function createActionForText (text) {
var text_left_border_start = text.indexOf("[color="),
text_left_border_end = text.indexOf("]", text_left_border_start),
color = text.slice(text_left_border_start + 7, text_left_border_end),
text_right_border_start = text.indexOf("[/color"),
text_right_border_end = text.indexOf("]", text_right_border_start),
value = text.slice(text_left_border_end + 1, text_right_border_start),
text_array = text.split("");
text_array.splice(text_right_border_start, 8);
text_array.splice(text_left_border_start, color.length + 8);
return {
text: text_array.join(""),
start: text_left_border_end - (color.length + 8),
end: (text_left_border_end - (color.length + 8)) + value.length,
color: color
}
}
console.log(createActionForText(text));
У меня вроде получилось примерно то что надо, но как то уж больно громоздко выглядит, может можно как то поизящнее это сделать?
|
|
19.08.2018, 23:28
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
var rx = /\[color=([^\]]+)\](.*?)(?:\[\/color\]|$)/g;
var array_action = [];
var totalRemove = 0;
var resultStr = str.replace(rx, function(a, color, txt, idx) {
array_action.push({
index_start_action: idx - totalRemove,
index_end_action: idx + txt.length - totalRemove
});
totalRemove += color.length + 16;
return txt;
});
|
|
19.08.2018, 23:37
|
Интересующийся
|
|
Регистрация: 12.08.2018
Сообщений: 18
|
|
Alexandroppolus, Это уже намного лучше! Спасибо большое!
|
|
19.08.2018, 23:50
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,120
|
|
Arhitector,
<script>
var str = 'Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.',
reg = /\[([^=]+)=([^\]]+)\]([\S\s]*?)\[\/\1\]/mig,
array_action = [], n = 1;
str = str.replace(reg, function(a,b,c,d,e) {
var index_start_action = e - n;
var index_end_action = index_start_action + d.length
var color = c;
var obj = {index_start_action : index_start_action, index_end_action : index_end_action, color : color};
array_action.push(obj);
n += a.length - d.length;
return d
});
document.write(str + "<br>" + JSON.stringify(array_action, null, 4))
</script>
|
|
20.08.2018, 00:10
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,587
|
|
Вообще такие вещи делаются конечным автоматом, но по-быстрому можно и регуляркой нафигачить, как и все ребята выше
(версия игнорирующая незакрытые тэги и работающая со вложенностью):
var str = 'Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.';
var array_action = [];
var shift = 0;
var start = [];
var result = str.replace(/\[(\/?)color(?:\s*=\s*([^\]]+)\s*)?\]/g, function(full, end, color, index){
if(end){
if(end = start.pop()){
end.index_end_action = index - shift;
array_action.push(end);
}
} else {
start.push({
index_start_action: index - shift,
color: color
})
}
shift += full.length;
return '';
});
console.log(result, array_action);
__________________
29375, 35
Последний раз редактировалось Aetae, 20.08.2018 в 00:17.
|
|
20.08.2018, 00:13
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Вариант с String.prototype.match
<!doctype html>
<html>
<head><style>body { font: 120% sans-serif; }</style></head>
<body>
<script>
// функция, выдающая строку и объект с данными о позиции цветного текста
function parse(string) {
var match;
var spans = [], index = 0, text = [], length;
while(match = string.match(/(\[color=([^\]]+)\])(.*?)(\[\/color\])/s)) {
index += match.index;
text.push(string.slice(0, match.index) + match[3]);
length = match[0].length - match[1].length - match[4].length;
spans.push({
start: index,
end: index + length,
color: match[2]
});
index += length;
string = string.slice(match.index + match[0].length);
}
text.push(string);
return {
text: text.join(""),
spans
};
}
// пример, проверка
function stringify({ text, spans }) {
return spans.reduce((string, { start, end, color }, index, data) => {
string.push(
`<mark style="color: ${color};">${text.slice(start, end)}</mark>`
);
string.push(
(index + 1) in data ?
text.slice(end, data[index + 1].start) :
text.slice(end)
);
return string;
}, [text.slice(0, 0 in spans ? spans[0].start : Infinity)]).join("");
}
var r = parse("Оооочень большая строка текста, [color=red]выделенный текст[/color], еще всякий текст текст текст [color=green]еще выделенный текст[/color]! Ну и тд.");
document.body.innerHTML = `<pre>${JSON.stringify(r, null, "\t")}</pre>` + stringify(r);
</script>
</body>
</html>
|
|
20.08.2018, 00:33
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от Aetae
|
работающая со вложенностью
|
со вложенностью не совсем понятно, какой правильный результат должен быть (автор ничего не говорил об этом)
возможно, для строки
"111[color=green]222[color=red]333[/color]444[/color]555"
должно быть 3 непересекающихся экшена - green для "222", red для "333", green для "444". Но и там в принципе твой вариант со стеком можно приспособить
|
|
|
|