|
@@ -0,0 +1,126 @@
|
|
1
|
+## Style Attributes
|
|
2
|
+
|
|
3
|
+Style attributes in Zefyr documents are simple key-value pairs, where
|
|
4
|
+keys identify the attribute and value describes the style applied, for
|
|
5
|
+instance, `{ "heading": 1 }` defines heading style for a line of
|
|
6
|
+text with value `1` (equivalent of `h1` in HTML).
|
|
7
|
+
|
|
8
|
+It is important to note
|
|
9
|
+that one attribute can describe multiple different styles depending
|
|
10
|
+on the current value. E.g. attribute with key "heading" can be set to values
|
|
11
|
+`1`, `2` or `3`, equivalents of `h1`, `h2` and `h3` in HTML. This prevents
|
|
12
|
+a line of text from being formatted as `h1` and `h2` heading at the same time,
|
|
13
|
+which is intentional.
|
|
14
|
+
|
|
15
|
+Additionally, each attribute gets assigned one of two scopes. An
|
|
16
|
+attribute can be either *inline-scoped* or *line-scoped*, but not both.
|
|
17
|
+A good example of an inline-scoped attribute is "bold" attribute. Bold
|
|
18
|
+style can be applied to any character within a line, but not the the
|
|
19
|
+line itself. Similarly "heading" style is line-scoped and has effect
|
|
20
|
+only on the line as a whole.
|
|
21
|
+
|
|
22
|
+Below table summarizes information about all currently supported
|
|
23
|
+attributes in Zefyr:
|
|
24
|
+
|
|
25
|
+| Name | Key | Scope | Type | Valid values |
|
|
26
|
+|---------|-----------|----------|----------|----------------------------------------|
|
|
27
|
+| Bold | `b` | `inline` | `bool` | `true` |
|
|
28
|
+| Italic | `i` | `inline` | `bool` | `true` |
|
|
29
|
+| Link | `a` | `inline` | `String` | Non-empty string |
|
|
30
|
+| Heading | `heading` | `line` | `int` | `1`, `2` and `3` |
|
|
31
|
+| Block | `block` | `line` | `String` | `"ul"`, `"ol"`, `"code"` and `"quote"` |
|
|
32
|
+
|
|
33
|
+Removing a specific style is as simple as setting corresponding
|
|
34
|
+attribute to `null`.
|
|
35
|
+
|
|
36
|
+Here is an example of applying some styles to a document:
|
|
37
|
+
|
|
38
|
+```dart
|
|
39
|
+import 'package:zefyr/zefyr.dart';
|
|
40
|
+
|
|
41
|
+void makeItPretty(ZefyrDocument document) {
|
|
42
|
+ /// All attributes can be accessed through [ZefyrAttribute] class.
|
|
43
|
+
|
|
44
|
+ // Format 5 characters starting at index 0 as bold.
|
|
45
|
+ document.format(0, 5, ZefyrAttribute.bold);
|
|
46
|
+
|
|
47
|
+ // Similarly for italic.
|
|
48
|
+ document.format(0, 5, ZefyrAttribute.italic);
|
|
49
|
+
|
|
50
|
+ // Format the first line as a heading (level 1).
|
|
51
|
+ // Note that there is no need to specify character range of the whole
|
|
52
|
+ // line. Simply set index position to anywhere within the line and
|
|
53
|
+ // length to 0.
|
|
54
|
+ document.format(0, 0, ZefyrAttribute.heading.level1);
|
|
55
|
+
|
|
56
|
+ // Add a link:
|
|
57
|
+ document.format(10, 15, ZefyrAttribute.link.fromString('https://github.com'));
|
|
58
|
+
|
|
59
|
+ // Format a line as code block. Similarly to heading styles there is no need
|
|
60
|
+ // to specify the whole character range of the line. In following example:
|
|
61
|
+ // whichever line is at character index 23 in the document will get
|
|
62
|
+ // formatted as code block.
|
|
63
|
+ document.format(23, 0, ZefyrAttribute.block.code);
|
|
64
|
+
|
|
65
|
+ // Remove heading style from the first line. All attributes
|
|
66
|
+ // have `unset` property which can be used the same way.
|
|
67
|
+ document.format(0, 0, ZefyrAttribute.heading.unset);
|
|
68
|
+}
|
|
69
|
+```
|
|
70
|
+
|
|
71
|
+### How attributes are stored in Deltas
|
|
72
|
+
|
|
73
|
+As mentioned previously a document delta consists of a sequence of `insert`
|
|
74
|
+operations. Attributes (if any) are stored as metadata on each of the
|
|
75
|
+operations.
|
|
76
|
+
|
|
77
|
+One important detail here is how line and inline-scoped attributes are
|
|
78
|
+handled. Since Deltas are essentially a flat data structure there is
|
|
79
|
+nothing in the format itself to represent a line of text, which is
|
|
80
|
+required to allow storing line-scoped style attributes.
|
|
81
|
+
|
|
82
|
+To solve this issue Zefyr (similarly to Quill.js) reserves the
|
|
83
|
+**newline** character (aka `\n` and `0x0A`) as storage for line-scoped
|
|
84
|
+styles.
|
|
85
|
+
|
|
86
|
+Zefyr's document model is designed to enforce this rule and
|
|
87
|
+prevents malformed changes from being composed into a document. For
|
|
88
|
+instance, an attempt to apply "bold" style to a newline character
|
|
89
|
+will have no effect.
|
|
90
|
+
|
|
91
|
+Below is an example of Zefyr document's Delta with two lines of text.
|
|
92
|
+The first line is formatted as an `h1` heading and on the second line
|
|
93
|
+there is bold-styled word "Flutter":
|
|
94
|
+
|
|
95
|
+```dart
|
|
96
|
+var delta = new Delta();
|
|
97
|
+delta
|
|
98
|
+ ..insert('Zefyr Editor')
|
|
99
|
+ ..insert('\n', attributes: {'heading': 1})
|
|
100
|
+ ..insert('A rich text editor for ');
|
|
101
|
+ ..insert('Flutter', attributes: {'b': true});
|
|
102
|
+ ..insert('\n');
|
|
103
|
+```
|
|
104
|
+
|
|
105
|
+Note that there is no block-level scope for style attributes. Again,
|
|
106
|
+given flat structure of Deltas there is nothing that can represent a
|
|
107
|
+block of lines which share the same style, e.g. bullet list. And we
|
|
108
|
+already reserved newline character for line styles.
|
|
109
|
+
|
|
110
|
+As it turns out, this is not a big issue and it is possible to achieve
|
|
111
|
+a friendly user experience without this extra level in a document model.
|
|
112
|
+
|
|
113
|
+The `block` attribute in Zefyr is line-scoped. To change a group of
|
|
114
|
+lines from "bullet list" to "number list" we need to update block
|
|
115
|
+style on each of the lines individually. Zefyr editor abstracts away
|
|
116
|
+such details with help of [heuristic rules][heuristics].
|
|
117
|
+
|
|
118
|
+### Next up
|
|
119
|
+
|
|
120
|
+* [Heuristics][heuristics]
|
|
121
|
+
|
|
122
|
+[heuristics]: /doc/heuristics.md
|
|
123
|
+
|
|
124
|
+### Previous
|
|
125
|
+
|
|
126
|
+* [Data Format and Document Model](/doc/data_and_document.md)
|