Add autoformater for book dialogues
This commit is contained in:
parent
b32c26cb04
commit
2aa9b37d4e
|
|
@ -1,3 +1,62 @@
|
|||
class DialogueFormatter {
|
||||
constructor(quill) {
|
||||
this.quill = quill;
|
||||
this.setupKeyboardHandling();
|
||||
}
|
||||
|
||||
setupKeyboardHandling() {
|
||||
this.quill.keyboard.addBinding({
|
||||
key: ' ',
|
||||
shortKey: false,
|
||||
handler: (range, context) => {
|
||||
return this.handleSpacePress(range, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleSpacePress(range, context) {
|
||||
// Проверяем, достаточно ли символов для проверки
|
||||
if (range.index < 2) return true;
|
||||
|
||||
// Получаем текст от начала строки до текущей позиции
|
||||
const lineStart = this.getLineStart(range.index);
|
||||
const textBeforeCursor = this.quill.getText(lineStart, range.index - lineStart);
|
||||
|
||||
// Проверяем, начинается ли строка с "-" и пробел будет первым пробелом после дефиса
|
||||
if (this.isBeginningOfLine(lineStart, range.index) &&
|
||||
textBeforeCursor === '-') {
|
||||
|
||||
// Сохраняем текущую позицию курсора
|
||||
const savedPosition = range.index;
|
||||
|
||||
// Заменяем дефис на тире, сохраняя пробел
|
||||
this.quill.deleteText(range.index - 1, 2, 'user');
|
||||
this.quill.insertText(range.index - 1, '— ', 'user');
|
||||
|
||||
// Восстанавливаем курсор после пробела
|
||||
setTimeout(() => {
|
||||
this.quill.setSelection(savedPosition + 2, 0, 'silent');
|
||||
}, 0);
|
||||
|
||||
return true; // Разрешаем стандартную обработку пробела
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getLineStart(index) {
|
||||
let lineStart = index;
|
||||
while (lineStart > 0 && this.quill.getText(lineStart - 1, 1) !== '\n') {
|
||||
lineStart--;
|
||||
}
|
||||
return lineStart;
|
||||
}
|
||||
|
||||
isBeginningOfLine(lineStart, currentIndex) {
|
||||
return currentIndex === lineStart + 1;
|
||||
}
|
||||
}
|
||||
|
||||
class WriterEditor {
|
||||
constructor(formSelector = '#chapter-form', editorContainerId = 'quill-editor', textareaId = 'content') {
|
||||
this.form = document.querySelector(formSelector);
|
||||
|
|
@ -15,6 +74,8 @@ class WriterEditor {
|
|||
toolbar: [
|
||||
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
||||
['bold','italic','underline','strike'],
|
||||
[{ 'align': [] }],
|
||||
[{ 'color': [] }, { 'background': [] }],
|
||||
['blockquote','code-block'],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'script': 'sub'}, { 'script': 'super' }],
|
||||
|
|
@ -22,17 +83,40 @@ class WriterEditor {
|
|||
[{ 'size': ['small', false, 'large', 'huge'] }],
|
||||
[{ 'font': [] }],
|
||||
['link','image','video'],
|
||||
['clean']
|
||||
['clean'],
|
||||
],
|
||||
history: { delay: 1000, maxStack: 100, userOnly: true }
|
||||
history: { delay: 1000, maxStack: 100, userOnly: true },
|
||||
keyboard: {
|
||||
bindings: {
|
||||
// Отключаем автоформатирование списков для дефиса с пробелом
|
||||
'list autofill': {
|
||||
key: ' ',
|
||||
format: ['list'],
|
||||
handler: function(range, context) {
|
||||
// Если это начало строки с дефисом - не создаем список
|
||||
if (context.prefix && context.prefix.trim() === '-') {
|
||||
return true; // Пропускаем автоформатирование
|
||||
}
|
||||
// Стандартная обработка для других случаев
|
||||
return Quill.import('modules/keyboard').bindings['list autofill'].handler.call(this, range, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
placeholder: 'Введите текст главы...'
|
||||
});
|
||||
|
||||
// Инициализируем автоформатер диалогов
|
||||
new DialogueFormatter(this.quill);
|
||||
|
||||
// Загружаем текст
|
||||
const rawContent = this.editorContainer.dataset.content || '';
|
||||
if (rawContent.trim()) this.quill.root.innerHTML = rawContent.trim();
|
||||
|
||||
// Обрабатываем уже существующие диалоги при загрузке
|
||||
setTimeout(() => this.formatExistingDialogues(), 100);
|
||||
|
||||
// Синхронизация с textarea
|
||||
const sync = () => {
|
||||
let html = this.quill.root.innerHTML;
|
||||
|
|
@ -47,8 +131,28 @@ class WriterEditor {
|
|||
window.quillEditorInstance = this.quill;
|
||||
window.quillTextarea = this.textarea;
|
||||
}
|
||||
|
||||
// Форматирование уже существующих диалогов при загрузке
|
||||
formatExistingDialogues() {
|
||||
const text = this.quill.getText();
|
||||
const lines = text.split('\n');
|
||||
|
||||
let totalOffset = 0;
|
||||
lines.forEach((line, index) => {
|
||||
if (line.startsWith('- ')) {
|
||||
// Находим позицию для замены
|
||||
const replacePosition = totalOffset;
|
||||
|
||||
// Заменяем дефис на тире
|
||||
this.quill.deleteText(replacePosition, 1, 'silent');
|
||||
this.quill.insertText(replacePosition, '—', 'silent');
|
||||
}
|
||||
|
||||
totalOffset += line.length + 1; // +1 для символа новой строки
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.writerEditor = new WriterEditor();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue