<commit_before>#= require trix/models/document
#= require trix/models/line_break_insertion

{normalizeRange, rangesAreEqual, rangeIsCollapsed, objectsAreEqual, arrayStartsWith, summarizeArrayChange, getAllAttributeNames, getBlockConfig, getTextConfig, extend} = Trix

class Trix.Composition extends Trix.BasicObject
  constructor: ->
    @document = new Trix.Document
    @attachments = []
    @currentAttributes = {}
    @revision = 0

  setDocument: (document) ->
    unless document.isEqualTo(@document)
      @document = document
      @refreshAttachments()
      @revision++
      @delegate?.compositionDidChangeDocument?(document)

  # Snapshots

  getSnapshot: ->
    document: @document
    selectedRange: @getSelectedRange()

  loadSnapshot: ({document, selectedRange}) ->
    @delegate?.compositionWillLoadSnapshot?()
    @setDocument(document ? new Trix.Document)
    @setSelection(selectedRange ? [0, 0])
    @delegate?.compositionDidLoadSnapshot?()

  # Responder protocol

  insertText: (text, {updatePosition} = updatePosition: true) ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertTextAtRange(text, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + text.getLength()

    @setSelection(endPosition) if updatePosition
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertBlock: (block = new Trix.Block) ->
    document = new Trix.Document [block]
    @insertDocument(document)

  insertDocument: (document = new Trix.Document) ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertDocumentAtRange(document, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + document.getLength()

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertString: (string, options) ->
    attributes = @getCurrentTextAttributes()
    text = Trix.Text.textForStringWithAttributes(string, attributes)
    @insertText(text, options)

  insertBlockBreak: ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertBlockBreakAtRange(selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + 1

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertLineBreak: ->
    insertion = new Trix.LineBreakInsertion this

    if insertion.shouldDecreaseListLevel()
      @decreaseListLevel()
      @setSelection(insertion.startPosition)
    else if insertion.shouldPrependListItem()
      document = new Trix.Document [insertion.block.copyWithoutText()]
      @insertDocument(document)
    else if insertion.shouldInsertBlockBreak()
      @insertBlockBreak()
    else if insertion.shouldRemoveLastBlockAttribute()
      @removeLastBlockAttribute()
    else if insertion.shouldBreakFormattedBlock()
      @breakFormattedBlock(insertion)
    else
      @insertString("\n")

  insertHTML: (html) ->
    document = Trix.Document.fromHTML(html)
    selectedRange = @getSelectedRange()

    @setDocument(@document.mergeDocumentAtRange(document, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + document.getLength() - 1

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  replaceHTML: (html) ->
    document = Trix.Document.fromHTML(html).copyUsingObjectsFromDocument(@document)
    locationRange = @getLocationRange(strict: false)
    selectedRange = @document.rangeFromLocationRange(locationRange)
    @setDocument(document)
    @setSelection(selectedRange)

  insertFile: (file) ->
    @insertFiles([file])

  insertFiles: (files) ->
    text = new Trix.Text

    for file in files when @delegate?.compositionShouldAcceptFile(file)
      attachment = Trix.Attachment.attachmentForFile(file)
      type = attachment.getType()
      presentation = Trix.config.attachments[type]?.presentation

      attributes = @getCurrentTextAttributes()
      attributes.presentation = presentation if presentation

      attachmentText = Trix.Text.textForAttachmentWithAttributes(attachment, attributes)
      text = text.appendText(attachmentText)

    @insertText(text)

  insertAttachment: (attachment) ->
    attributes = @getCurrentTextAttributes()
    text = Trix.Text.textForAttachmentWithAttributes(attachment, attributes)
    @insertText(text)

  deleteInDirection: (direction) ->
    locationRange = @getLocationRange()
    range = @getSelectedRange()
    selectionIsCollapsed = rangeIsCollapsed(range)

    if selectionIsCollapsed
      deletingIntoPreviousBlock = direction is "backward" and locationRange[0].offset is 0
    else
      selectionSpansBlocks = locationRange[0].index isnt locationRange[1].index

    if deletingIntoPreviousBlock
      if @canDecreaseBlockAttributeLevel()
        block = @getBlock()

        if block.isListItem()
          @decreaseListLevel()
        else
          @decreaseBlockAttributeLevel()<commit_msg>Update Composition#insertAttachment for presentation attribute<commit_after>#= require trix/models/document
#= require trix/models/line_break_insertion

{normalizeRange, rangesAreEqual, rangeIsCollapsed, objectsAreEqual, arrayStartsWith, summarizeArrayChange, getAllAttributeNames, getBlockConfig, getTextConfig, extend} = Trix

class Trix.Composition extends Trix.BasicObject
  constructor: ->
    @document = new Trix.Document
    @attachments = []
    @currentAttributes = {}
    @revision = 0

  setDocument: (document) ->
    unless document.isEqualTo(@document)
      @document = document
      @refreshAttachments()
      @revision++
      @delegate?.compositionDidChangeDocument?(document)

  # Snapshots

  getSnapshot: ->
    document: @document
    selectedRange: @getSelectedRange()

  loadSnapshot: ({document, selectedRange}) ->
    @delegate?.compositionWillLoadSnapshot?()
    @setDocument(document ? new Trix.Document)
    @setSelection(selectedRange ? [0, 0])
    @delegate?.compositionDidLoadSnapshot?()

  # Responder protocol

  insertText: (text, {updatePosition} = updatePosition: true) ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertTextAtRange(text, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + text.getLength()

    @setSelection(endPosition) if updatePosition
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertBlock: (block = new Trix.Block) ->
    document = new Trix.Document [block]
    @insertDocument(document)

  insertDocument: (document = new Trix.Document) ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertDocumentAtRange(document, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + document.getLength()

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertString: (string, options) ->
    attributes = @getCurrentTextAttributes()
    text = Trix.Text.textForStringWithAttributes(string, attributes)
    @insertText(text, options)

  insertBlockBreak: ->
    selectedRange = @getSelectedRange()
    @setDocument(@document.insertBlockBreakAtRange(selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + 1

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  insertLineBreak: ->
    insertion = new Trix.LineBreakInsertion this

    if insertion.shouldDecreaseListLevel()
      @decreaseListLevel()
      @setSelection(insertion.startPosition)
    else if insertion.shouldPrependListItem()
      document = new Trix.Document [insertion.block.copyWithoutText()]
      @insertDocument(document)
    else if insertion.shouldInsertBlockBreak()
      @insertBlockBreak()
    else if insertion.shouldRemoveLastBlockAttribute()
      @removeLastBlockAttribute()
    else if insertion.shouldBreakFormattedBlock()
      @breakFormattedBlock(insertion)
    else
      @insertString("\n")

  insertHTML: (html) ->
    document = Trix.Document.fromHTML(html)
    selectedRange = @getSelectedRange()

    @setDocument(@document.mergeDocumentAtRange(document, selectedRange))

    startPosition = selectedRange[0]
    endPosition = startPosition + document.getLength() - 1

    @setSelection(endPosition)
    @notifyDelegateOfInsertionAtRange([startPosition, endPosition])

  replaceHTML: (html) ->
    document = Trix.Document.fromHTML(html).copyUsingObjectsFromDocument(@document)
    locationRange = @getLocationRange(strict: false)
    selectedRange = @document.rangeFromLocationRange(locationRange)
    @setDocument(document)
    @setSelection(selectedRange)

  insertFile: (file) ->
    @insertFiles([file])

  insertFiles: (files) ->
    attachments = []
    for file in files when @delegate?.compositionShouldAcceptFile(file)
      attachment = Trix.Attachment.attachmentForFile(file)
      attachments.push(attachment)
    @insertAttachments(attachments)

  insertAttachment: (attachment) ->
    @insertAttachments([attachment])

  insertAttachments: (attachments) ->
    text = new Trix.Text

    for attachment in attachments
      type = attachment.getType()
      presentation = Trix.config.attachments[type]?.presentation

      attributes = @getCurrentTextAttributes()
      attributes.presentation = presentation if presentation

      attachmentText = Trix.Text.textForAttachmentWithAttributes(attachment, attributes)
      text = text.appendText(attachmentText)

    @insertText(text)

  deleteInDirection: (direction) ->
    locationRange = @getLocationRange()
    range = @getSelectedRange()
    selectionIsCollapsed = rangeIsCollapsed(range)

    if selectionIsCollapsed
      deletingIntoPreviousBlock = direction is "backward" and locationRange[0].offset is 0
    else
      selectionSpansBlocks = locationRange[0].index isnt locationRange[1].index

    if deletingIntoPreviousBlock
      if @canDecreaseBlockAttributeLevel()
        block = @getBlock()

        if block.isListItem()
          @decreaseListLevel()
        else
          @decreaseBlockAttributeLevel()
{'fraction_non_alphanumeric': 0.09694633857100504, 'fraction_numerical': 0.002569423856112264, 'mean_word_length': 4.455525606469003, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2745066', 'n_tokens_mistral': 2781, 'n_tokens_neox': 2689, 'n_words': 517}