Портфолио
Подсветка

Подсветка синтаксиса

Для подсветки синтаксиса Nextra использует Shiki (opens in a new tab). Это удобно для восприятия кода пользователем. Например, если в Markdown-файле написать:

Markdown
```js
console.log('hello, world')
```

то результат будет выглядеть вот так:

console.log('hello, world')

Возможности

Подсветка внутри текста

Для выделения кода внутри текста допустимо использовать {:}.
Например, чтобы в этой строке подсветить let x = 1, в Markdown-файле мы написали:

Markdown
Например, чтобы в этой строке подсветить `let x = 1{:jsx}`, в Markdown-файле мы написали:

Подсветка строк

Для того, чтобы подсветить определенные строки, используйте атрибут {}.
Внутри фигурных скобок укажите номера или диапазон строк, которые нужно выделить:

Markdown
```js {1,4-5}
import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}
```

В результате получится такое выделение:

import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

Подстветка слов

Для того, чтобы в блоке с кодом выделить определенные слова, используйте //:

Markdown
```js /useState/
import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}
```
import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

Также вы можете выделить только часть вхождений слов. Для этого добавьте номера вхождений или их диапазон: /str/1, or multiple: /str/1-3, /str/1,3.

Кнопка "Скопировать код"

Если в блок кода добавить атрибут copy, то при наведении мышкой на код справа будет появляться кнопка "Скопировать код":

Markdown
```js copy
console.log('hello, world')
```

Попробуйте навести мышкой на этот блок кода:

console.log('hello, world')

Эту возможность вы можете установить на глобальном уровне. Для этого в конфигурационном файле Nextra (next.config.js) укажите defaultShowCopyCode: true. А чтобы затем отключить эту фичу в конкретном блоке с кодом, примените атрибут copy=false.

Нумерация строк

Атрибут showLineNumbers позволяет отобразить в блоке с кодом нумерацию строк:

Markdown
```js showLineNumbers
import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}
```

Вот результат:

import { useState } from 'react'
 
function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

Имена файлов и заголовки

В блок кода можно добавить имена файлов и заголовки. Для этого используйте атрибут filename:

Markdown
```js filename="example.js"
console.log('hello, world')
```

Вот результат:

example.js
console.log('hello, world')

ANSI подсветка

Управляющие последовательности ANSI (англ. ANSI escape codes (opens in a new tab)) можно выделить атрибутом ansi:

Markdown
```ansi
 ✓ src/index.test.ts (1)
   Test Files  1 passed (1)
        Tests  1 passed (1)
     Start at  23:32:41
     Duration  11ms
   PASS  Waiting for file changes...
         press h to show help, press q to quit
```

Результат:

  src/index.test.ts (1)
   Test Files  1 passed (1)
        Tests  1 passed (1)
     Start at  23:32:41
     Duration  11ms
   PASS  Waiting for file changes...
         press h to show help, press q to quit

Поддержка языков

В этом списке (opens in a new tab) перечислены все поддерживаемые языки.

Кастомизация темы

Nextra использует CSS переменные для определения цвета токенов. Вы можете установить глобальный CSS (global CSS (opens in a new tab)), чтобы кастомизировать их под светлую/темную темы. Например, по умолчанию применяются следующие токены. Вы можете переопределить любой из них:

styles.css
:root {
  --shiki-color-text: #414141;
  --shiki-color-background: transparent;
  --shiki-token-constant: #1976d2;
  --shiki-token-string: #22863a;
  --shiki-token-comment: #aaa;
  --shiki-token-keyword: #d32f2f;
  --shiki-token-parameter: #ff9800;
  --shiki-token-function: #6f42c1;
  --shiki-token-string-expression: #22863a;
  --shiki-token-punctuation: #212121;
  --shiki-token-link: #22863a;
}
 
.dark {
  --shiki-color-text: #d1d1d1;
  --shiki-token-constant: #79b8ff;
  --shiki-token-string: #ffab70;
  --shiki-token-comment: #6b737c;
  --shiki-token-keyword: #f97583;
  --shiki-token-parameter: #ff9800;
  --shiki-token-function: #b392f0;
  --shiki-token-string-expression: #4bb74a;
  --shiki-token-punctuation: #bbb;
  --shiki-token-link: #ffab70;
}

Блок кода с динамическим контентом

Поскольку подсветка синтаксиса выполняется во время сборки, вы не можете использовать динамический контент в своих блоках кода. Однако MDX предоставляет обходной путь с помощью клиентского JS. Вот пример:

dynamic_code.js
function hello () {
  const x = 2 + 3
  console.log(1)
}
Увеличить число на единицуИзменить на `1 + 1`

Это решение имеет ограничение. Оно заключается в том, что обновленный контент не будет выделен повторно. Например, если мы изменим число на 1 + 1, оно будет подсвечено неправильно.

Посмотрите этот код (opens in a new tab), чтобы понять, как это работает.

Отключение подсветки синтаксиса

Вы можете отключить предустановленную подстветку синтаксиса и установить свою собственную. Для этого на глобальном уровне в конфигурационном файле Nextra (next.config.js) пропишите атрибут: codeHighlight: false.

OptionTypeDescription
codeHighlightbooleanEnable or disable syntax highlighting. Defaults to 'true'.

Пользовательская грамматика

Shiki поддерживает VSCode TextMate Grammar (opens in a new tab) для подсветки синтаксиса с пользовательской грамматикой языка.

Вы можете настроить грамматику, переопределив параметры функции getHighlighter в mdxOptions.rehypePrettyCodeOptions. Это делается в конфигурационном файле Nextra (next.config.js):

next.config.js
import { BUNDLED_LANGUAGES } from 'shiki'
 
nextra({
  // ... other options
  mdxOptions: {
    rehypePrettyCodeOptions: {
      getHighlighter: options =>
        getHighlighter({
          ...options,
          langs: [
            ...BUNDLED_LANGUAGES,
            // настройки грамматики (custom grammar options). Как их переопределить смотрите в документации по Shiki.
            {
              id: 'my-lang',
              scopeName: 'source.my-lang',
              aliases: ['mylang'], // Наряду с идентификатором, псевдонимы будут включены в список разрешенных имен, которые вы можете использовать при написании Markdown.
              path: '../../public/syntax/grammar.tmLanguage.json'
            }
          ]
        })
    }
  }
})

Пользовательская тема

С помощью mdxOptions.rehypePrettyCodeOptions вы также можете перенастроить пользовательскую тему вместо CSS переменных (CSS Variables):

next.config.js
nextra({
  // ... other options
  mdxOptions: {
    rehypePrettyCodeOptions: {
      // VSCode тема или встроенная тема Shiki. Подробности смотрите в документации по Shiki
      theme: JSON.parse(
        readFileSync('./public/syntax/arctis_light.json', 'utf8')
      )
    }
  }
})

Несколько тем

В настоящее время Nextra не поддерживает одновременное использование нескольких тем. Причина этого в том, что Shiki отображает несколько блоков кода для каждой темы и помечает их атрибутом data-theme, например: data-theme="dark".

Тем не менее в будущем такая возможность будет реализована. Вы сможете отслеживать эти изменения в shikiji (newly fork of Shiki) https://github.com/antfu/shikiji#multiple-themes (opens in a new tab), который уже поддерживает использование нескольких тем без рендеринга нескольких блоков кода.