Добавлена обработка многострочного выделения для списков и цитат в компонентах NoteEditor и NoteItem. Улучшена логика добавления тегов в зависимости от формата выделенного текста, включая поддержку чекбоксов и нумерованных списков.
This commit is contained in:
parent
bdd932bbbb
commit
e3b98ea8d3
@ -327,15 +327,79 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
|||||||
newEnd = start + innerText.length;
|
newEnd = start + innerText.length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Добавляем теги
|
// Проверяем, является ли это форматированием списка или цитаты
|
||||||
newText =
|
const isListFormatting = /^[-*+]\s|^\d+\.\s|^- \[ \]\s|^>\s/.test(before);
|
||||||
content.substring(0, start) +
|
const isMultiline = selectedText.includes("\n");
|
||||||
before +
|
|
||||||
selectedText +
|
if (isListFormatting && isMultiline) {
|
||||||
after +
|
// Обрабатываем многострочное выделение для списков
|
||||||
content.substring(end);
|
const lines = selectedText.split("\n");
|
||||||
newStart = start + before.length;
|
let processedLines: string[] = [];
|
||||||
newEnd = end + before.length;
|
let currentNumber = 1;
|
||||||
|
let isFirstNonEmptyLine = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
const trimmedLine = line.trim();
|
||||||
|
|
||||||
|
// Пропускаем пустые строки
|
||||||
|
if (trimmedLine === "") {
|
||||||
|
processedLines.push(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Определяем отступ текущей строки
|
||||||
|
const indentMatch = line.match(/^(\s*)/);
|
||||||
|
const indent = indentMatch ? indentMatch[1] : "";
|
||||||
|
|
||||||
|
// Обрабатываем в зависимости от типа маркера
|
||||||
|
if (before.startsWith("- [ ]")) {
|
||||||
|
// Чекбокс
|
||||||
|
processedLines.push(indent + "- [ ] " + trimmedLine);
|
||||||
|
} else if (before.startsWith("- ")) {
|
||||||
|
// Маркированный список
|
||||||
|
processedLines.push(indent + "- " + trimmedLine);
|
||||||
|
} else if (before.match(/^\d+\.\s/)) {
|
||||||
|
// Нумерованный список - извлекаем начальный номер
|
||||||
|
const numberMatch = before.match(/^(\d+)\.\s/);
|
||||||
|
if (numberMatch && isFirstNonEmptyLine) {
|
||||||
|
// Для первой непустой строки используем номер из маркера
|
||||||
|
currentNumber = parseInt(numberMatch[1]);
|
||||||
|
isFirstNonEmptyLine = false;
|
||||||
|
} else if (isFirstNonEmptyLine) {
|
||||||
|
// Если маркера нет, начинаем с 1
|
||||||
|
currentNumber = 1;
|
||||||
|
isFirstNonEmptyLine = false;
|
||||||
|
}
|
||||||
|
processedLines.push(indent + currentNumber + ". " + trimmedLine);
|
||||||
|
currentNumber++;
|
||||||
|
} else if (before.startsWith("> ")) {
|
||||||
|
// Цитата
|
||||||
|
processedLines.push(indent + "> " + trimmedLine);
|
||||||
|
} else {
|
||||||
|
// Для других форматов просто добавляем маркер
|
||||||
|
processedLines.push(indent + before + trimmedLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedText = processedLines.join("\n");
|
||||||
|
newText =
|
||||||
|
content.substring(0, start) +
|
||||||
|
processedText +
|
||||||
|
content.substring(end);
|
||||||
|
newStart = start + before.length;
|
||||||
|
newEnd = start + processedText.length;
|
||||||
|
} else {
|
||||||
|
// Добавляем теги обычным способом
|
||||||
|
newText =
|
||||||
|
content.substring(0, start) +
|
||||||
|
before +
|
||||||
|
selectedText +
|
||||||
|
after +
|
||||||
|
content.substring(end);
|
||||||
|
newStart = start + before.length;
|
||||||
|
newEnd = end + before.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setContent(newText);
|
setContent(newText);
|
||||||
|
|||||||
@ -416,15 +416,79 @@ export const NoteItem: React.FC<NoteItemProps> = ({
|
|||||||
newEnd = start + innerText.length;
|
newEnd = start + innerText.length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Добавляем теги
|
// Проверяем, является ли это форматированием списка или цитаты
|
||||||
newText =
|
const isListFormatting = /^[-*+]\s|^\d+\.\s|^- \[ \]\s|^>\s/.test(before);
|
||||||
editContent.substring(0, start) +
|
const isMultiline = selectedText.includes("\n");
|
||||||
before +
|
|
||||||
selectedText +
|
if (isListFormatting && isMultiline) {
|
||||||
after +
|
// Обрабатываем многострочное выделение для списков
|
||||||
editContent.substring(end);
|
const lines = selectedText.split("\n");
|
||||||
newStart = start + before.length;
|
let processedLines: string[] = [];
|
||||||
newEnd = end + before.length;
|
let currentNumber = 1;
|
||||||
|
let isFirstNonEmptyLine = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
const trimmedLine = line.trim();
|
||||||
|
|
||||||
|
// Пропускаем пустые строки
|
||||||
|
if (trimmedLine === "") {
|
||||||
|
processedLines.push(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Определяем отступ текущей строки
|
||||||
|
const indentMatch = line.match(/^(\s*)/);
|
||||||
|
const indent = indentMatch ? indentMatch[1] : "";
|
||||||
|
|
||||||
|
// Обрабатываем в зависимости от типа маркера
|
||||||
|
if (before.startsWith("- [ ]")) {
|
||||||
|
// Чекбокс
|
||||||
|
processedLines.push(indent + "- [ ] " + trimmedLine);
|
||||||
|
} else if (before.startsWith("- ")) {
|
||||||
|
// Маркированный список
|
||||||
|
processedLines.push(indent + "- " + trimmedLine);
|
||||||
|
} else if (before.match(/^\d+\.\s/)) {
|
||||||
|
// Нумерованный список - извлекаем начальный номер
|
||||||
|
const numberMatch = before.match(/^(\d+)\.\s/);
|
||||||
|
if (numberMatch && isFirstNonEmptyLine) {
|
||||||
|
// Для первой непустой строки используем номер из маркера
|
||||||
|
currentNumber = parseInt(numberMatch[1]);
|
||||||
|
isFirstNonEmptyLine = false;
|
||||||
|
} else if (isFirstNonEmptyLine) {
|
||||||
|
// Если маркера нет, начинаем с 1
|
||||||
|
currentNumber = 1;
|
||||||
|
isFirstNonEmptyLine = false;
|
||||||
|
}
|
||||||
|
processedLines.push(indent + currentNumber + ". " + trimmedLine);
|
||||||
|
currentNumber++;
|
||||||
|
} else if (before.startsWith("> ")) {
|
||||||
|
// Цитата
|
||||||
|
processedLines.push(indent + "> " + trimmedLine);
|
||||||
|
} else {
|
||||||
|
// Для других форматов просто добавляем маркер
|
||||||
|
processedLines.push(indent + before + trimmedLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedText = processedLines.join("\n");
|
||||||
|
newText =
|
||||||
|
editContent.substring(0, start) +
|
||||||
|
processedText +
|
||||||
|
editContent.substring(end);
|
||||||
|
newStart = start + before.length;
|
||||||
|
newEnd = start + processedText.length;
|
||||||
|
} else {
|
||||||
|
// Добавляем теги обычным способом
|
||||||
|
newText =
|
||||||
|
editContent.substring(0, start) +
|
||||||
|
before +
|
||||||
|
selectedText +
|
||||||
|
after +
|
||||||
|
editContent.substring(end);
|
||||||
|
newStart = start + before.length;
|
||||||
|
newEnd = end + before.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setEditContent(newText);
|
setEditContent(newText);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user