<commit_before>/* global HTMLElement */
var schema = require('./schema');
var styleParser = require('style-attr');
var systems = require('./system');
var utils = require('../utils/');

var parseProperties = schema.parseProperties;
var parseProperty = schema.parseProperty;
var processSchema = schema.process;
var isSingleProp = schema.isSingleProperty;
var stringifyProperties = schema.stringifyProperties;
var stringifyProperty = schema.stringifyProperty;
var components = module.exports.components = {}; // Keep track of registered components.

/**
 * Component class definition.
 *
 * Components configure appearance, modify behavior, or add functionality to
 * entities. The behavior and appearance of an entity can be changed at runtime
 * by adding, removing, or updating components. Entities do not share instances
 * of components.
 *
 * @namespace Component
 * @property {object} data - Stores component data, populated by parsing the
 *           attribute name of the component plus applying defaults and mixins.
 * @property {object} el - Reference to the entity element.
 * @property {string} name - Name of the attribute the component is connected
 *           to.
 * @member {Element} el
 * @member {object} data
 * @member {function} getData
 * @member {function} init
 * @member {function} update
 * @member {function} remove
 * @member {function} parse
 * @member {function} stringify
 */
var Component = module.exports.Component = function (el) {
  var name = this.name;
  var elData = HTMLElement.prototype.getAttribute.call(el, name);

  this.el = el;
  // The last parameter of builData suppresses the warnings
  // We don't want to display warning messages when parsing the data
  // before updating the schema
  this.updateSchema(buildData(el, name, this.schema, elData, true));
  this.data = buildData(el, name, this.schema, elData);
  this.init();
  this.update();
};

Component.prototype = {
  /**
   * Contains the type schema and defaults for the data values.
   * Data is coerced into the types of the values of the defaults.
   */
  schema: { },

  /**
   * Init handler. Similar to attachedCallback.
   * Called during component initialization and is only run once.
   * Components can use this to set initial state.
   */
  init: function () { /* no-op */ },

  /**
   * Update handler. Similar to attributeChangedCallback.
   * Called whenever component's data changes.
   * Also called on component initialization when the component receives initial data.
   *
   * @param {object} prevData - Previous attributes of the component.
   */
  update: function (prevData) { /* no-op */ },

  updateSchema: function (prevData) { /* no-op */ },

  /**
   * Tick handler.
   * Called on each tick of the scene render loop.
   * Affected by play and pause.
   *
   * @param {number} time - Scene tick time.
   * @param {number} timeDelta - Difference in current render time and previous render time.
   */
  tick: undefined,

  /**
   * Called to start any dynamic behavior (e.g., animation, AI, events, physics).
   */
  play: function () { /* no-op */ },

  /**
   * Called to stop any dynamic behavior (e.g., animation, AI, events, physics).
   */
  pause: function () { /* no-op */ },

  /**
   * Remove handler. Similar to detachedCallback.
   * Called whenever component is removed from the entity (i.e., removeAttribute).
   * Components can use this to reset behavior on the entity.
   */
  remove: function () { /* no-op */ },

  /**
   * Parses each property based on property type.
   * If component is single-property, then parses the single property value.
   *
   * @param {string} value - HTML attribute value.
   * @param {boolean} silent - Suppress warning messages.
   * @returns {object} Component data.
   */
  parse: function (value, silent) {
    var schema = this.schema;
    if (isSingleProp(schema)) { return parseProperty(value, schema); }
    return parseProperties(objectParse(value), schema, true, silent);
  },

  /**
   * Stringify properties if necessary.
   *
   * Only called from `entity.setAttribute` for properties that accept an object value such as
   * vec3 {x, y, z}.
   *
   * @param {object} data - Complete component data.
   * @returns {string}
   */
  stringify: function (data) {
    var schema = this.schema;
    if (typeof data === 'string') { return data; }

    if (isSingleProp(schema)) { return stringifyProperty(data, schema); }
    data = stringifyProperties(data, schema);
    return objectStringify(data);
  },

  /**
   * Returns a copy of data such that we don't expose the private this.data.
   *
   * @returns {object} data
   */
  getData: function () {
    var data = this.data;
    if (typeof data !== 'object') { return data; }
    return utils.extend({}, data);
  },

  /**
   * Called when new value is coming from the entity (e.g., attributeChangedCb)
   * or from its mixins. Does some parsing and applying before updating the
   * component.
   * Does not update if data has not changed.
   *
   * @param {string} value - HTML attribute value.
   */
  updateProperties: function (value) {
    var el = this.el;
    var isSinglePropSchema = isSingleProp(this.schema);
    var previousData = extendProperties({}, this.data, isSinglePropSchema);

    this.updateSchema(objectParse(value));
    this.data = buildData(el, this.name, this.schema, value);

    // Don't update if properties haven't changed
    if (!isSinglePropSchema && utils.deepEqual(previousData, this.data)) { return; }

    this.update(previousData);

    el.emit('componentchanged', {
      name: this.name,
      newData: this.getData(),
      oldData: previousData
    });
  },

  /**
   * Extends the schema of the component with a given new schema
   * Some components might want to mutate their schema based on
   * certain conditions. e.g: The material component changes its
   * squema based on the selected shader to account for the
   * different uniforms
   *  @param newSchema {object} - Schema that extends the original one.
   */
  extendSchema: function (newSchema) {
    // Copies original schema
    var extendedSchema = utils.extend({}, components[this.name].schema);
    // Extends original schema with the new one
    utils.extend(extendedSchema, newSchema);
    this.schema = processSchema(extendedSchema);
    this.el.emit('schemachanged', { component: this.name });
  }
};

