Код
Помещает многострочный код отдельно от обычного текста. В пустом абзаце введите три обратные кавычки и нажмите Space или Enter либо выполните преобразование с панели инструментов. Если после кавычек указать имя языка, например ts, оно также будет сохранено.
Имя языка служит идентификатором подсветки синтаксиса; вручную можно ввести и имя вне зарегистрированного списка. Блок кода не поддерживает выравнивание абзаца, поскольку содержимое и отступы кода должны сохраняться.
npm install nabi-noteimport {
createNabiWith, mountSurface, mountToolbar, mountContextToolbar,
mountHints, watchSettle, detailsWing, codeWing, youtubeWing,
mountViewTools,
} from 'nabi-note'
const selected = [
detailsWing,
codeWing,
youtubeWing,
]
const { nabi, registry } = createNabiWith(selected)
// Bring your own highlighter (Prism, highlight.js, Shiki, …) — the wing stays as it is
// and only the attach is swapped (`makeCodeAttach` ships from the same door)
// { ...codeWing, attach: makeCodeAttach({ highlight: (source, lang) => [{ text: source }] }) }
const root = document.querySelector('.nabi')!
const content = document.querySelector('.nabi-content')!
// The locale also sets the direction — Arabic and Urdu run right to left
mountSurface({ nabi, registry, root: content, locale: 'ru' })
const settle = watchSettle(document, { surface: content })
const shared = { nabi, registry, surface: content, settle, locale: 'ru' }
const toolbar = mountToolbar({ ...shared, root: document.querySelector('#toolbar')! })
const context = mountContextToolbar({ ...shared, root: document.querySelector('#context')! })
mountHints({ toolbar, context, root, surface: content })
// The preview and fullscreen buttons — they stand their own box at the end of the row
mountViewTools({ ...shared, root, container: document.querySelector('#toolbar')! })
// on every change — hook up your own code here
// nabi.onChange(() => user_callback(nabi.getHtml()))const selected = wings().use('code').build()Подключение подсветки кода
После регистрации блока кода редактор использует базовую раскраску. Чтобы раскрашивать код и на опубликованной странице, подключите nabi-note/viewer. Viewer находит pre > code и читает значение data-nabi-lang родителя как имя языка. Если значения нет, он проверяет класс language-... элемента code.
import { attachViewer } from 'nabi-note/viewer'
const viewer = attachViewer(article, {
locale: 'ru',
})
// После изменения опубликованного HTML
viewer.refresh()
// При закрытии экрана
viewer.unmount()Если отдельного подсветчика нет или он не умеет обрабатывать этот язык, код раскрашивает встроенный токенизатор без зависимостей. Добавленные подсветчиком токеновые span существуют только на экране и не попадают в сохранённый JSON или исходный опубликованный HTML. refresh() и unmount() удаляют эти span и заново подключаются к текущему исходному коду.
Как сайт NABI подключает Shiki
Чтобы не включать Shiki в первый экран и SSR bundle, сайт NABI загружает подсветчик динамически. loadCodeHighlighting() из nabi-web/docs/.vitepress/src/highlight.ts создаёт Shiki core и загружает грамматику языка лишь тогда, когда в ней действительно возникает потребность. Ниже показан тот же способ подключения на опубликованной странице.
import { attachViewer } from 'nabi-note/viewer'
import { loadCodeHighlighting } from '../src/highlight'
const highlighting = await loadCodeHighlighting()
const viewer = attachViewer(article, {
locale: 'ru',
highlight: highlighting?.highlight,
})
const stop = highlighting?.onGrammarLoaded(() => viewer.refresh())
// При закрытии экрана
stop?.()
viewer.unmount()При первой встрече с языком начинается загрузка его грамматики; до её завершения используется встроенный токенизатор или обычный текст. После загрузки onGrammarLoaded() вызывает viewer.refresh() и раскрашивает код заново. Поэтому скачиваются только нужные языки, а поздно загруженная грамматика применяется без перехода на другой экран.
Редактор использует ту же функцию highlight. В демонстрации сайта NABI только attach базовой codeWing заменён на makeCodeAttach({ highlight, version }). Значение version меняется при загрузке каждой грамматики и сообщает, что уже отрисованный код нужно раскрасить заново. Отдельному сервису достаточно сначала подключить подсветку опубликованной страницы, а этот способ стоит добавлять лишь тогда, когда Shiki действительно нужен во время редактирования.
CSS-стили
Блок кода оформляется через .nabi-content pre, а сам код — через .nabi-content pre > code. Не меняйте white-space: это влияет на переносы строк и редактирование кода. Цвета токенов можно изменить селектором [data-nabi-token].
.nabi-content [data-nabi-token="keyword"] { color: #7b4fd0; }
.nabi-content [data-nabi-token="string"] { color: #a2543a; }