# Spaces

When a space reads as a plain or a no-break space, and which edits change it.

Word for the web stores a run of spaces as plain and no-break spaces in turn, and `text` reads them that way, so a test that compares text sees U+00A0 where it typed a space. Under tracking, inserting `X ` before ` the` in `pays the supplier` reads a no-break space after the new text:

```js
await Word.run(async context => {
  context.document.body.insertParagraph('pays the supplier', 'End');
  await context.sync();
});
await Word.run(async context => {
  context.document.changeTrackingMode = Word.ChangeTrackingMode.trackAll;
  context.document.body.search(' the').getFirst().insertText('X ', 'Before');
  await context.sync();
  const paragraphs = context.document.body.paragraphs;
  paragraphs.load('items/text');
  await context.sync();
  // paragraphs.items[1].text -> "paysX \u00a0the supplier"
});
```

### Under tracking, spaces side by side read plain and no-break in turn

Once an edit with tracking on changes a paragraph's text, `text` reads each run of spaces in it in turn: a plain space, then a no-break space (U+00A0), and so on. At the paragraph's start, a run starts with a no-break space. So inserting `X ` before ` the` reads `X \u00a0the`.

With tracking on, these edits do it:

- every `insertText`, and the body's `insertParagraph`;
- the body's `insertText`, though it writes its text untracked;
- a tracked `delete` that takes out your own insertion;
- an accept or reject that takes text out.

With tracking off, an edit leaves each space reading as it did. Spaces it leaves side by side read plain, and a no-break space an earlier tracked edit left stays.

`getOoxml`, the saved `.docx` and `search` keep plain spaces, so `search('X  the')` finds `X \u00a0the`.

### Text after a tab is a tab run

Text your add-in inserts right after a tab is a tab run. `getOoxml` writes it as tabs, whatever it holds:

- a space, two spaces, `X` or `X ` each write as one tab;
- each stretch between tabs writes as one tab, so `X\tY` writes as three tabs.

**Differs from Word for the web:** for some such text, Word's `getOoxml` throws `GeneralException` instead, and the document then refuses every `insertOoxml`. [Limitations](https://www.rystic.ai/docs/simulators/word.md#limitations) lists when.

It's a tab run when inserted through `Before` or `Start`, but not through a `Replace`, whose text writes as text. It's a tab run after a tab a tracked delete took, too. It stays one once the insertion is accepted, the tab's deletion included. So a package your add-in reads back and inserts again holds `pays\t\tthe` where it inserted a space before `the`.

`text` and `search` read the text, and the simulator's saved `.docx` keeps it. A space before the tab, after a held space or after a line break writes as written.

### A document read in, and every `insertOoxml`, reads every paragraph's spaces afresh

A document reads every paragraph's spaces afresh in `text` when it is read in as it was written. It does again once an `insertOoxml` goes through, through the body, a paragraph or a range, at any location, tracking on or off. Table cells and a package's own paragraphs are read afresh too. Whatever an edit under tracking had set, each space reads by this rule:

| A space that | Reads as |
|---|---|
| starts a paragraph, ends it or is followed by another space | a no-break space (U+00A0) |
| does anything else | a plain space |

| Text | Reads |
|---|---|
| `aaaa  bbbb` | `aaaa\u00a0 bbbb` |
| `aaaa   bbbb` | `aaaa\u00a0\u00a0 bbbb` |
| ` cccc ` | `\u00a0cccc\u00a0` |

Every other character keeps spaces apart. So a tab, a soft hyphen, a line break, a comment reference or a field between two spaces leaves both plain, even a field whose result reads as nothing. So does a tracked deletion's text or a tracked insertion's. So does each edge of a content control, even an empty one, or of a hyperlink:

- `ffff ` before a control holding ` gggg` reads `ffff  gggg`.
- A pair on one side of an edge still reads `\u00a0 `.

A paragraph a block content control holds has no first or last space. Neither does a cell that a row, cell or table control holds. So a block control's ` mmmm ` reads ` mmmm `.

A refused `insertOoxml` changes no reading. Neither does a range's `TrackAll` `Replace` across a paragraph mark, which changes nothing. Until the next `insertOoxml`, a space an edit leaves reads as that edit's rule says:

| Edit | Spaces |
|---|---|
| untracked | each space reads as it was, and the edit writes its own plain |
| under tracking | its paragraph reads plain and no-break in turn |

`getOoxml`, the saved `.docx` and `search` keep plain spaces, except in a tab run (above). `search` matches a no-break space, in the search text or in the document, with a plain space.

---

Source: https://www.rystic.ai/docs/simulators/word/features/spaces · Markdown: https://www.rystic.ai/docs/simulators/word/features/spaces.md
