attribute.dart 9.3 KB

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