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

Support complex / deep / nested attributes #48

Closed
wants to merge 1 commit into from

Commits on Feb 19, 2020

  1. Support complex / deep / nested attributes

    This change adds support for complex attributes, which might have
    arbitrarily nested properties:
    
    ```json
    {
      "insert": "some text",
      "attributes": {
        "complexAttribute": {
          "prop1": {
            "subPropA": "a",
            "subPropB": 2
          },
          "prop2": true
        }
      }
    }
    ```
    
    ## Motivation
    
    The particular use case with which this was written in mind is the
    addition of comments to Quill. That is, the ability to select part of a
    document, and add some extra information about that selection.
    
    Comments can be applied to arbitrary content, so cannot be represented
    as an embed (for example). They naturally belong to the attributes:
    
    ```json
    {
      "insert": "This text is commented",
      "attributes": {
        "comment": "comment-id"
      }
    }
    ```
    
    The issue with comments is that multiple comments may exist on the same
    range:
    
    ```json
    {
      "insert": "this text is commented",
      "attributes": {
        "comment": {
          "comment-id-1": true,
          "comment-id-2": true
        }
      }
    }
    ```
    
    These cannot be "flattened", because the IDs are arbitrary strings,
    which:
    
      - could collide with other attributes who rely on IDs like this
      - does not map neatly to a Quill attributor / blot
    
    Any other metadata-like attributes may also benefit from this sort of
    deeply nested structure. For example, a naive git-blame-like feature
    might look like:
    
    ```json
    {
      "insert": "\n",
      "attributes": {
        "blame": {
          "hash1": {
            "author": "Alec Gibson",
            "timestamp": 1582123032,
          }
        }
      }
    }
    ```
    
    ## Implementation
    
    This change adds support to all of `compose`, `diff`, `invert` and
    `transform` for complex attributes.
    
    The implementation is recursive, and each depth of attributes is
    treated similarly to the top level. In particular:
    
      - `null` will remove a property
      - an empty object is treated as `null`
    
    ```javascript
    const attributes = {complex: {foo: 123}}
    const update = {complex: {foo: null}}
    AttributeMap.compose(attributes, update) // => undefined
    ```
    
    ### Arrays
    
    Note that arrays are out-of-scope of this change. Their behaviour is not
    well defined when composing deltas together, and they are treated as if
    they are primitive values (ie they directly overwrite one another,
    rather than attempt a deep change).
    
    ## Quill integration
    
    Quill will not natively support these changes, and further work will be
    required if this capability is to be adopted there. Given that Quill v2
    is currently in development, this may be a good time to do this work, if
    desirable.
    
    In particular:
    
      - `format()` methods need to `compose` values rather than simply
        overwrite
      - `merge()` methods need to perform deep equality checks, rather than
        object reference checks
    
    Note that Quill can currently support these complex attributes, but only
    with blots that override the above methods.
    
    ## Backwards compatibility
    
    This change is not technically backwards-compatible. If anyone is
    already using deeply nested attributes and relying on the current
    all-or-nothing behaviour, then this change will break their code.
    Alec Gibson committed Feb 19, 2020
    Configuration menu
    Copy the full SHA
    88174dd View commit details
    Browse the repository at this point in the history