## Style Attributes > If you haven't yet, read introduction to Zefyr document model called > Notus [here][data_and_document]; Style attributes in Notus documents are simple key-value pairs, where keys identify the attribute and value describes the style applied, for instance, `{ "heading": 1 }` defines heading style for a line of text with value `1` (equivalent of `h1` in HTML). Note that one attribute can describe multiple different styles depending on the current value. E.g. attribute with key "heading" can be set to values `1`, `2` or `3`, equivalents of `h1`, `h2` and `h3` in HTML. This prevents a line of text from being formatted as `h1` and `h2` heading at the same time, which is intentional. Additionally, each attribute gets assigned one of two scopes. An attribute can be either *inline-scoped* or *line-scoped*, but not both. A good example of an inline-scoped attribute is "bold" attribute. Bold style can be applied to any character within a line, but not to the line itself. Similarly "heading" style is line-scoped and has effect only on the line as a whole. Below table summarizes information about all currently supported attributes in Zefyr: | Name | Key | Scope | Type | Valid values | |---------|-----------|----------|----------|----------------------------------------| | Bold | `b` | `inline` | `bool` | `true` | | Italic | `i` | `inline` | `bool` | `true` | | Link | `a` | `inline` | `String` | Non-empty string | | Heading | `heading` | `line` | `int` | `1`, `2` and `3` | | Block | `block` | `line` | `String` | `"ul"`, `"ol"`, `"code"` and `"quote"` | | Embed | `embed` | `inline` | `Map` | `"hr"`, `"image"` | Removing a specific style is as simple as setting corresponding attribute to `null`. Here is an example of applying some styles to a document: ```dart import 'package:notus/notus.dart'; void makeItPretty(NotusDocument document) { /// All attributes can be accessed through [NotusAttribute] class. // Format 5 characters starting at index 0 as bold. document.format(0, 5, NotusAttribute.bold); // Similarly for italic. document.format(0, 5, NotusAttribute.italic); // Format the first line as a heading (level 1). // Note that there is no need to specify character range of the whole // line. Simply set index position to anywhere within the line and // length to 0. document.format(0, 0, NotusAttribute.heading.level1); // Add a link: document.format(10, 15, NotusAttribute.link.fromString('https://github.com')); // Format a line as code block. Similarly to heading styles there is no need // to specify the whole character range of the line. In following example: // whichever line is at character index 23 in the document will get // formatted as code block. document.format(23, 0, NotusAttribute.block.code); // Remove heading style from the first line. All attributes // have `unset` property which can be used the same way. document.format(0, 0, NotusAttribute.heading.unset); } ``` ### How attributes are stored in Deltas As mentioned previously a document delta consists of a sequence of `insert` operations. Attributes (if any) are stored as metadata on each of the operations. There is a difference in how line and inline-scoped attributes are handled. Since Deltas are essentially a flat data structure there is nothing in the format itself to represent a line of text, which is required to allow storing line-scoped style attributes. To solve this issue Notus document (similarly to Quill.js) reserves the **newline** character (aka `\n` and `0x0A`) as storage for line-scoped styles. Notus document model is designed to enforce this rule and prevents malformed changes from being composed into a document. For instance, an attempt to apply "bold" style to a newline character will have no effect. Below is an example of Notus document's Delta with two lines of text. The first line is formatted as an `h1` heading and on the second line there is bold-styled word "Flutter": ```dart var delta = new Delta(); delta ..insert('Zefyr Editor') ..insert('\n', attributes: {'heading': 1}) ..insert('A rich text editor for '); ..insert('Flutter', attributes: {'b': true}); ..insert('\n'); ``` Note that there is no block-level scope for style attributes. Again, given flat structure of Deltas there is nothing that can represent a block of lines which share the same style, e.g. bullet list. And we already reserved newline character for line styles. As it turns out, this is not a big issue and it is possible to achieve a friendly user experience without this extra level in a document model. The `block` attribute in Notus documents is line-scoped. To change a group of lines from "bullet list" to "number list" we need to update block style on each of the lines individually. Zefyr editor abstracts away such details with help of [heuristic rules][heuristics]. ### Next up * [Heuristics][heuristics] [heuristics]: /doc/heuristics.md ### Previous * [Data Format and Document Model][data_and_document] [data_and_document]: /doc/data_and_document.md