# Текстовые диапазоны и абзацы

- Human documentation: [https://docs.univer.ai/ru-RU/guides/docs/model/text-runs-and-paragraphs](https://docs.univer.ai/ru-RU/guides/docs/model/text-runs-and-paragraphs)

- Agent Markdown: [https://docs.univer.ai/ru-RU/guides/docs/model/text-runs-and-paragraphs.md](https://docs.univer.ai/ru-RU/guides/docs/model/text-runs-and-paragraphs.md)

- Requested language: `ru-RU`

- Content language: `ru-RU`

- Documentation version: `1.2.0`

- Source: [docs/model/text-runs-and-paragraphs.ru-RU.mdx](https://github.com/dream-num/documentation/blob/dev/content/guides/docs/model/text-runs-and-paragraphs.ru-RU.mdx)

---

## Модель на основе индексов

Univer Docs не хранит форматированный текст в виде вложенного дерева. Обычный текст хранится в `body.dataStream`[^utf16-offsets], а стили и структура привязываются к нему с помощью диапазонов индексов.

Наиболее распространённые структуры на основе индексов:

* `ITextRun`: диапазон стиля символов.
* `IParagraph`: метаданные и стиль абзаца.
* `ISectionBreak`: метаданные разрыва раздела.

## ITextRun

`ITextRun` описывает стиль непрерывного диапазона текста.

| Свойство | Тип          | Описание                             |
| -------- | ------------ | ------------------------------------ |
| st       | `number`     | **Начальный индекс включительно.**   |
| ed       | `number`     | **Конечный индекс не включительно.** |
| sId?     | `string`     | Идентификатор связанного стиля.      |
| ts?      | `ITextStyle` | Объект стиля символов.               |

```typescript
const body: IDocumentBody = {
  dataStream: 'Hello Univer\r\n',
  textRuns: [
    {
      st: 0,
      ed: 5,
      ts: { bl: 1 },
    },
    {
      st: 6,
      ed: 12,
      ts: { cl: { rgb: '#2563eb' } },
    },
  ],
}
```

В этом примере `Hello` выделено полужирным, а `Univer` — синим цветом. Разрыв абзаца `\r\n` не входит в стилизованные диапазоны.

## IParagraph

`IParagraph` описывает метаданные уровня абзаца. `startIndex` указывает на позицию разрыва абзаца в `dataStream`.

| Свойство        | Тип               | Описание                                                                            |
| --------------- | ----------------- | ----------------------------------------------------------------------------------- |
| startIndex      | `number`          | Индекс разрыва абзаца.                                                              |
| paragraphId     | `string`          | Стабильный идентификатор абзаца.                                                    |
| paragraphStyle? | `IParagraphStyle` | Стиль абзаца, например выравнивание, отступы, межстрочный интервал и тип заголовка. |
| bullet?         | `IBullet`         | Метаданные маркера списка.                                                          |

```typescript
const body: IDocumentBody = {
  dataStream: 'Hello Univer\r\nSecond line\r\n',
  paragraphs: [
    {
      startIndex: 12,
      paragraphId: 'p-1',
      paragraphStyle: {
        namedStyleType: NamedStyleType.HEADING_1,
      },
    },
    {
      startIndex: 25,
      paragraphId: 'p-2',
    },
  ],
}
```

## ISectionBreak

`ISectionBreak` также использует индекс для привязки настроек раздела к текстовому потоку. Для отдельного раздела он позволяет переопределить размер страницы, поля, колонтитулы, колонки и направление текста.

```typescript
const body: IDocumentBody = {
  dataStream: 'First section\nSecond section\r\n',
  sectionBreaks: [
    {
      startIndex: 13,
      pageSize: { width: 595, height: 842 },
      marginTop: 72,
      marginBottom: 72,
    },
  ],
}
```

## Примечания

* Следите, чтобы индексы соответствовали `dataStream`. Неверные индексы могут привести к рассогласованию диапазонов стилей, абзацев, выделения или отрисовки.
* Для редактирования активного документа рекомендуется использовать Facade API и команды.
* При создании снимка вручную сначала сформируйте `dataStream`, а затем вычислите по этой строке диапазоны и позиции абзацев.

[^utf16-offsets]: Смещения измеряются в кодовых единицах UTF-16 JavaScript, а не видимых символах: `"😀".length` равно 2. Текстовый диапазон `[st, ed)` не включает конец, в отличие от диапазонов ячеек.
