Добавлена обработка многострочного выделения для списков и цитат в компонентах NoteEditor и NoteItem. Улучшена логика добавления тегов в зависимости от формата выделенного текста, включая поддержку чекбоксов и нумерованных списков.
This commit is contained in:
parent
bdd932bbbb
commit
e3b98ea8d3
@ -327,7 +327,70 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
newEnd = start + innerText.length;
|
||||
}
|
||||
} else {
|
||||
// Добавляем теги
|
||||
// Проверяем, является ли это форматированием списка или цитаты
|
||||
const isListFormatting = /^[-*+]\s|^\d+\.\s|^- \[ \]\s|^>\s/.test(before);
|
||||
const isMultiline = selectedText.includes("\n");
|
||||
|
||||
if (isListFormatting && isMultiline) {
|
||||
// Обрабатываем многострочное выделение для списков
|
||||
const lines = selectedText.split("\n");
|
||||
let processedLines: string[] = [];
|
||||
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 +
|
||||
@ -337,6 +400,7 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
newStart = start + before.length;
|
||||
newEnd = end + before.length;
|
||||
}
|
||||
}
|
||||
|
||||
setContent(newText);
|
||||
|
||||
|
||||
@ -416,7 +416,70 @@ export const NoteItem: React.FC<NoteItemProps> = ({
|
||||
newEnd = start + innerText.length;
|
||||
}
|
||||
} else {
|
||||
// Добавляем теги
|
||||
// Проверяем, является ли это форматированием списка или цитаты
|
||||
const isListFormatting = /^[-*+]\s|^\d+\.\s|^- \[ \]\s|^>\s/.test(before);
|
||||
const isMultiline = selectedText.includes("\n");
|
||||
|
||||
if (isListFormatting && isMultiline) {
|
||||
// Обрабатываем многострочное выделение для списков
|
||||
const lines = selectedText.split("\n");
|
||||
let processedLines: string[] = [];
|
||||
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 +
|
||||
@ -426,6 +489,7 @@ export const NoteItem: React.FC<NoteItemProps> = ({
|
||||
newStart = start + before.length;
|
||||
newEnd = end + before.length;
|
||||
}
|
||||
}
|
||||
|
||||
setEditContent(newText);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user