Guest User

Untitled

a guest
Jan 23rd, 2018
330
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.50 KB | None | 0 0
  1. #+TITLE:Quill Blots
  2.  
  3. There are four options for creating a custom blot:
  4.  
  5. +-------+--------+-------+
  6. | | Inline | Block |
  7. +-------+--------+-------+
  8. | Embed | | |
  9. +-------+--------+-------+
  10. | Text | | |
  11. +-------+--------+-------+
  12.  
  13. * Inline vs block
  14. The major difference between inline and block blots is that blocks
  15. cannot be nested. "Instead of wrapping, Block blots replace one
  16. another when applied to the same text range."
  17.  
  18. * TODO Embed vs text
  19. * How Quill/Parchment work
  20. Quill's user-facing interface is based on the =Delta= format:
  21. documents are represented as text strings with properties applied to
  22. certain ranges (this format strongly resembles the Emacs propertized
  23. strings format). Block-level formatting is handled by special-casing
  24. the formatting operations on newlines in the text string.
  25.  
  26. Parchment's interface is tree-based, though it maps into a linear
  27. content model similar to how the DOM does (in the case of the DOM,
  28. the mapping is called document order). In Parchment's tree, nodes
  29. are called Blots, which are instances of a =ShadowBlot= subclass. As
  30. with any tree, there are two main types of blots: parent blots
  31. inherit from =ContainerBlot= and leaf blots inherit from
  32. =LeafBlot=.
  33.  
  34. There's another categorization of blots that's specific to Parchment
  35. however:
  36.  
  37. - Inline blots :: These represent either run-level formatting (e.g.,
  38. bold, italics, etc.) or run-level content (e.g.,
  39. text nodes). Formatting blots are nestable, just
  40. like HTML tags.
  41. - Block blots :: These represent paragraph-level content or
  42. formatting (e.g., block quote) that are not
  43. nestable. E.g., paragraphs can be of type
  44. "unordered list" or "ordered list", but not
  45. both. Block-level content is unspecified in
  46. Parchment, but can be e.g., video or floated
  47. pictures.
  48. * How Quill uses Parchment
  49. Each Quill instance has an associated =Scroll= instance attached to
  50. the main =<div contenteditable>= (viz. =quill.root=). Operations
  51. using the quill API like =quill.applyDelta= or =quill.format= will
  52. typically reduce to calls to one of the following /core methods/ on
  53. the scroll instance:
  54. - formatAt(index, length, name, value) :: apply the format
  55. identified by the string =name= with =value= to the user range
  56. =[index, index + length)=
  57. - insertAt(index, value: string, def?) :: Insert a new string
  58. into the document at =index= (in user coordinates).
  59. - deleteAt(index, length) :: Delete the user range =[index, index +
  60. length)=
  61. - update(mutations, context) :: After any outside modifications to
  62. the DOM, this method synchronizes the Blot's internal data with
  63. its DOM node
  64. - optimize() :: This method "canonicalizes" a Blot tree to ensure
  65. that the Delta -> Blot map remains well-defined.
  66. * The Parchment blot hierarchy
  67. ** ShadowBlot
  68. This is the root blot type, defining core operations on the blot
  69. tree. There are also a number of essentially internal operations
  70. (=attach=, =clone=, ..., =wrap=) made to ease the implementation of
  71. other blots that need to manipulate the blot tree
  72. *** ContainerBlot
  73. Defines a =children= property and extends the [[*How Quill uses Parchment][core methods]] to
  74. forward the call to the appropriate child (modifying the =index=
  75. and =length= parameters accordingly)
  76. **** ScrollBlot
  77. This blot defines a =MutationObserver= to ensure that =update=
  78. and =optimize= are called on descendant nodes after any DOM
  79. modification. This is used as the root blot in quill.
  80. **** FormatBlot
  81. In addition to managing child nodes, this blot handles
  82. =Attributors= (cf. README). It defines an additional API for its
  83. descendant nodes to handle =formatAt= calls. The idea is to
  84. associate with each blot a ={key: value}= /format map/
  85. representing the sum of the blot and its attributors. This map is
  86. used in the following methods:
  87. - formats() :: Return the format map for this blot. The default
  88. implementation starts with the =Attributor=
  89. attributes and simply adds =this.statics.blotName=
  90. to the map with value =static
  91. formats(this.domNode)=
  92. - static formats(domNode) :: Returns the value to use in the
  93. format map for the overal blot
  94. - format(name, value) :: This method is in charge of modifying
  95. the blot tree to mirror the effect of setting =name= to
  96. =value= in the format map.
  97. ***** BlockBlot
  98. BlockBlot handles =formatAt= calls in two ways:
  99. - attributor calls :: These calls use formats registered to
  100. =Attributors= and simply delegate to =FormatBlot=
  101. - all-or-nothing :: These calls replace this blot with another
  102. block-scoped blot.
  103. =insertAt= is modified slightly to ensure that inserting
  104. block-scoped blots splits the blot instead of adding a
  105. child. The other [[*How Quill uses Parchment][core methods]] are essentially unchanged
  106. ***** InlineBlot
  107. InlineBlot handles =formatAt= calls that cause the blot to vanish from
  108. the tree (e.g., removing bolding). It forwards =Attributor=
  109. calls into the [[*FormatBlot][FormatBlot]] API. =InlineBlot.optimize= performs
  110. two optimizations:
  111. 1. If the blot has no children, it is removed from the tree
  112. 2. If the blot and its next sibling have identical formats, they
  113. are merged together
  114. *** LeafBlot
  115. Leaf blots are independent units which have a /value/ associated
  116. with them. Their =static value(domNode)= and =value()= methods
  117. retrieve this value from a dom node and a blot respectively. They
  118. also have =index= and =position= nodes that I don't really
  119. understand
  120. **** TextBlot
  121. Implements =deleteAt= and =insertAt= as expected. =optimize=
  122. removes empty text nodes and merges consecutive text nodes.
  123. **** EmbedBlot
  124. Adds a =format= method for subclasses to override wholesale
  125. formatting of the embed. Similar to [[*FormatBlot][FormatBlot]], adds =static
  126. formats= and =formats= methods as well, though instead of a
  127. key-value map, the two =formats= methods return any value
  128. representing the embed value. (Default ~undefined~)
  129. * Quill blots
  130. Quill extends and overrides Parchment's blots as follows:
  131. ** Container
  132. Only allows quill-specific Blocks, BlockEmbeds, and itself as
  133. children.
  134. *** ScrollBlot
  135. Special-cases various things for code blocks and breaks. Adds a
  136. =whitelist= attribute to restrict which formats may be
  137. used. Ensures that inline blots are always descended from block
  138. blots.
  139. *** FormatBlot
  140. No change
  141. **** Block
  142. Adds a translation layer to the Delta format using newlines to
  143. indicate blocks. Thus, it ignores all-or-nothing =formatAt= calls
  144. unless they include the final newline and modifies =insertAt=
  145. calls to add blocks where needed
  146. **** BlockEmbed
  147. This new element ignores all =formatAt= calls except
  148. Attributors. =insertAt= adds new nodes as siblings rather than
  149. children.
  150. **** Inline
  151. Ensures nested inlines are always nested in the same order (to
  152. ensure a canonical representation as DOM nodes)
  153. ** Leaf
  154. *** Text
  155. No change from Parchment
  156. *** Embed
  157. Wraps the embed in a span with =leftGuard= and =rightGuard= nodes
  158. on either side of the real dom node. Disables contenteditable on
  159. the wrapping span.
  160. * Specific methods
  161. ** Basic blot methods
  162. Every Blot has these structure editing methods, which don't generally
  163. have to be overriden
  164.  
  165. - attach
  166. - clone
  167. - deleteAt
  168. - detach
  169. - formatAt
  170. - insertAt
  171. - insertInto
  172. - isolate
  173. - offset
  174. - optimize
  175. - remove
  176. - replace
  177. - replaceWith
  178. - split
  179. - update
  180. - wrap
  181.  
  182. ** static create(value: any) : Node
  183. This method should create a new `Node` and modify it such that value
  184. is later recoverable. In other words, this should be an invertible
  185. function. Often this involves using the `dataset` API. E.g., a
  186. `LinkBlot` which takes a url as `value` sets the `href` attribute,
  187. which can then be used to recover the url.
  188.  
  189. This method must also set non-format related attributes as
  190. needed (e.g., `target=_blank` on links), since the returned node will
  191. probably be added to the page.
  192.  
  193. The super method creates a `DOMNode` using the `tagName` and
  194. `className` properties.
  195.  
  196. *** When is this method called?
  197. This method is only ever called by `Registry.create`, which is in
  198. turn called whenever Parchment tree manipulations (and their
  199. associated DOM node manipulations) are taking place
Add Comment
Please, Sign In to add comment