<commit_before>import Ember from 'ember';
import appendRange from '../utils/dom/append-range';
import appendCachedRange from '../utils/dom/append-cached-range';

const {
  run,
  Object: Obj
  } = Ember;

const DEFAULT_EXPIRES = 1000 * 5; // 5s

export default Obj.extend({
  _isSustainFactory: true,

  sustainService: null,

  // params exposed via the `{{sustain}}` helper
  component: '', // component name passed into the flexi-sustain marker
  label: null,
  model: null,
  copy: false,
  expires: DEFAULT_EXPIRES,

  // the element where the content should currently be rendered
  parent: null,

  // the content
  range: null,

  // reference to the sustain-container component where the content
  // was initially rendered
  _component: null,

  // caches the teardown handler
  removeTimeout: null,
  storeTimeout: null,

  // caches clone info
  _previousParent: null,
  _previousCopy: false,
  _previousClone: false,

  // caches a range when tearing down
  _cachedRange: false,

  cache() {
    this._cachedRange = this.getNodeRange();
  },

  remove() {
    this.cache();

    if (this.get('copy')) {
      this._previousParent = this.parent;
      this._previousCopy = true;
      this._previousClone = this.cloneNodeRange();
    }

    this.scheduleStorage();
    this.scheduleRemove();

    this.triggerHook('willMove');
  },

  triggerHook(name) {
    if (this._component[name]) {
      this._component[name]();
    }
    this._component.trigger(name);
  },

  // called each time the location of parent has changed
  insert(to) {
    run.cancel(this.removeTimeout);
    run.cancel(this.storeTimeout);

    // initial insert
    if (!this._isReady) {
      this.parent = to.parent;
      return;
    }

    // move to new location
    if (this._cachedRange) {
      appendCachedRange(to.parent, this._cachedRange);
      this._cachedRange = null;
    } else {
      this.triggerHook('willMove');
      appendRange(to.parent, this.range.firstNode, this.range.lastNode);
    }
    this.triggerHook('didMove');

    // leave copy in old location
    if (this._previousClone) {
      let parent = this._previousParent;
      let clone = this._previousClone;

      appendCachedRange(parent, clone);
      this._previousClone = null;
      this._previousParent = null;
    }

    // update params
    this.parent = to.parent;

    this.setProperties({
      copy: to.copy,
      model: to.model
    });

    let expires = this.get('expires');
    if ((to.expires || to.expires === 0) && expires !== 0 && expires !== -1) {
      if (!expires || to.expires === 0 || to.expires === -1 || to.expires > expires) {
        this.set('expires', to.expires);
      }
    }

  },

  getNodeRange() {
    let node = this.range.firstNode;
    let list = [];

    list.push(node);
    while (node !== this.range.lastNode) {
      list.push(node);
      node = node.nextSibling;
    }

    return list;
  },

  cloneNodeRange() {<commit_msg>fix(tagless components): tagless components are now correctly handled<commit_after>import Ember from 'ember';
import appendRange from '../utils/dom/append-range';
import appendCachedRange from '../utils/dom/append-cached-range';

const {
  run,
  Object: Obj
  } = Ember;

const DEFAULT_EXPIRES = 1000 * 5; // 5s

export default Obj.extend({
  _isSustainFactory: true,

  sustainService: null,

  // params exposed via the `{{sustain}}` helper
  component: '', // component name passed into the flexi-sustain marker
  label: null,
  model: null,
  copy: false,
  expires: DEFAULT_EXPIRES,

  // the element where the content should currently be rendered
  parent: null,

  // the content
  range: null,

  // reference to the sustain-container component where the content
  // was initially rendered
  _component: null,

  // caches the teardown handler
  removeTimeout: null,
  storeTimeout: null,

  // caches clone info
  _previousParent: null,
  _previousCopy: false,
  _previousClone: false,

  // caches a range when tearing down
  _cachedRange: false,

  cache() {
    this._cachedRange = this.getNodeRange();
  },

  remove() {
    this.cache();

    if (this.get('copy')) {
      this._previousParent = this.parent;
      this._previousCopy = true;
      this._previousClone = this.cloneNodeRange();
    }

    this.scheduleStorage();
    this.scheduleRemove();

    this.triggerHook('willMove');
  },

  triggerHook(name) {
    if (this._component[name]) {
      this._component[name]();
    }
    this._component.trigger(name);
  },

  // called each time the location of parent has changed
  insert(to) {
    run.cancel(this.removeTimeout);
    run.cancel(this.storeTimeout);

    // initial insert
    if (!this._isReady) {
      this.parent = to.parent;
      return;
    }

    // move to new location
    if (this._cachedRange) {
      appendCachedRange(to.parent, this._cachedRange);
      this._cachedRange = null;
    } else {
      this.triggerHook('willMove');
      appendRange(to.parent, this.range.firstNode, this.range.lastNode);
    }
    this.triggerHook('didMove');

    // leave copy in old location
    if (this._previousClone) {
      let parent = this._previousParent;
      let clone = this._previousClone;

      appendCachedRange(parent, clone);
      this._previousClone = null;
      this._previousParent = null;
    }

    // update params
    this.parent = to.parent;

    this.setProperties({
      copy: to.copy,
      model: to.model
    });

    let expires = this.get('expires');
    if ((to.expires || to.expires === 0) && expires !== 0 && expires !== -1) {
      if (!expires || to.expires === 0 || to.expires === -1 || to.expires > expires) {
        this.set('expires', to.expires);
      }
    }

  },

  getNodeRange() {
    let node = this.range.firstNode;
    let list = [];

    while (node !== this.range.lastNode) {
      list.push(node);
      node = node.nextSibling;
    }
    list.push(node);

    return list;
  },

  cloneNodeRange() {
{'fraction_non_alphanumeric': 0.13055929919137466, 'fraction_numerical': 0.003706199460916442, 'mean_word_length': 2.7059925093632957, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '3057376', 'n_tokens_mistral': 1891, 'n_tokens_neox': 1824, 'n_words': 457}