Раскрашивание кода (реинкарнация обработки с ИТС)

0. salexdv 2123 04.02.22 11:30 Сейчас в теме
Обработка для раскраски кода, написанного на встроенном языке 1С:Предприятия, работающая в управляемых формах с возможностью сохранения результата в html.

Перейти к публикации

Отзывы
6. DrAku1a 1590 05.02.22 12:46 Сейчас в теме
Для тех, кому лень качать - делюсь своей реализацией функции раскраски кода
//Вспомогательная, используется в "РаскраситьКод1С8"
Процедура ДобавитьСлово(Код, Слово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, ТипСлова=Неопределено)
	Если ПустаяСтрока(Слово) Тогда
		Код = Код + СтрЗаменить(СтрЗаменить(СтрЗаменить(Слово, " ", " "), Символы.НПП, " "), Символы.Таб, "    ");
		Возврат;
	ИначеЕсли ТипСлова=Неопределено Тогда
		нсл = НРег(СокрП(Слово));
		Если Найти(СписокКлючевыхСлов, нсл)>0 Тогда
			ТипСлова = "<keywrd>";
		ИначеЕсли Слово = "0" или мОписаниеТипаЧисло.ПривестиЗначение(Слово)<>0 Тогда
			ТипСлова = "<num>";
		Иначе
			ТипСлова = "<text>";
			ЭтоЧисло = Истина;
			Для сч=1 по СтрДлина(нсл) Цикл
				ТекСимв=Сред(нсл, сч, 1);
				Если Найти(ДопустимыеЗнаки, ТекСимв)=0 Тогда
					ТипСлова="<unwn>";
					Прервать;
				ИначеЕсли ТекСимв<>"0" Тогда
					ЭтоЧисло = Ложь;
				КонецЕсли;
			КонецЦикла;
			Если ЭтоЧисло Тогда
				ТипСлова = "<num>";
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Код = Код + ?(ТекТипСлова=ТипСлова, "", ТипСлова) + СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Слово, "<", "<"), ">", ">"), " ", " "), Символы.НПП, " "), Символы.Таб, "    ");
	ТекТипСлова = ТипСлова;
	Слово = "";
КонецПроцедуры

