Quill, как один из самых современных текстовых редакторов, набрал более 35 тысяч звезд на Github. Его многочисленные полезные функции делают его расширяемым, совместимым и простым в использовании. Еще одна важная характеристика Quill заключается в его настраиваемости. Сама функция позволяет разработчикам адаптировать Quill для своих нужд.
При использовании Quill в сообщениях блога очень часто оглавление (TOC) размещается в верхней части сообщения. Это упрощает доступность контента для читателя, а также улучшения поисковой оптимизации (SEO). TOC, если он используется правильно, может одновременно нацеливаться на несколько ключевых слов в одном сообщении в блоге. Следовательно, сообщения могут ранжироваться по нескольким ключевым словам в поисковой выдаче! При этом Quill в сопровождении хорошего оглавления может заинтересовать многих разработчиков.
TOC для сообщений в блогах
Хотя существует много отличных модулей Quill, кажется, что ему не хватает простого оглавления, такого простого, как начать использовать сам Quill. В этой статье мы попробуем создать простую оглавление для поста в блоге. Мы предполагаем, что этот пост в блоге имеет несколько тегов заголовков, и мы стремимся создать список в виде кликабельного оглавления и поместить его в начало поста. Для демонстрации вы можете посмотреть эту запись в блоге.
Создать TOC просто, для этого нужны две вещи: во-первых, теги заголовков должны иметь уникальные идентификаторы, чтобы на них можно было ссылаться, а во-вторых, ссылка, которая переходит на соответствующую позицию в сообщении. Поскольку это не реализуется непосредственно с помощью Quill, нам нужно получить помощь от некоторых модулей и добавить несколько строк кода, чтобы выполнить это.
Ссылки без целевого атрибута
В Quill кажется, что target="_blank"
для ссылок является поведением по умолчанию, поэтому, если у нас есть ссылки для элементов TOC, он открывает ссылку на новой странице, что не является ожидаемым поведением для элементов TOC. Это должна быть ссылка с target="_self"
. На самом деле должно быть два разных типа ссылок, один для оглавления, а другой для обычных ссылок. Ну, настраиваемость Quill может помочь здесь.
var Link = Quill.import('formats/link'); class MyLink extends Link { static create(value) { let node = Link.create(value); value = Link.sanitize(value); node.setAttribute('href', value); if (value.startsWith("#")) { node.removeAttribute('target'); } else { node.setAttribute("target", "_blank"); } return node; } format(name, value) { super.format(name, value); if (name !== this.statics.blotName || !value) { return; } if (value.startsWith("#")) { this.domNode.removeAttribute("target"); } else { this.domNode.setAttribute("target", "_blank"); } } } Quill.register(MyLink);
Он расширяет модуль Quill Link и в методе создания смотрите на значение href
, если оно начинается с #
, атрибут target
будет удален, и будет применяться его поведение по умолчанию (_self
). Для других ссылок открывается новая страница.
Теги заголовков с атрибутом id
Чтобы иметь заголовки с атрибутом id
, можно изменить модуль заголовка следующим образом:
var ids = []; function getRandomId(domNode) { let _id = Math.random().toString(16).slice(2, 9); ids.push(_id); return _id; } class MyHeader extends Header { constructor(domNode) { let a = super(domNode); domNode.setAttribute('id', getRandomId(domNode)); this.cache = {}; } static create(value) { const node = super.create(); return node; } static formats(domNode) { return { id: domNode.getAttribute("id") }; } } Quill.register("formats/header", MyHeader); MyHeader.blotName = "header"
Обратите внимание, что с помощью функции getRandomId()
мы временно присваиваем уникальный идентификатор каждому заголовку. Массив ids
хранит сгенерированные идентификаторы для последующего использования. Эти значения будут заменены соответствующими и значимыми идентификаторами. Теперь у нас есть строительные блоки нашей работы, и мы можем использовать их для создания оглавления для этого поста в блоге. Но мы еще не инициализировали наш редактор Quill, так что давайте сделаем это.
Инициализировать редактор Quill
После настройки нашего Quill нам нужно его инициализировать. Обратите внимание: поскольку я загружаю свой контент из красноречивой модели Laravel, здесь я использую синтаксис блейда Laravel: {!! $post->content !!}
.
var content = new Quill(document.createElement("div"), { theme: 'snow', readonly: false, modules: { syntax: false, toolbar: '', }, }); content.setContents({!! $post->content !!});
Найти заголовки и исправить их идентификаторы
Теперь нам нужно перебрать ops
и найти теги заголовков. Массив headers
содержит теги заголовков, которые мы нашли в операциях, за исключением заголовков, которые содержат только пустую строку ( \n
), потому что иногда теги заголовков включают пустые строки.
Теперь пришло время создать нашу оглавление. Мы можем выполнить это с помощью функции Quill insertText
и добавить каждый заголовок в список (formatLine
). Мы также заменяем пробелы в тексте заголовка на тире.
Контент готов с оглавлением в начале, поэтому давайте покажем его с помощью $(“#q-content”).html(content.root.innerHTML)
.
let index = 0; let headers = []; content.getContents().ops.forEach(ops => { index++; if (ops?.attributes?.header) { if (content.getContents().ops[index - 2].insert !== "\n") { headers.push(content.getContents().ops[index - 2].insert); } } }); headers.slice().reverse().forEach(h => { content.insertText(0, h + '\n', 'link', '#' + h.replace(/\s/g , "-"), { 'color': '#5a3e3e', 'italic': true }); content.formatLine(1, 1, 'list', 'bullet'); }) $("#q-content").html(content.root.innerHTML);
Наконец, мы обновляем случайно созданные идентификаторы их новыми значениями:
ids.forEach(hid => { try { var node = document.getElementById(hid); node.id = node.innerHTML.replace(/\s/g , "-"); } catch (error) { } });
Заключительные слова
Вот и все. У нас есть пост с оглавлением с использованием текстового редактора Quill и некоторых кодов JavaScript. Хотя это прямое и простое решение для создания TOC для Quill, я уверен, что есть много возможностей для его улучшения, и, конечно же, его можно закодировать более надежно и профессионально. Поэтому не стесняйтесь улучшать его и дайте мне знать, как вы с этим справляетесь. Свяжитесь со мной в случае возникновения вопросов.