# Text Runs and Paragraphs

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

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

- Requested language: `en-US`

- Content language: `en-US`

- Documentation version: `1.0.0-rc.0`

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

---

## Index-Based Model

Univer Docs does not store rich text as a nested tree. It stores plain text in `body.dataStream`, and then uses index ranges to attach style and structure to the text.

The most common index-based structures are:

* `ITextRun`: inline text style range.
* `IParagraph`: paragraph metadata and paragraph style.
* `ISectionBreak`: section break metadata.

## ITextRun

`ITextRun` describes the style of a continuous text range.

| Property | Type         | Description               |
| -------- | ------------ | ------------------------- |
| st       | `number`     | Start index, inclusive.   |
| ed       | `number`     | End index, exclusive.     |
| sId?     | `string`     | Referenced style ID.      |
| ts?      | `ITextStyle` | Inline text style object. |

```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' } },
    },
  ],
}
```

In this example, `Hello` is bold and `Univer` is blue. The paragraph break `\r\n` is not included in the styled ranges.

## IParagraph

`IParagraph` describes paragraph-level metadata. `startIndex` points to the paragraph break position in `dataStream`.

| Property        | Type              | Description                                                                     |
| --------------- | ----------------- | ------------------------------------------------------------------------------- |
| startIndex      | `number`          | Index of the paragraph break.                                                   |
| paragraphId     | `string`          | Stable paragraph ID.                                                            |
| paragraphStyle? | `IParagraphStyle` | Paragraph style such as alignment, indentation, line spacing, and heading type. |
| bullet?         | `IBullet`         | List marker metadata.                                                           |

```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` also uses an index to connect section-level settings to the text stream. It can override page size, margins, headers, footers, columns, and text direction for a section.

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

## Notes

* Keep indexes aligned with `dataStream`. Incorrect indexes can cause style ranges, paragraphs, selections, or rendering to become inconsistent.
* Prefer Facade APIs and commands for editing an active document.
* When generating snapshots manually, build `dataStream` first, then compute ranges and paragraph positions from that string.
