attribute.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. import 'package:quiver/core.dart';
  2. enum AttributeScope {
  3. INLINE, // refer to https://quilljs.com/docs/formats/#inline
  4. BLOCK, // refer to https://quilljs.com/docs/formats/#block
  5. EMBEDS, // refer to https://quilljs.com/docs/formats/#embeds
  6. IGNORE, // attributes that can be ignored
  7. }
  8. class Attribute<T> {
  9. Attribute(this.key, this.scope, this.value);
  10. final String key;
  11. final AttributeScope scope;
  12. final T value;
  13. static final Map<String, Attribute> _registry = {
  14. Attribute.bold.key: Attribute.bold,
  15. Attribute.italic.key: Attribute.italic,
  16. Attribute.underline.key: Attribute.underline,
  17. Attribute.strikeThrough.key: Attribute.strikeThrough,
  18. Attribute.font.key: Attribute.font,
  19. Attribute.size.key: Attribute.size,
  20. Attribute.link.key: Attribute.link,
  21. Attribute.color.key: Attribute.color,
  22. Attribute.background.key: Attribute.background,
  23. Attribute.placeholder.key: Attribute.placeholder,
  24. Attribute.header.key: Attribute.header,
  25. Attribute.indent.key: Attribute.indent,
  26. Attribute.align.key: Attribute.align,
  27. Attribute.list.key: Attribute.list,
  28. Attribute.codeBlock.key: Attribute.codeBlock,
  29. Attribute.quoteBlock.key: Attribute.quoteBlock,
  30. Attribute.width.key: Attribute.width,
  31. Attribute.height.key: Attribute.height,
  32. Attribute.style.key: Attribute.style,
  33. Attribute.token.key: Attribute.token,
  34. };
  35. // Attribute Properties
  36. static final BoldAttribute bold = BoldAttribute();
  37. static final ItalicAttribute italic = ItalicAttribute();
  38. static final UnderlineAttribute underline = UnderlineAttribute();
  39. static final StrikeThroughAttribute strikeThrough = StrikeThroughAttribute();
  40. static final FontAttribute font = FontAttribute(null);
  41. static final SizeAttribute size = SizeAttribute(null);
  42. static final LinkAttribute link = LinkAttribute(null);
  43. static final ColorAttribute color = ColorAttribute(null);
  44. static final BackgroundAttribute background = BackgroundAttribute(null);
  45. static final PlaceholderAttribute placeholder = PlaceholderAttribute();
  46. static final HeaderAttribute header = HeaderAttribute();
  47. static final IndentAttribute indent = IndentAttribute();
  48. static final AlignAttribute align = AlignAttribute(null);
  49. static final ListAttribute list = ListAttribute(null);
  50. static final CodeBlockAttribute codeBlock = CodeBlockAttribute();
  51. static final QuoteBlockAttribute quoteBlock = QuoteBlockAttribute();
  52. static final WidthAttribute width = WidthAttribute(null);
  53. static final HeightAttribute height = HeightAttribute(null);
  54. static final StyleAttribute style = StyleAttribute(null);
  55. static final TokenAttribute token = TokenAttribute('');
  56. static Attribute<int?> get h1 => HeaderAttribute(level: 1);
  57. static Attribute<int?> get h2 => HeaderAttribute(level: 2);
  58. static Attribute<int?> get h3 => HeaderAttribute(level: 3);
  59. static Attribute<int?> get h4 => HeaderAttribute(level: 4);
  60. static Attribute<int?> get h5 => HeaderAttribute(level: 5);
  61. static Attribute<int?> get h6 => HeaderAttribute(level: 6);
  62. static Attribute<String?> get leftAlignment => AlignAttribute('left');
  63. static Attribute<String?> get centerAlignment => AlignAttribute('center');
  64. static Attribute<String?> get rightAlignment => AlignAttribute('right');
  65. static Attribute<String?> get justifyAlignment => AlignAttribute('justify');
  66. static Attribute<String?> get bullet => ListAttribute('bullet');
  67. static Attribute<String?> get ordered => ListAttribute('ordered');
  68. static Attribute<String?> get checked => ListAttribute('checked');
  69. static Attribute<String?> get unchecked => ListAttribute('unchecked');
  70. static Attribute<int?> get indentL1 => IndentAttribute(level: 1);
  71. static Attribute<int?> get indentL2 => IndentAttribute(level: 2);
  72. static Attribute<int?> get indentL3 => IndentAttribute(level: 3);
  73. static Attribute<int?> get indentL4 => IndentAttribute(level: 4);
  74. static Attribute<int?> get indentL5 => IndentAttribute(level: 5);
  75. static Attribute<int?> get indentL6 => IndentAttribute(level: 6);
  76. static Attribute<int?> getIndentLevel(int? level) {
  77. switch (level) {
  78. case 1:
  79. return indentL1;
  80. case 2:
  81. return indentL2;
  82. case 3:
  83. return indentL3;
  84. case 4:
  85. return indentL4;
  86. case 5:
  87. return indentL5;
  88. default:
  89. return indentL6;
  90. }
  91. }
  92. // Keys Container
  93. static final Set<String> inlineKeys = {
  94. Attribute.bold.key,
  95. Attribute.italic.key,
  96. Attribute.underline.key,
  97. Attribute.strikeThrough.key,
  98. Attribute.link.key,
  99. Attribute.color.key,
  100. Attribute.background.key,
  101. Attribute.placeholder.key,
  102. };
  103. static final Set<String> blockKeys = {
  104. Attribute.header.key,
  105. Attribute.indent.key,
  106. Attribute.align.key,
  107. Attribute.list.key,
  108. Attribute.codeBlock.key,
  109. Attribute.quoteBlock.key,
  110. };
  111. static final Set<String> blockKeysExceptHeader = blockKeys
  112. ..remove(Attribute.header.key);
  113. // Utils
  114. bool get isInline => AttributeScope.INLINE == scope;
  115. bool get isIgnored => AttributeScope.IGNORE == scope;
  116. bool get isBlockExceptHeader => blockKeysExceptHeader.contains(key);
  117. Map<String, dynamic> toJson() => <String, dynamic>{key: value};
  118. static Attribute fromKeyValue(String key, dynamic value) {
  119. if (!_registry.containsKey(key)) {
  120. throw ArgumentError.value(key, 'key "$key" not found.');
  121. }
  122. final origin = _registry[key]!;
  123. final attribute = clone(origin, value);
  124. return attribute;
  125. }
  126. static Attribute clone(Attribute origin, dynamic value) {
  127. return Attribute(origin.key, origin.scope, value);
  128. }
  129. @override
  130. bool operator ==(Object other) {
  131. if (identical(this, other)) return true;
  132. if (other is! Attribute<T>) return false;
  133. final typedOther = other;
  134. return key == typedOther.key &&
  135. scope == typedOther.scope &&
  136. value == typedOther.value;
  137. }
  138. @override
  139. int get hashCode => hash3(key, scope, value);
  140. @override
  141. String toString() {
  142. return 'Attribute{key: $key, scope: $scope, value: $value}';
  143. }
  144. }
  145. /* -------------------------------------------------------------------------- */
  146. /* Attributes Impl */
  147. /* -------------------------------------------------------------------------- */
  148. /* --------------------------------- INLINE --------------------------------- */
  149. class BoldAttribute extends Attribute<bool> {
  150. BoldAttribute() : super('bold', AttributeScope.INLINE, true);
  151. }
  152. class ItalicAttribute extends Attribute<bool> {
  153. ItalicAttribute() : super('italic', AttributeScope.INLINE, true);
  154. }
  155. class UnderlineAttribute extends Attribute<bool> {
  156. UnderlineAttribute() : super('underline', AttributeScope.INLINE, true);
  157. }
  158. class StrikeThroughAttribute extends Attribute<bool> {
  159. StrikeThroughAttribute()
  160. : super('strikethrough', AttributeScope.INLINE, true);
  161. }
  162. class FontAttribute extends Attribute<String?> {
  163. FontAttribute(String? value) : super('font', AttributeScope.INLINE, value);
  164. }
  165. class SizeAttribute extends Attribute<String?> {
  166. SizeAttribute(String? value) : super('size', AttributeScope.INLINE, value);
  167. }
  168. class LinkAttribute extends Attribute<String?> {
  169. LinkAttribute(String? value) : super('link', AttributeScope.INLINE, value);
  170. }
  171. class ColorAttribute extends Attribute<String?> {
  172. ColorAttribute(String? value) : super('color', AttributeScope.INLINE, value);
  173. }
  174. class BackgroundAttribute extends Attribute<String?> {
  175. BackgroundAttribute(String? value)
  176. : super('background', AttributeScope.INLINE, value);
  177. }
  178. class PlaceholderAttribute extends Attribute<bool?> {
  179. PlaceholderAttribute() : super('placeholder', AttributeScope.INLINE, true);
  180. }
  181. /* ---------------------------------- BLOCK --------------------------------- */
  182. class HeaderAttribute extends Attribute<int?> {
  183. HeaderAttribute({int? level}) : super('header', AttributeScope.BLOCK, level);
  184. }
  185. class IndentAttribute extends Attribute<int?> {
  186. IndentAttribute({int? level}) : super('indent', AttributeScope.BLOCK, level);
  187. }
  188. class AlignAttribute extends Attribute<String?> {
  189. AlignAttribute(String? value) : super('align', AttributeScope.BLOCK, value);
  190. }
  191. class ListAttribute extends Attribute<String?> {
  192. ListAttribute(String? value) : super('list', AttributeScope.BLOCK, value);
  193. }
  194. class CodeBlockAttribute extends Attribute<bool?> {
  195. CodeBlockAttribute() : super('code_block', AttributeScope.BLOCK, true);
  196. }
  197. class QuoteBlockAttribute extends Attribute<bool?> {
  198. QuoteBlockAttribute() : super('quote_block', AttributeScope.BLOCK, true);
  199. }
  200. /* --------------------------------- IGNORE --------------------------------- */
  201. class WidthAttribute extends Attribute<String?> {
  202. WidthAttribute(String? value) : super('width', AttributeScope.IGNORE, value);
  203. }
  204. class HeightAttribute extends Attribute<String?> {
  205. HeightAttribute(String? value)
  206. : super('height', AttributeScope.IGNORE, value);
  207. }
  208. class StyleAttribute extends Attribute<String?> {
  209. StyleAttribute(String? value) : super('style', AttributeScope.IGNORE, value);
  210. }
  211. class TokenAttribute extends Attribute<String?> {
  212. TokenAttribute(String? value) : super('token', AttributeScope.IGNORE, value);
  213. }