Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added 'custom' attribute for non-UI attributes #184

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.idea/
packages/zefyr/example/ios/Flutter/flutter_export_environment.sh
.DS_Store
.idea/
7 changes: 6 additions & 1 deletion doc/concepts/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ 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.
only on the line as a whole. A custom *inline-scoped* attributes can be
added for tracking of non-UI based attributes.

Below table summarizes information about all currently supported
attributes in Zefyr:
Expand All @@ -32,6 +33,7 @@ attributes in Zefyr:
| Heading | `heading` | `line` | `int` | `1`, `2` and `3` |
| Block | `block` | `line` | `String` | `"ul"`, `"ol"`, `"code"` and `"quote"` |
| Embed | `embed` | `inline` | `Map` | `"hr"`, `"image"` |
| Custom | `custom` | `inline` | `String` | Non-empty string |

Removing a specific style is as simple as setting corresponding
attribute to `null`.
Expand Down Expand Up @@ -68,6 +70,9 @@ void makeItPretty(NotusDocument document) {
// 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);

// Add a custom attribute that does not reflect in the UI
document.format(15, 23, NotusAttribute.custom.withValue('customAttribute'));
}
```

Expand Down
1 change: 1 addition & 0 deletions packages/notus/example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void main() {
0, 'Notus package provides rich text document model for Zefyr editor');
doc.format(0, 5, NotusAttribute.bold); // Makes first word bold.
doc.format(0, 0, NotusAttribute.h1); // Makes first line a heading.
doc.format(15, 23, NotusAttribute.custom.withValue('customAttribute')); // Adds a non-UI custom attribute
doc.delete(23, 10); // Deletes "rich text " segment.

// Collects style attributes at 1 character in this document.
Expand Down
17 changes: 17 additions & 0 deletions packages/notus/lib/src/document/attributes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
NotusAttribute.heading.key: NotusAttribute.heading,
NotusAttribute.block.key: NotusAttribute.block,
NotusAttribute.embed.key: NotusAttribute.embed,
NotusAttribute.custom.key: NotusAttribute.custom,
};

// Inline attributes
Expand Down Expand Up @@ -126,6 +127,9 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
// ignore: const_eval_throws_exception
static const embed = EmbedAttributeBuilder._();

/// Custom attribute.
static final custom = CustomAttributeBuilder._();

static NotusAttribute _fromKeyValue(String key, dynamic value) {
if (!_registry.containsKey(key)) {
throw ArgumentError.value(
Expand Down Expand Up @@ -454,3 +458,16 @@ class EmbedAttribute extends NotusAttribute<Map<String, dynamic>> {
return hashObjects(objects);
}
}

/// Builder for custom attributes that do not necessarily need styling.
///
/// There is no need to use this class directly, consider using
/// [NotusAttribute.custom] instead.
class CustomAttributeBuilder extends NotusAttributeBuilder<String> {
static const _kCustom = 'custom';

const CustomAttributeBuilder._() : super._(_kCustom, NotusAttributeScope.inline);

NotusAttribute<String> withValue(String value) => NotusAttribute<String>._(key, scope, value);
}