/**
 * Registers a component to A-Frame.
 *
 * @param {string} name - Component name.
 * @param {object} definition - Component property and methods.
 * @returns {object} Component.
 */
module.exports.registerComponent = function (name, definition) {
  var NewComponent;
  var proto = {};

  // Format definition object to prototype object.
  Object.keys(definition).forEach(function (key) {<commit_msg>clean up component comments/jsdocs<commit_after>/* global HTMLElement */
var schema = require('./schema');
var styleParser = require('style-attr');
var systems = require('./system');
var utils = require('../utils/');

var parseProperties = schema.parseProperties;
var parseProperty = schema.parseProperty;
var processSchema = schema.process;
var isSingleProp = schema.isSingleProperty;
var stringifyProperties = schema.stringifyProperties;
var stringifyProperty = schema.stringifyProperty;
var components = module.exports.components = {}; // Keep track of registered components.

/**
 * Component class definition.
 *
 * Components configure appearance, modify behavior, or add functionality to
 * entities. The behavior and appearance of an entity can be changed at runtime
 * by adding, removing, or updating components. Entities do not share instances
 * of components.
 *
 * @member {object} data - Component data populated by parsing the
 *         mapped attribute of the component plus applying defaults and mixins.
 * @member {object} el - Reference to the entity element.
 * @member {string} name - Component name exposed as an HTML attribute.
 */
var Component = module.exports.Component = function (el) {
  var name = this.name;
  var elData = HTMLElement.prototype.getAttribute.call(el, name);

  this.el = el;
  // Check whether we need to rebuild the schema depending on the data.
  // Call buildData with silent flag to suppress warnings when parsing data before updating
  // the schema.
  this.updateSchema(buildData(el, name, this.schema, elData, true));
  this.data = buildData(el, name, this.schema, elData);
  this.init();
  this.update();
};

Component.prototype = {
  /**
   * Contains the type schema and defaults for the data values.
   * Data is coerced into the types of the values of the defaults.
   */
  schema: { },

  /**
   * Init handler. Similar to attachedCallback.
   * Called during component initialization and is only run once.
   * Components can use this to set initial state.
   */
  init: function () { /* no-op */ },

  /**
   * Update handler. Similar to attributeChangedCallback.
   * Called whenever component's data changes.
   * Also called on component initialization when the component receives initial data.
   *
   * @param {object} prevData - Previous attributes of the component.
   */
  update: function (prevData) { /* no-op */ },

  updateSchema: function (prevData) { /* no-op */ },

  /**
   * Tick handler.
   * Called on each tick of the scene render loop.
   * Affected by play and pause.
   *
   * @param {number} time - Scene tick time.
   * @param {number} timeDelta - Difference in current render time and previous render time.
   */
  tick: undefined,

  /**
   * Called to start any dynamic behavior (e.g., animation, AI, events, physics).
   */
  play: function () { /* no-op */ },

  /**
   * Called to stop any dynamic behavior (e.g., animation, AI, events, physics).
   */
  pause: function () { /* no-op */ },

  /**
   * Remove handler. Similar to detachedCallback.
   * Called whenever component is removed from the entity (i.e., removeAttribute).
   * Components can use this to reset behavior on the entity.
   */
  remove: function () { /* no-op */ },

  /**
   * Parses each property based on property type.
   * If component is single-property, then parses the single property value.
   *
   * @param {string} value - HTML attribute value.
   * @param {boolean} silent - Suppress warning messages.
   * @returns {object} Component data.
   */
  parse: function (value, silent) {
    var schema = this.schema;
    if (isSingleProp(schema)) { return parseProperty(value, schema); }
    return parseProperties(objectParse(value), schema, true, silent);
  },

  /**
   * Stringify properties if necessary.
   *
   * Only called from `Entity.setAttribute` for properties whose parsers accept a non-string
   * value (e.g., selector, vec3 property types).
   *
   * @param {object} data - Complete component data.
   * @returns {string}
   */
  stringify: function (data) {
    var schema = this.schema;
    if (typeof data === 'string') { return data; }

    if (isSingleProp(schema)) { return stringifyProperty(data, schema); }
    data = stringifyProperties(data, schema);
    return objectStringify(data);
  },

  /**
   * Returns a copy of data such that we don't expose the private this.data.
   *
   * @returns {object} data
   */
  getData: function () {
    var data = this.data;
    if (typeof data !== 'object') { return data; }
    return utils.extend({}, data);
  },

  /**
   * Apply new component data if data has changed.
   *
   * @param {string} value - HTML attribute value.
   */
  updateProperties: function (value) {
    var el = this.el;
    var isSinglePropSchema = isSingleProp(this.schema);
    var previousData = extendProperties({}, this.data, isSinglePropSchema);

    this.updateSchema(objectParse(value));
    this.data = buildData(el, this.name, this.schema, value);

    // Don't update if properties haven't changed
    if (!isSinglePropSchema && utils.deepEqual(previousData, this.data)) { return; }

    this.update(previousData);

    el.emit('componentchanged', {
      name: this.name,
      newData: this.getData(),
      oldData: previousData
    });
  },

  /**
   * Extend schema of component given a partial schema.
   *
   * Some components might want to mutate their schema based on certain properties.
   * e.g., Material component changes its schema based on `shader` to account for different
   * uniforms
   *
   * @param {object} schemaAddon - Schema chunk that extend base schema.
   */
  extendSchema: function (schemaAddon) {
    // Clone base schema.
    var extendedSchema = utils.extend({}, components[this.name].schema);
    // Extend base schema with new schema chunk.
    utils.extend(extendedSchema, schemaAddon);
    this.schema = processSchema(extendedSchema);
    this.el.emit('schemachanged', { component: this.name });
  }
};

/**
 * Registers a component to A-Frame.
 *
 * @param {string} name - Component name.
 * @param {object} definition - Component schema and lifecycle method handlers.
 * @returns {object} Component.
 */
module.exports.registerComponent = function (name, definition) {
  var NewComponent;
  var proto = {};

  // Format definition object to prototype object.
  Object.keys(definition).forEach(function (key) {
{'fraction_non_alphanumeric': 0.1140203988430507, 'fraction_numerical': 0.00015223017202009437, 'mean_word_length': 3.2728455284552846, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4188482', 'n_tokens_mistral': 3650, 'n_tokens_neox': 3578, 'n_words': 1329}