//Реализует функционал "Оформить фрагмент кода"
Функция РаскраситьКод1С8(ТекстКод) Экспорт
	мОписаниеТипаЧисло = Новый ОписаниеТипов("Число");
	Таб = Символы.Таб;
	НПП = Символы.НПП;
	ДопустимыеЗнаки = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя0123456789abcdefghijklmnop­qrstyvwxyz_";
	СписокКлючевыхСлов = "асинх|async|ждать|await|if|если|then|тогда|elsif|иначеесли|else|иначе|endif|конецесли|do|цикл|for|для|to|по|each|каждого|in|из|while|пока|enddo|конеццикла|procedure|процедура|endprocedure|конецпроцедуры|function|функция|endfunction|конецфункции|var|перем|export|экспорт|goto|перейти|and|и|or|или|not|не|val|знач|break|прервать|continue|продолжить|return|возврат|try|попытка|except|исключение|endtry|конецпопытки|raise|вызватьисключение|false|ложь|true|истина|undefined|неопределено|null|new|новый|execute|выполнить|";
	Ответ = "<span style=""text-align: left; font-family: courier new,courier; color: blue; font-size: 10pt; white-space: pre; display: inline-block; ""><font>";
	ТекТипСлова = "<text>";
	Для нс=1 По СтрЧислоСтрок(ТекстКод) Цикл
		ТекСтрока = СокрП(СтрПолучитьСтроку(ТекстКод, нс));
		дл = СтрДлина(ТекСтрока);
		сч = 0;
		ТекСлово = "";
		КодНеНачался = Истина;
		Пока сч<дл Цикл
			сч = сч + 1;
			ТекущийСимвол = Сред(ТекСтрока, сч, 1);
			Если КодНеНачался Тогда
				Если ТекущийСимвол=" " Или ТекущийСимвол=Таб Или ТекущийСимвол=НПП Тогда
					//ТекущийСимвол = ?(ТекущийСимвол=" " или ТекущийСимвол=НПП, " ", "    ");
					Ответ = Ответ + ТекущийСимвол;
					Продолжить;
				ИначеЕсли ТекущийСимвол="#" или ТекущийСимвол="&" Тогда
					ТекСлово = "";
					ДобавитьСлово(Ответ, Сред(ТекСтрока, сч), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<dir>");
					Прервать;
				КонецЕсли;
			КонецЕсли;
			КодНеНачался = Ложь;			
			Если ТекущийСимвол=" " Или ТекущийСимвол=Таб Или ТекущийСимвол=НПП Тогда
				Если КодНеНачался Тогда
					Ответ = Ответ + ТекущийСимвол;
					Продолжить;
				КонецЕсли;
				//ТекущийСимвол = ?(ТекущийСимвол=" " или ТекущийСимвол=НПП, " ", "    ");
				ДобавитьСлово(Ответ, ТекСлово+ТекущийСимвол, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				ТекСлово = "";
				Продолжить;
			ИначеЕсли Найти("():;.,=+-*<>?[]%/", ТекущийСимвол) > 0 Тогда
				ДобавитьСлово(Ответ, ТекСлово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				ТекСлово = "";
				//Проверяем на комментарий
				Если ТекущийСимвол="/" и Сред(ТекСтрока, сч+1, 1)="/" Тогда
					ТекСлово = "";
					ДобавитьСлово(Ответ, СокрП(Сред(ТекСтрока, сч)), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<cmnt>");
					Прервать;
				КонецЕсли;	
				ДобавитьСлово(Ответ, ТекущийСимвол, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<symb>");
				Продолжить;
			ИначеЕсли ТекущийСимвол="""" или ТекущийСимвол="|" Тогда
				ДобавитьСлово(Ответ, ТекСлово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				// найти закрывающую кавычку
				нач = сч;
				сч = сч + 1;
				СледующийСимвол = Сред(ТекСтрока, сч, 1);
				Пока сч<дл Цикл
					сч = сч + 1;
					ТекущийСимвол = СледующийСимвол;
					СледующийСимвол = Сред(ТекСтрока, сч, 1);
					Если ТекущийСимвол="""" Тогда
						Если СледующийСимвол="""" Тогда
							сч = сч + 1;
							СледующийСимвол = Сред(ТекСтрока, сч, 1);
						Иначе
							Прервать;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				ТекСлово = "";
				ДобавитьСлово(Ответ, Сред(ТекСтрока, нач, сч-нач), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<str>");
				сч = сч - 1;
				Продолжить;
			ИначеЕсли ТекущийСимвол="'" Тогда
				нач = сч;
				сч = сч + 1;
				СледующийСимвол = Сред(ТекСтрока, сч, 1);
				Пока сч<дл Цикл
					сч = сч + 1;
					ТекущийСимвол = СледующийСимвол;
					СледующийСимвол = Сред(ТекСтрока, сч, 1);
					Если ТекущийСимвол="'" Тогда
						Если СледующийСимвол="'" Тогда
							сч = сч + 1;
							СледующийСимвол = Сред(ТекСтрока, сч, 1);
						Иначе
							Прервать;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				ТекСлово = "";
				ДобавитьСлово(Ответ, Сред(ТекСтрока, нач, сч-нач), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<str>");
				сч = сч - 1;
				Продолжить;
			КонецЕсли;
			ТекСлово = ТекСлово + ТекущийСимвол;
		КонецЦикла;
		Если Не ПустаяСтрока(ТекСлово) Тогда
			ДобавитьСлово(Ответ,СокрП(ТекСлово), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
		КонецЕсли;
		Ответ = Ответ + "";
	КонецЦикла;	
	Ответ = Ответ + Символы.ПС+"</font></span>";
	Ответ = СтрЗаменить(Ответ, "<keywrd>", "</font><font color=red>");
	Ответ = СтрЗаменить(Ответ, "<text>", "</font><font color=blue>");
	Ответ = СтрЗаменить(Ответ, "<str>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<num>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<unwn>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<symb>", "</font><font color=red>");
	Ответ = СтрЗаменить(Ответ, "<cmnt>", "</font><font color=green>");
	Ответ = СтрЗаменить(Ответ, "<dir>", "</font><font color=brown>");	
	Ответ = СтрЗаменить(Ответ, Символы.Таб, "    ");
	Возврат Ответ;
КонецФункции
Показать
semagin@gmail.com; Merkalov; Totoro; Jeka44; cosmo2004; Batman; fancy; mrChOP93; pavlov_dv; starik-2005; ubnkfl; salexdv; +12 Ответить
19. DrAku1a 1590 07.02.22 14:58 Сейчас в теме
(17) В функции "РаскраситьКод1С8"
после
// найти закрывающую кавычку
будет цикл.
После цикла - добавьте
				Если ТекущийСимвол<>"""" или СледующийСимвол="""" Тогда
					сч = сч + 1;
				КонецЕсли;
Прикрепленные файлы:
ТестРаскраскиКода1Сv8.epf
Остальные комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. jan-pechka 376 04.02.22 12:23 Сейчас в теме
2. 1v7 229 04.02.22 17:35 Сейчас в теме
Класс! п.с. - В сети еще есть Онлайн сервис по раскраске кода 1С 8.3
Obertone; +1 Ответить
3. salexdv 2123 04.02.22 18:22 Сейчас в теме
4. 1v7 229 04.02.22 18:23 Сейчас в теме
5. webester 25 05.02.22 03:31 Сейчас в теме
(2) Да сервисов то даже особо не надо) Было дело баловался в детстве с библиотекой highlight.js https://26226.selcdn.ru/paint_1c/export.html но это было давно. Тогда ключевые слова сами добавляли и собирали библиотеку, теперь 1с уже зашит в библиотеку.
6. DrAku1a 1590 05.02.22 12:46 Сейчас в теме
Для тех, кому лень качать - делюсь своей реализацией функции раскраски кода
//Вспомогательная, используется в "РаскраситьКод1С8"
Процедура ДобавитьСлово(Код, Слово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, ТипСлова=Неопределено)
	Если ПустаяСтрока(Слово) Тогда
		Код = Код + СтрЗаменить(СтрЗаменить(СтрЗаменить(Слово, " ", " "), Символы.НПП, " "), Символы.Таб, "    ");
		Возврат;
	ИначеЕсли ТипСлова=Неопределено Тогда
		нсл = НРег(СокрП(Слово));
		Если Найти(СписокКлючевыхСлов, нсл)>0 Тогда
			ТипСлова = "<keywrd>";
		ИначеЕсли Слово = "0" или мОписаниеТипаЧисло.ПривестиЗначение(Слово)<>0 Тогда
			ТипСлова = "<num>";
		Иначе
			ТипСлова = "<text>";
			ЭтоЧисло = Истина;
			Для сч=1 по СтрДлина(нсл) Цикл
				ТекСимв=Сред(нсл, сч, 1);
				Если Найти(ДопустимыеЗнаки, ТекСимв)=0 Тогда
					ТипСлова="<unwn>";
					Прервать;
				ИначеЕсли ТекСимв<>"0" Тогда
					ЭтоЧисло = Ложь;
				КонецЕсли;
			КонецЦикла;
			Если ЭтоЧисло Тогда
				ТипСлова = "<num>";
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	Код = Код + ?(ТекТипСлова=ТипСлова, "", ТипСлова) + СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Слово, "<", "<"), ">", ">"), " ", " "), Символы.НПП, " "), Символы.Таб, "    ");
	ТекТипСлова = ТипСлова;
	Слово = "";
КонецПроцедуры

//Реализует функционал "Оформить фрагмент кода"
Функция РаскраситьКод1С8(ТекстКод) Экспорт
	мОписаниеТипаЧисло = Новый ОписаниеТипов("Число");
	Таб = Символы.Таб;
	НПП = Символы.НПП;
	ДопустимыеЗнаки = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя0123456789abcdefghijklmnop­qrstyvwxyz_";
	СписокКлючевыхСлов = "асинх|async|ждать|await|if|если|then|тогда|elsif|иначеесли|else|иначе|endif|конецесли|do|цикл|for|для|to|по|each|каждого|in|из|while|пока|enddo|конеццикла|procedure|процедура|endprocedure|конецпроцедуры|function|функция|endfunction|конецфункции|var|перем|export|экспорт|goto|перейти|and|и|or|или|not|не|val|знач|break|прервать|continue|продолжить|return|возврат|try|попытка|except|исключение|endtry|конецпопытки|raise|вызватьисключение|false|ложь|true|истина|undefined|неопределено|null|new|новый|execute|выполнить|";
	Ответ = "<span style=""text-align: left; font-family: courier new,courier; color: blue; font-size: 10pt; white-space: pre; display: inline-block; ""><font>";
	ТекТипСлова = "<text>";
	Для нс=1 По СтрЧислоСтрок(ТекстКод) Цикл
		ТекСтрока = СокрП(СтрПолучитьСтроку(ТекстКод, нс));
		дл = СтрДлина(ТекСтрока);
		сч = 0;
		ТекСлово = "";
		КодНеНачался = Истина;
		Пока сч<дл Цикл
			сч = сч + 1;
			ТекущийСимвол = Сред(ТекСтрока, сч, 1);
			Если КодНеНачался Тогда
				Если ТекущийСимвол=" " Или ТекущийСимвол=Таб Или ТекущийСимвол=НПП Тогда
					//ТекущийСимвол = ?(ТекущийСимвол=" " или ТекущийСимвол=НПП, " ", "    ");
					Ответ = Ответ + ТекущийСимвол;
					Продолжить;
				ИначеЕсли ТекущийСимвол="#" или ТекущийСимвол="&" Тогда
					ТекСлово = "";
					ДобавитьСлово(Ответ, Сред(ТекСтрока, сч), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<dir>");
					Прервать;
				КонецЕсли;
			КонецЕсли;
			КодНеНачался = Ложь;			
			Если ТекущийСимвол=" " Или ТекущийСимвол=Таб Или ТекущийСимвол=НПП Тогда
				Если КодНеНачался Тогда
					Ответ = Ответ + ТекущийСимвол;
					Продолжить;
				КонецЕсли;
				//ТекущийСимвол = ?(ТекущийСимвол=" " или ТекущийСимвол=НПП, " ", "    ");
				ДобавитьСлово(Ответ, ТекСлово+ТекущийСимвол, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				ТекСлово = "";
				Продолжить;
			ИначеЕсли Найти("():;.,=+-*<>?[]%/", ТекущийСимвол) > 0 Тогда
				ДобавитьСлово(Ответ, ТекСлово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				ТекСлово = "";
				//Проверяем на комментарий
				Если ТекущийСимвол="/" и Сред(ТекСтрока, сч+1, 1)="/" Тогда
					ТекСлово = "";
					ДобавитьСлово(Ответ, СокрП(Сред(ТекСтрока, сч)), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<cmnt>");
					Прервать;
				КонецЕсли;	
				ДобавитьСлово(Ответ, ТекущийСимвол, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<symb>");
				Продолжить;
			ИначеЕсли ТекущийСимвол="""" или ТекущийСимвол="|" Тогда
				ДобавитьСлово(Ответ, ТекСлово, ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
				// найти закрывающую кавычку
				нач = сч;
				сч = сч + 1;
				СледующийСимвол = Сред(ТекСтрока, сч, 1);
				Пока сч<дл Цикл
					сч = сч + 1;
					ТекущийСимвол = СледующийСимвол;
					СледующийСимвол = Сред(ТекСтрока, сч, 1);
					Если ТекущийСимвол="""" Тогда
						Если СледующийСимвол="""" Тогда
							сч = сч + 1;
							СледующийСимвол = Сред(ТекСтрока, сч, 1);
						Иначе
							Прервать;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				ТекСлово = "";
				ДобавитьСлово(Ответ, Сред(ТекСтрока, нач, сч-нач), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<str>");
				сч = сч - 1;
				Продолжить;
			ИначеЕсли ТекущийСимвол="'" Тогда
				нач = сч;
				сч = сч + 1;
				СледующийСимвол = Сред(ТекСтрока, сч, 1);
				Пока сч<дл Цикл
					сч = сч + 1;
					ТекущийСимвол = СледующийСимвол;
					СледующийСимвол = Сред(ТекСтрока, сч, 1);
					Если ТекущийСимвол="'" Тогда
						Если СледующийСимвол="'" Тогда
							сч = сч + 1;
							СледующийСимвол = Сред(ТекСтрока, сч, 1);
						Иначе
							Прервать;
						КонецЕсли;
					КонецЕсли;
				КонецЦикла;
				ТекСлово = "";
				ДобавитьСлово(Ответ, Сред(ТекСтрока, нач, сч-нач), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло, "<str>");
				сч = сч - 1;
				Продолжить;
			КонецЕсли;
			ТекСлово = ТекСлово + ТекущийСимвол;
		КонецЦикла;
		Если Не ПустаяСтрока(ТекСлово) Тогда
			ДобавитьСлово(Ответ,СокрП(ТекСлово), ТекТипСлова, СписокКлючевыхСлов, ДопустимыеЗнаки, мОписаниеТипаЧисло);
		КонецЕсли;
		Ответ = Ответ + "";
	КонецЦикла;	
	Ответ = Ответ + Символы.ПС+"</font></span>";
	Ответ = СтрЗаменить(Ответ, "<keywrd>", "</font><font color=red>");
	Ответ = СтрЗаменить(Ответ, "<text>", "</font><font color=blue>");
	Ответ = СтрЗаменить(Ответ, "<str>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<num>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<unwn>", "</font><font color=black>");
	Ответ = СтрЗаменить(Ответ, "<symb>", "</font><font color=red>");
	Ответ = СтрЗаменить(Ответ, "<cmnt>", "</font><font color=green>");
	Ответ = СтрЗаменить(Ответ, "<dir>", "</font><font color=brown>");	
	Ответ = СтрЗаменить(Ответ, Символы.Таб, "    ");
	Возврат Ответ;
КонецФункции
Показать
semagin@gmail.com; Merkalov; Totoro; Jeka44; cosmo2004; Batman; fancy; mrChOP93; pavlov_dv; starik-2005; ubnkfl; salexdv; +12 Ответить
11. salexdv 2123 07.02.22 13:21 Сейчас в теме
(6) Чтобы избежать ошибок при раскраске кода, содержащего html-сущности, которые могут сломать разметку, добавьте в начало функции РаскраситьКод1С8 следующие строки:

ТекстКод= СтрЗаменить(ТекстКод, "<", "& lt;");
ТекстКод= СтрЗаменить(ТекстКод, ">", "& gt;");
14. salexdv 2123 07.02.22 14:31 Сейчас в теме
(11) Вернее не совсем так. Данную замену надо производить, когда указанные сущности встречаются внутри строки или комментария.
16. DrAku1a 1590 07.02.22 14:45 Сейчас в теме
(11) Не в начале функции "РаскраситьКод1С8", а в функции "ДобавитьСлово"
Это на самом деле было реализовано, просто верстка кода на сайте Инфостарта немного скорректировала некоторые символы.
В итоге получилась вот такая глупость: СтрЗаменить(Слово, "<", "<"), ">", ">"), " ", " ")...
Тестовую обработку прилагаю - она делает нормальный HTML-код.
semagin@gmail.com; salexdv; +2 Ответить
17. salexdv 2123 07.02.22 14:48 Сейчас в теме
(16) Всё равно есть небольшая ошибка.
Прикрепленные файлы:
19. DrAku1a 1590 07.02.22 14:58 Сейчас в теме
(17) В функции "РаскраситьКод1С8"
после
// найти закрывающую кавычку
будет цикл.
После цикла - добавьте
				Если ТекущийСимвол<>"""" или СледующийСимвол="""" Тогда
					сч = сч + 1;
				КонецЕсли;
Прикрепленные файлы:
ТестРаскраскиКода1Сv8.epf
7. 1v7 229 07.02.22 11:21 Сейчас в теме
Протестировал. На типовых кусках кода хорошо работает. Но если в коде есть теги html - всё - баста. Попробуйте вставить код от DrAku1a (сообщение выше).
Прикрепленные файлы:
8. salexdv 2123 07.02.22 11:26 Сейчас в теме
9. salexdv 2123 07.02.22 13:01 Сейчас в теме
(7) Исправил. Справедливости ради замечу, что сервис, ссылку на который вы давали выше тоже выдает ошибку на данном коде. Вернее отображает раскрашенный код он правильно, а вот код для вставки содержит ошибку. Вся проблема в том, что такие HTML-сущности как <> не преобразуются в соответствующие символы. Алгоритм от DrAku1a (6) имеет ту же проблему.
10. 1v7 229 07.02.22 13:08 Сейчас в теме
(9) О! Теперь работает как надо. Спасибо!
12. 1v7 229 07.02.22 13:43 Сейчас в теме
(9) Теперь не корректно красит где в тексте знаки сравнения (<>). Из-за:
Код = СтрЗаменить(Код, "<", "<");
Код = СтрЗаменить(Код, ">", ">");
Но если закомментировать эти замены, ожидаемо сносит html.
По мне так очень сложно пофиксить данный баг. Одни и те же символы выполняют разные роли. Тут даже логику не применить никак
13. salexdv 2123 07.02.22 13:46 Сейчас в теме
(12) Да. такое действительно может быть. Чуть позже исправлю. Скорее всего надо заменять только парные HTML-сущности
15. salexdv 2123 07.02.22 14:37 Сейчас в теме
18. 1v7 229 07.02.22 14:52 Сейчас в теме
20. user1259182 2 07.02.22 16:08 Сейчас в теме
А в режиме реального времени чтоб красил это же текстовое поле с сохранением позиции курсора можно сделать?
21. salexdv 2123 07.02.22 16:13 Сейчас в теме
(20) Для раскрашивания в режиме реального времени лучше использовать эту разработку или, например, решения на основе библиотек SyntaxHighlighter и highlight.js
22. ctahok2 04.08.22 16:02 Сейчас в теме
Оставьте свое сообщение
Вакансии
Программист/тестировщик
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Ведущий разработчик 1С / Team lead отдела разработки 1С
Москва
зарплата от 300 000 руб. до 300 000 руб.
Полный день

Программист 1С
Москва
зарплата от 150 000 руб. до 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 150 000 руб. до 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день