Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 19.08.2018, 23:05
Интересующийся
Отправить личное сообщение для Arhitector Посмотреть профиль Найти все сообщения от Arhitector
 
Регистрация: 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, никаких плагинов библиотек и тд!
Пожалуйста помогите с решением! Сам уже кучу времени убил, но ничего толкового пока что не получилось...
Ответить с цитированием
  #2 (permalink)  
Старый 19.08.2018, 23:25
Интересующийся
Отправить личное сообщение для Arhitector Посмотреть профиль Найти все сообщения от Arhitector
 
Регистрация: 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));

У меня вроде получилось примерно то что надо, но как то уж больно громоздко выглядит, может можно как то поизящнее это сделать?
Ответить с цитированием
  #3 (permalink)  
Старый 19.08.2018, 23:28
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 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;
});
Ответить с цитированием
  #4 (permalink)  
Старый 19.08.2018, 23:37
Интересующийся
Отправить личное сообщение для Arhitector Посмотреть профиль Найти все сообщения от Arhitector
 
Регистрация: 12.08.2018
Сообщений: 18

Alexandroppolus, Это уже намного лучше! Спасибо большое!
Ответить с цитированием
  #5 (permalink)  
Старый 19.08.2018, 23:50
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,108

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>
Ответить с цитированием
  #6 (permalink)  
Старый 20.08.2018, 00:10
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,583

Вообще такие вещи делаются конечным автоматом, но по-быстрому можно и регуляркой нафигачить, как и все ребята выше
(версия игнорирующая незакрытые тэги и работающая со вложенностью):
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.
Ответить с цитированием
  #7 (permalink)  
Старый 20.08.2018, 00:13
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 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>
Ответить с цитированием
  #8 (permalink)  
Старый 20.08.2018, 00:33
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Сообщение от Aetae
работающая со вложенностью
со вложенностью не совсем понятно, какой правильный результат должен быть (автор ничего не говорил об этом)

возможно, для строки
"111[color=green]222[color=red]333[/color]444[/color]555"
должно быть 3 непересекающихся экшена - green для "222", red для "333", green для "444". Но и там в принципе твой вариант со стеком можно приспособить
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как с помощью скрипта высчитать ширину полосы прокрутки? LADYX Элементы интерфейса 35 13.11.2017 12:50
Вырезать все символы между заданными символами hfts_rider Events/DOM/Window 6 20.05.2015 16:28
Удаление в выделенном тексте символы и все, что между ними dimmapril Общие вопросы Javascript 0 08.04.2012 19:54
Название ячейки таблицы Questioner Общие вопросы Javascript 6 16.02.2011 09:58
глюк форума Gvozd Сайт Javascript.ru 11 18.03.2009 14:37