<commit_before>#!/usr/bin/env node
/*
 *
 * Copyright 2013 Anis Kadri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

// copyright (c) 2013 Andrew Lunny, Adobe Systems
var fs = require('fs')
  , path = require('path')
  , url = require('url')
  , package = require(path.join(__dirname, 'package'))
  , et = require('elementtree')
  , nopt = require('nopt')
  , plugins = require('./util/plugins')
  , shell = require('shelljs')
  , plugin_loader = require('./util/plugin_loader')
  , platform_modules = {
        'android': require('./platforms/android'),
        'ios': require('./platforms/ios'),
        'blackberry': require('./platforms/blackberry'),
        'www': require('./platforms/www')
    };

var known_opts = { 'platform' : [ 'ios', 'android', 'blackberry' ,'www' ]
            , 'project' : path
            , 'plugin' : [String, path, url]
            , 'remove' : Boolean
            , 'list' : Boolean
            , 'v' : Boolean
            , 'debug' : Boolean
            , 'prepare' : Boolean
            , 'plugins': path
            , 'www': path
            , 'variable' : Array
            }, shortHands = { 'var' : 'variable' };

var cli_opts = nopt(known_opts);

// Default the plugins_dir to './cordova/plugins'.
var plugins_dir;

// Without these arguments, the commands will fail and print the usage anyway.
if (cli_opts.plugins_dir || cli_opts.project) {
    plugins_dir = typeof cli_opts.plugins_dir == 'string' ?
        cli_opts.plugins_dir :
        path.join(cli_opts.project, 'cordova', 'plugins');
}

// only dump stack traces in debug mode, otherwise show error message and exit
if (!cli_opts.debug) {
    // provide clean output on exceptions rather than dumping a stack trace
    process.on('uncaughtException', function(error){
        console.error(error + '\n');
        process.exit(1);
    });
}

if (cli_opts.v) {
    console.log(package.name + ' version ' + package.version);
}
else if (cli_opts.list) {
    plugins.listAllPlugins(function(plugins) {
      for(var i = 0, j = plugins.length ; i < j ; i++) {
        console.log(plugins[i].value.name, '-', plugins[i].value.description);
      }
    });
}
else if (cli_opts.prepare && cli_opts.project && cli_opts.www) {
    util.handlePrepare(cli_opts.project, plugins_dir, cli_opts.www, cli_opts.platform);
}
else if (!cli_opts.platform || !cli_opts.project || !cli_opts.plugin) {
    printUsage();
}
else if (cli_opts.remove) {
    handlePlugin('uninstall', cli_opts.platform, cli_opts.project, cli_opts.plugin);
}
else {
  var cli_variables = {}
  if (cli_opts.variable) {
    cli_opts.variable.forEach(function (variable) {
        var tokens = variable.split('=');
        var key = tokens.shift().toUpperCase();
        if (/^[\w-_]+$/.test(key)) cli_variables[key] = tokens.join('=');
        });
  }
  handlePlugin('install', cli_opts.platform, cli_opts.project, cli_opts.plugin, cli_variables);
}

function printUsage() {
    platforms = known_opts.platform.join('|');
<<<<<<< HEAD
    console.error('Usage\n---------');
    console.error('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --variable <preference_name>="<substituion>" --plugin <directory|git-url|name>\n');
    console.error('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.error('List plugins:\n\t' + package.name + ' --list\n');
    process.exit(1);
=======
    console.log('Usage\n---------');
    console.log('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.log('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.log('List plugins:\n\t' + package.name + ' --list\n');
    console.log('Prepare project:\n\t' + package.name + ' --prepare --platform <ios|android|bb10> --project <directory> --www <directory> [--plugins_dir <directory>]');
    console.log('\n\t--plugins_dir defaults to <project>/cordova/plugins, but can be any directory containing a subdirectory for each plugin');
>>>>>>> --prepare with ported JS installation, cache plugins locally
}

function execAction(action, platform, project_dir, plugin_dir, cli_variables) {
    var xml_path     = path.join(plugin_dir, 'plugin.xml')
      , xml_text     = fs.readFileSync(xml_path, 'utf-8')
      , plugin_et    = new et.ElementTree(et.XML(xml_text))
      , filtered_variables = {};

    if (action == 'install') {
        // checking preferences
        prefs = plugin_et.findall('./preference') || [];
        prefs = prefs.concat(plugin_et.findall('./platform[@name="'+platform+'"]/preference'));
        var missing_vars = [];
        prefs.forEach(function (pref) {
            var key = pref.attrib["name"].toUpperCase();
            if (cli_variables[key] == undefined)
                missing_vars.push(key)
            else
                filtered_variables[key] = cli_variables[key]
        })
        if (missing_vars.length > 0) {
            console.error('Variable missing: ' + missing_vars.join(", "));
            return;
        }

        if((info = plugin_et.find('./platform[@name="'+platform+'"]/info'))) {
            console.log(info.text);
        }
    }

    // run the platform-specific function
    try {
      platform_modules[platform].handlePlugin(action, project_dir, plugin_dir, plugin_et, filtered_variables);
      console.log('plugin ' + action + 'ed');
    } catch(e) {
        var revert = (action == "install" ? "force-uninstall" : "force-install" );
        console.error("An error occurred for action", action, ":", e.message, "\nTrying to revert changes...");
        try {
          platform_modules[platform].handlePlugin(revert, project_dir, plugin_dir, plugin_et, filtered_variables);
        } catch(e) {
          console.log("Changes might have not been reverted: "+e.message);
        }
    }
}

function handlePlugin(action, platform, project_dir, plugin_dir, cli_variables) {
    var plugin_xml_path, async = false;

    // Ensure the containing directory exists.
    shell.mkdir('-p', plugins_dir);

    // clone from git repository
    if(plugin_dir.indexOf('https://') == 0 || plugin_dir.indexOf('git://') == 0) {
        plugin_dir = plugins.clonePluginGitRepo(plugin_dir, plugins_dir);
    } else { // Copy from the local filesystem.
        var lastSlash = plugin_dir.lastIndexOf(path.sep);
        var dest = plugin_dir;
        if (lastSlash >= 0) {
            dest = dest.substring(lastSlash+1);
        }
        dest = path.join(plugins_dir, dest);

        shell.rm('-rf', dest);
        shell.cp('-R', plugin_dir, plugins_dir); // Yes, not dest.

        plugin_dir = dest;
    }

    plugin_xml_path = path.join(plugin_dir, 'plugin.xml');
    if (!fs.existsSync(plugin_xml_path)) {
        // try querying the plugin database
        async = true;
        plugins.getPluginInfo(plugin_dir,
            function(plugin_info) {
                execAction(action, platform, project_dir, plugins.clonePluginGitRepo(plugin_info.url), cli_variables);
            },
            function(e) {
                throw new Error(action + ' failed. "' + plugin_xml_path + '" not found');
            }
        );
    }

    if (!platform_modules[platform]) {
        throw { name: "Platform Error", message: platform + " not supported" }
    }

    // check arguments and resolve file paths
    if(!async) {
        execAction(action, platform, project_dir, plugin_dir, cli_variables);
    }
}

<commit_msg>Plugin loading works correctly when using plugman solo.<commit_after>#!/usr/bin/env node
/*
 *
 * Copyright 2013 Anis Kadri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

// copyright (c) 2013 Andrew Lunny, Adobe Systems
var fs = require('fs')
  , path = require('path')
  , url = require('url')
  , package = require(path.join(__dirname, 'package'))
  , et = require('elementtree')
  , nopt = require('nopt')
  , plugins = require('./util/plugins')
  , shell = require('shelljs')
  , plugin_loader = require('./util/plugin_loader')
  , platform_modules = {
        'android': require('./platforms/android'),
        'ios': require('./platforms/ios'),
        'blackberry': require('./platforms/blackberry'),
        'www': require('./platforms/www')
    };

var known_opts = { 'platform' : [ 'ios', 'android', 'blackberry' ,'www' ]
            , 'project' : path
            , 'plugin' : [String, path, url]
            , 'remove' : Boolean
            , 'list' : Boolean
            , 'v' : Boolean
            , 'debug' : Boolean
            , 'prepare' : Boolean
            , 'plugins': path
            , 'www': path
            , 'variable' : Array
            }, shortHands = { 'var' : 'variable' };

var cli_opts = nopt(known_opts);

// Default the plugins_dir to './cordova/plugins'.
var plugins_dir;

// Without these arguments, the commands will fail and print the usage anyway.
if (cli_opts.plugins_dir || cli_opts.project) {
    plugins_dir = typeof cli_opts.plugins_dir == 'string' ?
        cli_opts.plugins_dir :
        path.join(cli_opts.project, 'cordova', 'plugins');
}

// only dump stack traces in debug mode, otherwise show error message and exit
if (!cli_opts.debug) {
    // provide clean output on exceptions rather than dumping a stack trace
    process.on('uncaughtException', function(error){
        console.error(error + '\n');
        process.exit(1);
    });
}

if (cli_opts.v) {
    console.log(package.name + ' version ' + package.version);
}
else if (cli_opts.list) {
    plugins.listAllPlugins(function(plugins) {
      for(var i = 0, j = plugins.length ; i < j ; i++) {
        console.log(plugins[i].value.name, '-', plugins[i].value.description);
      }
    });
}
else if (cli_opts.prepare && cli_opts.project && cli_opts.www) {
    plugin_loader.handlePrepare(cli_opts.project, plugins_dir, cli_opts.www, cli_opts.platform);
}
else if (!cli_opts.platform || !cli_opts.project || !cli_opts.plugin) {
    printUsage();
}
else if (cli_opts.remove) {
    handlePlugin('uninstall', cli_opts.platform, cli_opts.project, cli_opts.plugin);
}
else {
  var cli_variables = {}
  if (cli_opts.variable) {
    cli_opts.variable.forEach(function (variable) {
        var tokens = variable.split('=');
        var key = tokens.shift().toUpperCase();
        if (/^[\w-_]+$/.test(key)) cli_variables[key] = tokens.join('=');
        });
  }
  handlePlugin('install', cli_opts.platform, cli_opts.project, cli_opts.plugin, cli_variables);
}

function printUsage() {
    platforms = known_opts.platform.join('|');
<<<<<<< HEAD
    console.error('Usage\n---------');
    console.error('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --variable <preference_name>="<substituion>" --plugin <directory|git-url|name>\n');
    console.error('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.error('List plugins:\n\t' + package.name + ' --list\n');
    process.exit(1);
=======
    console.log('Usage\n---------');
    console.log('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.log('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
    console.log('List plugins:\n\t' + package.name + ' --list\n');
    console.log('Prepare project:\n\t' + package.name + ' --prepare --platform <ios|android|bb10> --project <directory> --www <directory> [--plugins_dir <directory>]');
    console.log('\n\t--plugins_dir defaults to <project>/cordova/plugins, but can be any directory containing a subdirectory for each plugin');
>>>>>>> --prepare with ported JS installation, cache plugins locally
}

function execAction(action, platform, project_dir, plugin_dir, cli_variables) {
    var xml_path     = path.join(plugin_dir, 'plugin.xml')
      , xml_text     = fs.readFileSync(xml_path, 'utf-8')
      , plugin_et    = new et.ElementTree(et.XML(xml_text))
      , filtered_variables = {};

    if (action == 'install') {
        // checking preferences
        prefs = plugin_et.findall('./preference') || [];
        prefs = prefs.concat(plugin_et.findall('./platform[@name="'+platform+'"]/preference'));
        var missing_vars = [];
        prefs.forEach(function (pref) {
            var key = pref.attrib["name"].toUpperCase();
            if (cli_variables[key] == undefined)
                missing_vars.push(key)
            else
                filtered_variables[key] = cli_variables[key]
        })
        if (missing_vars.length > 0) {
            console.error('Variable missing: ' + missing_vars.join(", "));
            return;
        }

        if((info = plugin_et.find('./platform[@name="'+platform+'"]/info'))) {
            console.log(info.text);
        }
    }

    // run the platform-specific function
    try {
      platform_modules[platform].handlePlugin(action, project_dir, plugin_dir, plugin_et, filtered_variables);
      console.log('plugin ' + action + 'ed');
    } catch(e) {
        var revert = (action == "install" ? "force-uninstall" : "force-install" );
        console.error("An error occurred for action", action, ":", e.message, "\nTrying to revert changes...");
        try {
          platform_modules[platform].handlePlugin(revert, project_dir, plugin_dir, plugin_et, filtered_variables);
        } catch(e) {
          console.log("Changes might have not been reverted: "+e.message);
        }
    }
}

function handlePlugin(action, platform, project_dir, plugin_dir, cli_variables) {
    var plugin_xml_path, async = false;

    // Ensure the containing directory exists.
    shell.mkdir('-p', plugins_dir);

    // clone from git repository
    if(plugin_dir.indexOf('https://') == 0 || plugin_dir.indexOf('git://') == 0) {
        plugin_dir = plugins.clonePluginGitRepo(plugin_dir, plugins_dir);
    } else { // Copy from the local filesystem.
        var lastSlash = plugin_dir.lastIndexOf(path.sep);
        var dest = plugin_dir;
        if (lastSlash >= 0) {
            dest = dest.substring(lastSlash+1);
        }
        dest = path.join(plugins_dir, dest);

        shell.rm('-rf', dest);
        shell.cp('-R', plugin_dir, plugins_dir); // Yes, not dest.

        plugin_dir = dest;
    }

    plugin_xml_path = path.join(plugin_dir, 'plugin.xml');
    if (!fs.existsSync(plugin_xml_path)) {
        // try querying the plugin database
        async = true;
        plugins.getPluginInfo(plugin_dir,
            function(plugin_info) {
                execAction(action, platform, project_dir, plugins.clonePluginGitRepo(plugin_info.url), cli_variables);
            },
            function(e) {
                throw new Error(action + ' failed. "' + plugin_xml_path + '" not found');
            }
        );
    }

    if (!platform_modules[platform]) {
        throw { name: "Platform Error", message: platform + " not supported" }
    }

    // check arguments and resolve file paths
    if(!async) {
        execAction(action, platform, project_dir, plugin_dir, cli_variables);
    }
}

<|endoftext|>


<commit_before>// Define Nutrition Variables
var n = {
	"serving_size_unit":"",
	"serving_size_qty":"",
	"serving_weight_grams":"",
	"servings_per_container":"",
	"calories":"",
	"calories_from_fat":"",
	"total_fat":"",
	"saturated_fat":"",
	"monounsaturated_fat":"",
	"polyunsaturated_fat":"",
	"trans_fatty_acid":"",
	"cholesterol":"",
	"sodium":"",
	"total_carbohydrate":"",
	"dietary_fiber":"",
	"sugars":"",
	"protein":"",
	"vitamin_a_iu":"",
	"vitamin_a_dv":"",
	"vitamin_c_mg":"",
	"vitamin_c_dv":"",
	"calcium_mg":"",
	"calcium_dv":"",
	"iron_mg":"",
	"iron_dv":"";
}

// example call
// n.servings_per_container
// gives you the value of that property in the hash

// ntx(nutriVariables);
// RENDERS | BELOW CONTENT

var nutritionLabel="";
nutritionLabel += "
";
nutritionLabel += "
Nutrition Facts<\/div>";
nutritionLabel += "
";
nutritionLabel += "
Serving Size " + nf_serving_size_qty + " " + n.serving_size_unit + "(" + nf_serving_weight_grams + "g)<\/div>";
nutritionLabel += "
Servings Per Container<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Amount Per Serving<\/b>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
";
nutritionLabel += "
Calories from Fat 110<\/div>";
nutritionLabel += "
";
nutritionLabel += "                    Calories<\/b>250<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "                % Daily Value<\/b>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    18<\/b>%<\/div>";
nutritionLabel += "                Total Fat<\/b>12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    15<\/b>%<\/div>Saturated Fat 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Trans<\/i>Fat 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    10<\/b>%<\/div>";
nutritionLabel += "                Cholesterol<\/b>30mg<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    20<\/b>%<\/div>";
nutritionLabel += "                Sodium<\/b>470g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    10<\/b>%<\/div>";
nutritionLabel += "                Total Carbohydrate<\/b>31g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    0<\/b>%<\/div>Dietary Fiber 12g<\/div>";
nutritionLabel += "
Sugars 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Proteins<\/b>12g<\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "
4%<\/div>Vitamin A<\/div>";
nutritionLabel += "
";
nutritionLabel += "
2%<\/div>Vitamin C<\/div>";
nutritionLabel += "
";
nutritionLabel += "
20%<\/div>Calcium<\/div>";
nutritionLabel += "
";
nutritionLabel += "
4%<\/div>Iron<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    *<\/span>Percent Daily Values are based on a 2,000 calorie diet. Your Daily";
nutritionLabel += "                    Values may be higher or lower depending on your calorie needs:<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "        <\/div>";

document.write(nutritionLabel);
<commit_msg>Update nutritionLabel_v1.0.js<commit_after>// Define Nutrition Variables
var n = {
	"nf_serving_size_unit":"",
	"nf_serving_size_qty":"",
	"nf_serving_weight_grams":"",
	"nf_servings_per_container":"",
	"nf_calories":"",
	"nf_calories_from_fat":"",
	"nf_total_fat":"",
	"nf_saturated_fat":"",
	"nf_monounsaturated_fat":"",
	"nf_polyunsaturated_fat":"",
	"nf_trans_fatty_acid":"",
	"nf_cholesterol":"",
	"nf_sodium":"",
	"nf_total_carbohydrate":"",
	"nf_dietary_fiber":"",
	"nf_sugars":"",
	"nf_protein":"",
	"nf_vitamin_a_iu":"",
	"nf_vitamin_a_dv":"",
	"nf_vitamin_c_mg":"",
	"nf_vitamin_c_dv":"",
	"nf_calcium_mg":"",
	"nf_calcium_dv":"",
	"nf_iron_mg":"",
	"nf_iron_dv":"";
}

// example call
// n.servings_per_container
// gives you the value of that property in the hash

// ntx(nutriVariables);
// RENDERS | BELOW CONTENT

var nutritionLabel="";
nutritionLabel += "
";
nutritionLabel += "
Nutrition Facts<\/div>";
nutritionLabel += "
";
nutritionLabel += "
Serving Size " + n.nf_serving_size_qty + " " + n.nf_serving_size_unit + "(" + n.nf_serving_weight_grams + "g)
";
nutritionLabel += "
Servings Per Container<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Amount Per Serving<\/b>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
";
nutritionLabel += "
Calories from Fat 110<\/div>";
nutritionLabel += "
";
nutritionLabel += "                    Calories<\/b>250<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "                % Daily Value<\/b>";
nutritionLabel += "            <\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    18<\/b>%<\/div>";
nutritionLabel += "                Total Fat<\/b>12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    15<\/b>%<\/div>Saturated Fat 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Trans<\/i>Fat 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    10<\/b>%<\/div>";
nutritionLabel += "                Cholesterol<\/b>30mg<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    20<\/b>%<\/div>";
nutritionLabel += "                Sodium<\/b>470g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    10<\/b>%<\/div>";
nutritionLabel += "                Total Carbohydrate<\/b>31g<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    0<\/b>%<\/div>Dietary Fiber 12g<\/div>";
nutritionLabel += "
Sugars 12g<\/div>";
nutritionLabel += "
";
nutritionLabel += "                Proteins<\/b>12g<\/div>";
nutritionLabel += "
<\/div>";
nutritionLabel += "
";
nutritionLabel += "
4%<\/div>Vitamin A<\/div>";
nutritionLabel += "
";
nutritionLabel += "
2%<\/div>Vitamin C<\/div>";
nutritionLabel += "
";
nutritionLabel += "
20%<\/div>Calcium<\/div>";
nutritionLabel += "
";
nutritionLabel += "
4%<\/div>Iron<\/div>";
nutritionLabel += "
";
nutritionLabel += "
";
nutritionLabel += "                    *<\/span>Percent Daily Values are based on a 2,000 calorie diet. Your Daily";
nutritionLabel += "                    Values may be higher or lower depending on your calorie needs:<\/div>";
nutritionLabel += "            <\/div>";
nutritionLabel += "        <\/div>";

document.write(nutritionLabel);
<|endoftext|>


<commit_before>/* eslint-disable import/no-unresolved, import/extensions */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { View, Image, Text, StyleSheet } from 'react-native';
import { ViewPropTypes } from '../utils';
/* eslint-enable import/no-unresolved, import/extensions */
import Icon from '../Icon';
import withTheme from '../styles/withTheme';

const propTypes = {
  /**
   * If passed in, this component will render image.
   */
  image: PropTypes.shape({ type: PropTypes.oneOf([Image]) }),
  /**
   * If passed in, this component will render icon element inside avatar.
   */
  icon: PropTypes.string,
  /**
   * If passed in, this component will render an icon with this color.
   */
  iconColor: PropTypes.string,
  /**
   * If passed in, this component will render an icon with this size.
   */
  iconSize: PropTypes.number,
  /**
   * If passed in, this component will render text element inside avatar.
   */
  text: PropTypes.string,
  /**
   * It's just sugar for: style: { width: size, height: size, borderRadius: size / 2 }
   */
  size: PropTypes.number,
  /**
   * Inline style of avatar
   */
  style: PropTypes.shape({
    container: ViewPropTypes.style,
    content: Text.propTypes.style, // eslint-disable-line
  }),
  /**
   * Theme
   */
  theme: PropTypes.any, // eslint-disable-line
};
const defaultProps = {
  image: null,
  icon: null,
  iconColor: null,
  iconSize: null,
  text: null,
  size: 48,
  style: {},
};

function getStyles(props) {
  const { size, theme } = props;
  const { avatar } = theme;

  const local = {};

  if (size) {
    local.container = {
      height: size,
      width: size,
      borderRadius: size / 2,
    };
  }

  return {
    container: [avatar.container, local.container, props.style.container],
    content: [avatar.content, local.content, props.style.content],
  };
}

class Avatar extends PureComponent {
  render() {
    const { image, icon, iconSize, iconColor, text, theme } = this.props;
    const { avatar, spacing } = theme;

    let content = null;

    const styles = getStyles(this.props);

    if (icon) {
      const color = iconColor || StyleSheet.flatten(avatar.content).color;
      const size = iconSize || spacing.iconSize;
      content = <Icon name={icon} color={color} size={size} />;
    } else if (text) {
      content = <Text style={styles.content}>{text}</Text>;
    } else if (image) {
      content = image;
    }

    return (
      <View style={{ flexGrow: 1 }}>
        <View style={styles.container}>{content}</View>
      </View>
    );
  }
}

Avatar.propTypes = propTypes;
Avatar.defaultProps = defaultProps;

export default withTheme(Avatar);
<commit_msg>replace Avatar image prop validation with element (#351)<commit_after>/* eslint-disable import/no-unresolved, import/extensions */
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native';
import { ViewPropTypes } from '../utils';
/* eslint-enable import/no-unresolved, import/extensions */
import Icon from '../Icon';
import withTheme from '../styles/withTheme';

const propTypes = {
  /**
   * If passed in, this component will render image.
   */
  image: PropTypes.element,
  /**
   * If passed in, this component will render icon element inside avatar.
   */
  icon: PropTypes.string,
  /**
   * If passed in, this component will render an icon with this color.
   */
  iconColor: PropTypes.string,
  /**
   * If passed in, this component will render an icon with this size.
   */
  iconSize: PropTypes.number,
  /**
   * If passed in, this component will render text element inside avatar.
   */
  text: PropTypes.string,
  /**
   * It's just sugar for: style: { width: size, height: size, borderRadius: size / 2 }
   */
  size: PropTypes.number,
  /**
   * Inline style of avatar
   */
  style: PropTypes.shape({
    container: ViewPropTypes.style,
    content: Text.propTypes.style, // eslint-disable-line
  }),
  /**
   * Theme
   */
  theme: PropTypes.any, // eslint-disable-line
};
const defaultProps = {
  image: null,
  icon: null,
  iconColor: null,
  iconSize: null,
  text: null,
  size: 48,
  style: {},
};

function getStyles(props) {
  const { size, theme } = props;
  const { avatar } = theme;

  const local = {};

  if (size) {
    local.container = {
      height: size,
      width: size,
      borderRadius: size / 2,
    };
  }

  return {
    container: [avatar.container, local.container, props.style.container],
    content: [avatar.content, local.content, props.style.content],
  };
}

class Avatar extends PureComponent {
  render() {
    const { image, icon, iconSize, iconColor, text, theme } = this.props;
    const { avatar, spacing } = theme;

    let content = null;

    const styles = getStyles(this.props);

    if (icon) {
      const color = iconColor || StyleSheet.flatten(avatar.content).color;
      const size = iconSize || spacing.iconSize;
      content = <Icon name={icon} color={color} size={size} />;
    } else if (text) {
      content = <Text style={styles.content}>{text}</Text>;
    } else if (image) {
      content = image;
    }

    return (
      <View style={{ flexGrow: 1 }}>
        <View style={styles.container}>{content}</View>
      </View>
    );
  }
}

Avatar.propTypes = propTypes;
Avatar.defaultProps = defaultProps;

export default withTheme(Avatar);
<|endoftext|>


<commit_before>"use strict";

const finder = require("glob-concat");
const fs = require("fs");
const path = require("path");
const camelCase = require("camelcase");
const EOL = require("os").EOL;
const getPath = require("./get.path.js");

const files = finder.sync([getPath() + "/node_modules/rectangular/tmp/app/component/**/*.route.js"]);
const tmpJS = getPath() + "/node_modules/rectangular/tmp/component.route.js";
const routes = [];
const imports = [];
const deps = [];

files.forEach((file) => {
	const route = path.basename(file).replace(".js", "");
	imports.push("import " + camelCase(route) + " from \"app/" + file.split("app/")[1] + "\";");
	deps.push(camelCase(route) + ".name");
	routes.push(route);
});

const componentRoutes = imports.join("") + "export default angular.module(\"component.route\", [" + deps.join(",") + "]);" + EOL;
fs.writeFile(tmpJS, componentRoutes);
<commit_msg>Better module support<commit_after>"use strict";

const finder = require("glob-concat");
const fs = require("fs");
const path = require("path");
const camelCase = require("camelcase");
const EOL = require("os").EOL;
const getPath = require("./get.path.js");

const files = finder.sync([getPath() + "/node_modules/rectangular/tmp/app/component/**/*.route.js"]);
const tmpJS = getPath() + "/node_modules/rectangular/tmp/component.route.js";
const routes = [];
const imports = [];
const deps = [];

files.forEach((file) => {
	const route = path.basename(file).replace(".js", "");
	console.log(file);
	imports.push("import " + camelCase(route) + " from \"app/" + file.split("app/")[1] + "\";");
	deps.push(camelCase(route) + ".name");
	routes.push(route);
});

const componentRoutes = imports.join("") + "export default angular.module(\"component.route\", [" + deps.join(",") + "]);" + EOL;
fs.writeFile(tmpJS, componentRoutes);
<|endoftext|>


<commit_before>"use strict";

const fs = require("fs");
const less = require("postcss-less");
const path = require("path");
const pify = require("pify");
const scss = require("postcss-scss");
const standalone = require("../standalone");
const stringFormatter = require("../formatters/stringFormatter");
const stripAnsi = require("strip-ansi");
const sugarss = require("sugarss");

const fixturesPath = path.join(__dirname, "fixtures");

it("standalone with scss syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    code: "$foo: bar; // foo;\nb {}",
    syntax: "scss",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("2:3")).not.toBe(-1);
    expect(strippedOutput.indexOf("block-no-empty")).not.toBe(-1);
  });
});

it("standalone with sugarss syntax", () => {
  const config = {
    rules: {
      "length-zero-no-unit": true
    }
  };

  return standalone({
    config,
    code: ".one\n  color: black\n  top: 0px\n.two",
    syntax: "sugarss",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("3:9")).not.toBe(-1);
    expect(strippedOutput.indexOf("length-zero-no-unit")).not.toBe(-1);
  });
});

it("standalone with Less syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    code: "@foo: bar; // foo;\nb {}",
    syntax: "less",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("2:3")).not.toBe(-1);
    expect(strippedOutput.indexOf("block-no-empty")).not.toBe(-1);
  });
});

it("standalone with postcss-html syntax", () => {
  const config = {
    rules: {
      "no-empty-source": true,
      "comment-empty-line-before": "always",
      "rule-empty-line-before": [
        "always",
        {
          ignore: ["inside-block"]
        }
      ],
      "at-rule-empty-line-before": [
        "always",
        {
          except: ["inside-block"]
        }
      ]
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/postcss-html-syntax`,
    files: [
      `${fixturesPath}/at-rule-empty-line-before.html`,
      `${fixturesPath}/comment-empty-line-before.html`,
      `${fixturesPath}/no-empty-source.html`,
      `${fixturesPath}/rule-empty-line-before.html`
    ],
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;
    expect(results.length).toBe(4);

    const atRuleEmptyLineBeforeResult = results.find(r =>
      /[/\\]at-rule-empty-line-before\.html$/.test(r.source)
    );
    expect(atRuleEmptyLineBeforeResult.errored).toBeFalsy();
    expect(atRuleEmptyLineBeforeResult.warnings.length).toBe(0);

    const commentEmptyLineBeforeResult = results.find(r =>
      /[/\\]comment-empty-line-before\.html$/.test(r.source)
    );
    expect(commentEmptyLineBeforeResult.errored).toBeFalsy();
    expect(commentEmptyLineBeforeResult.warnings.length).toBe(0);

    const noEmptySourceResult = results.find(r =>
      /[/\\]no-empty-source\.html$/.test(r.source)
    );
    expect(noEmptySourceResult.errored).toBeFalsy();
    expect(noEmptySourceResult.warnings.length).toBe(0);

    const ruleEmptyLineBeforeResult = results.find(r =>
      /[/\\]rule-empty-line-before\.html$/.test(r.source)
    );
    expect(ruleEmptyLineBeforeResult.errored).toBe(true);
    expect(ruleEmptyLineBeforeResult.warnings.length).toBe(1);
    expect(ruleEmptyLineBeforeResult.warnings[0].line).toBe(8);
    expect(ruleEmptyLineBeforeResult.warnings[0].rule).toBe(
      "rule-empty-line-before"
    );
  });
});

describe("standalone with syntax set by extension", () => {
  let results;

  // The first tests here establish the meaningfulness of the last test

  describe("SCSS", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "scss"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as SCSS", () => {
      const scssResult = results.find(r => path.extname(r.source) === ".scss");
      expect(scssResult._postcssResult.opts.syntax).toBe(scss);
    });
  });

  describe("Less", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "less"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as Less", () => {
      const lessResult = results.find(r => path.extname(r.source) === ".less");
      expect(lessResult._postcssResult.opts.syntax).toBe(less);
    });
  });

  describe("SugarSS", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "sugarss"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as SugarSS", () => {
      const sssResult = results.find(r => path.extname(r.source) === ".sss");
      expect(sssResult._postcssResult.opts.syntax).toBe(sugarss);
    });
  });

  describe("By extension", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } }
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed each according to its extension", () => {
      const sssResult = results.find(r => path.extname(r.source) === ".sss");
      const lessResult = results.find(r => path.extname(r.source) === ".less");
      const scssResult = results.find(r => path.extname(r.source) === ".scss");
      expect(sssResult._postcssResult.opts.syntax).toBe(sugarss);
      expect(lessResult._postcssResult.opts.syntax).toBe(less);
      expect(scssResult._postcssResult.opts.syntax).toBe(scss);
    });
  });
});

it("standalone with postcss-safe-parser", () => {
  return standalone({
    files: `${fixturesPath}/syntax_error.*`,
    config: {
      rules: {}
    },
    fix: true
  }).then(data => {
    const results = data.results;
    expect(results.length).toBe(5);

    return Promise.all(
      results.map(result => {
        if (/\.(css|pcss|postcss)$/i.test(result.source)) {
          const root = result._postcssResult.root;
          expect(results[0].errored).toBeFalsy();
          expect(results[0].warnings.length).toBe(0);
          expect(root.toString()).not.toBe(root.source.input.css);
          return pify(fs.writeFile)(
            root.source.input.file,
            root.source.input.css
          );
        } else {
          expect(results[0].warnings.length).toBe(0);
          expect(result.warnings.length).toBe(1);
          const error = result.warnings[0];
          expect(error.line).toBe(1);
          expect(error.column).toBe(1);
          expect(error.rule).toBe("CssSyntaxError");
          expect(error.severity).toBe("error");
        }
      })
    );
  });
});

it("standalone with path to custom parser", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/custom-parser`,
    code: ".foo { width: 200px }\n.bar {",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(6);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});

it("standalone with path to custom syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/custom-syntax`,
    code: "$foo: bar; // foo;\nb {}",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(3);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});

it("standalone should use customSyntax when both customSyntax and syntax are set", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    syntax: "less",
    customSyntax: `${fixturesPath}/custom-syntax`,
    code: "$foo: bar; // foo;\nb {}",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(3);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});
<commit_msg>fix testcase of postcss-safe-parser (#2997)<commit_after>"use strict";

const fs = require("fs");
const less = require("postcss-less");
const path = require("path");
const pify = require("pify");
const scss = require("postcss-scss");
const standalone = require("../standalone");
const stringFormatter = require("../formatters/stringFormatter");
const stripAnsi = require("strip-ansi");
const sugarss = require("sugarss");

const fixturesPath = path.join(__dirname, "fixtures");

it("standalone with scss syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    code: "$foo: bar; // foo;\nb {}",
    syntax: "scss",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("2:3")).not.toBe(-1);
    expect(strippedOutput.indexOf("block-no-empty")).not.toBe(-1);
  });
});

it("standalone with sugarss syntax", () => {
  const config = {
    rules: {
      "length-zero-no-unit": true
    }
  };

  return standalone({
    config,
    code: ".one\n  color: black\n  top: 0px\n.two",
    syntax: "sugarss",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("3:9")).not.toBe(-1);
    expect(strippedOutput.indexOf("length-zero-no-unit")).not.toBe(-1);
  });
});

it("standalone with Less syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    code: "@foo: bar; // foo;\nb {}",
    syntax: "less",
    formatter: stringFormatter
  }).then(linted => {
    const strippedOutput = stripAnsi(linted.output);
    expect(typeof linted.output).toBe("string");
    expect(strippedOutput.indexOf("2:3")).not.toBe(-1);
    expect(strippedOutput.indexOf("block-no-empty")).not.toBe(-1);
  });
});

it("standalone with postcss-html syntax", () => {
  const config = {
    rules: {
      "no-empty-source": true,
      "comment-empty-line-before": "always",
      "rule-empty-line-before": [
        "always",
        {
          ignore: ["inside-block"]
        }
      ],
      "at-rule-empty-line-before": [
        "always",
        {
          except: ["inside-block"]
        }
      ]
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/postcss-html-syntax`,
    files: [
      `${fixturesPath}/at-rule-empty-line-before.html`,
      `${fixturesPath}/comment-empty-line-before.html`,
      `${fixturesPath}/no-empty-source.html`,
      `${fixturesPath}/rule-empty-line-before.html`
    ],
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;
    expect(results.length).toBe(4);

    const atRuleEmptyLineBeforeResult = results.find(r =>
      /[/\\]at-rule-empty-line-before\.html$/.test(r.source)
    );
    expect(atRuleEmptyLineBeforeResult.errored).toBeFalsy();
    expect(atRuleEmptyLineBeforeResult.warnings.length).toBe(0);

    const commentEmptyLineBeforeResult = results.find(r =>
      /[/\\]comment-empty-line-before\.html$/.test(r.source)
    );
    expect(commentEmptyLineBeforeResult.errored).toBeFalsy();
    expect(commentEmptyLineBeforeResult.warnings.length).toBe(0);

    const noEmptySourceResult = results.find(r =>
      /[/\\]no-empty-source\.html$/.test(r.source)
    );
    expect(noEmptySourceResult.errored).toBeFalsy();
    expect(noEmptySourceResult.warnings.length).toBe(0);

    const ruleEmptyLineBeforeResult = results.find(r =>
      /[/\\]rule-empty-line-before\.html$/.test(r.source)
    );
    expect(ruleEmptyLineBeforeResult.errored).toBe(true);
    expect(ruleEmptyLineBeforeResult.warnings.length).toBe(1);
    expect(ruleEmptyLineBeforeResult.warnings[0].line).toBe(8);
    expect(ruleEmptyLineBeforeResult.warnings[0].rule).toBe(
      "rule-empty-line-before"
    );
  });
});

describe("standalone with syntax set by extension", () => {
  let results;

  // The first tests here establish the meaningfulness of the last test

  describe("SCSS", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "scss"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as SCSS", () => {
      const scssResult = results.find(r => path.extname(r.source) === ".scss");
      expect(scssResult._postcssResult.opts.syntax).toBe(scss);
    });
  });

  describe("Less", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "less"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as Less", () => {
      const lessResult = results.find(r => path.extname(r.source) === ".less");
      expect(lessResult._postcssResult.opts.syntax).toBe(less);
    });
  });

  describe("SugarSS", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } },
        syntax: "sugarss"
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed as SugarSS", () => {
      const sssResult = results.find(r => path.extname(r.source) === ".sss");
      expect(sssResult._postcssResult.opts.syntax).toBe(sugarss);
    });
  });

  describe("By extension", () => {
    beforeEach(() => {
      return standalone({
        files: `${fixturesPath}/extension-sensitive.*`,
        config: { rules: { "block-no-empty": true } }
      }).then(data => (results = data.results));
    });

    it("correct number of files", () => {
      expect(results.length).toBe(3);
    });

    it("parsed each according to its extension", () => {
      const sssResult = results.find(r => path.extname(r.source) === ".sss");
      const lessResult = results.find(r => path.extname(r.source) === ".less");
      const scssResult = results.find(r => path.extname(r.source) === ".scss");
      expect(sssResult._postcssResult.opts.syntax).toBe(sugarss);
      expect(lessResult._postcssResult.opts.syntax).toBe(less);
      expect(scssResult._postcssResult.opts.syntax).toBe(scss);
    });
  });
});

it("standalone with postcss-safe-parser", () => {
  return standalone({
    files: `${fixturesPath}/syntax_error.*`,
    config: {
      rules: {}
    },
    fix: true
  }).then(data => {
    const results = data.results;
    expect(results.length).toBe(5);

    return Promise.all(
      results.map(result => {
        if (/\.(css|pcss|postcss)$/i.test(result.source)) {
          const root = result._postcssResult.root;
          expect(results[0].errored).toBeFalsy();
          expect(results[0].warnings.length).toBe(0);
          expect(root.toString()).not.toBe(root.source.input.css);
          return pify(fs.writeFile)(
            root.source.input.file,
            root.source.input.css
          );
        } else {
          expect(result.warnings.length).toBe(1);
          const error = result.warnings[0];
          expect(error.line).toBe(1);
          expect(error.column).toBe(1);
          expect(error.rule).toBe("CssSyntaxError");
          expect(error.severity).toBe("error");
        }
      })
    );
  });
});

it("standalone with path to custom parser", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/custom-parser`,
    code: ".foo { width: 200px }\n.bar {",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(6);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});

it("standalone with path to custom syntax", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    customSyntax: `${fixturesPath}/custom-syntax`,
    code: "$foo: bar; // foo;\nb {}",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(3);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});

it("standalone should use customSyntax when both customSyntax and syntax are set", () => {
  const config = {
    rules: {
      "block-no-empty": true
    }
  };

  return standalone({
    config,
    syntax: "less",
    customSyntax: `${fixturesPath}/custom-syntax`,
    code: "$foo: bar; // foo;\nb {}",
    formatter: stringFormatter
  }).then(linted => {
    const results = linted.results;

    expect(results.length).toBe(1);
    expect(results[0].warnings.length).toBe(1);
    expect(results[0].warnings[0].line).toBe(2);
    expect(results[0].warnings[0].column).toBe(3);
    expect(results[0].warnings[0].rule).toBe("block-no-empty");
  });
});
<|endoftext|>


<commit_before>var m = require('mithril');
var h = require('highcharts');
var Graph = require('../models/Graph.js');

exports.controller = function () {
  var ctrl = this;
  ctrl.fetchAll = Graph.fetchAll().then(function(appData) {
    ctrl.graphOptions = graphOptions(appData);
  })
}

exports.plotter = function(ctrl) { // config class
  return function(elem , isin) {
    if(!isin) {
      ctrl.graphOptions.chart.renderTo = elem;
      var chart = new Highcharts.Chart(ctrl.graphOptions);
    }
  };
};

exports.view = function(ctrl) { // view
    return  m("html", [ m("body", [
        m("#plot[style=height:400px]", {config: exports.plotter(ctrl)}), console.log(ctrl),
        m("p",console.log(JSON.stringify(ctrl.fetchAll))),
        ]),
    ])
};

function graphOptions (graphData) {
  return {
        chart: {
            type: 'funnel',
            marginRight: 100
        },
        credits: {
            enabled: false
        },
        title: {
            text: 'Job Search Tracker',
            x: -50
        },
        plotOptions: {
            series: {
                dataLabels: {
                    enabled: true,
                    format: '{point.name} ({point.y:,.0f})',
                    color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black',
                    softConnector: true
                },
                neckWidth: '0%',
                neckHeight: '0%'

                //-- Other available options
                // height: pixels or percent
                // width: pixels or percent
            }
        },
        legend: {
            enabled: false
        },
        series: [{
            name: 'Students',
            data: [
                ['Applications Submitted',  graphData.submitted],
                ['Phones Screens',       graphData.phoneScreens],
                ['Onsite Interviews', graphData.interviews],
                ['Offers',    graphData.offers],
                ['Accepted Offers',    graphData.acceptedOffers]
            ]
        }],
        // tooltip: {
        //         formatter: function() {
        //                  return 'Branch: '+ this.series.name +
        //                     '
Date: '+ Highcharts.dateFormat('%e %b',this.x)+
        //                         '
Pass rate: '+ this.y +'%';
        //                      //     '
Pass count: '+  this.point.options.passCount+
        //                      // '
Total count: '+  this.point.options.totalCount;
        //         }
        //     },
    }
}
<commit_msg>removed unneccessary comments and console logs from outcomesGraph<commit_after>var m = require('mithril');
var h = require('highcharts');
var Graph = require('../models/Graph.js');

exports.controller = function () {
  var ctrl = this;
  ctrl.fetchAll = Graph.fetchAll().then(function(appData) {
    ctrl.graphOptions = graphOptions(appData);
  })
}

exports.plotter = function(ctrl) { // config class
  return function(elem , isin) {
    if(!isin) {
      ctrl.graphOptions.chart.renderTo = elem;
      var chart = new Highcharts.Chart(ctrl.graphOptions);
    }
  };
};

exports.view = function(ctrl) { // view
    return  m("html", [ m("body", [
        m("#plot[style=height:400px]", {config: exports.plotter(ctrl)}),
        m("p",console.log(JSON.stringify(ctrl.fetchAll))),
        ]),
    ])
};

function graphOptions (graphData) {
  return {
        chart: {
            type: 'funnel',
            marginRight: 100
        },
        credits: {
            enabled: false
        },
        title: {
            text: 'Job Search Tracker',
            x: -50
        },
        plotOptions: {
            series: {
                dataLabels: {
                    enabled: true,
                    format: '{point.name} ({point.y:,.0f})',
                    color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black',
                    softConnector: true
                },
                neckWidth: '0%',
                neckHeight: '0%'
            }
        },
        legend: {
            enabled: false
        },
        series: [{
            name: 'Students',
            data: [
                ['Applications Submitted',  graphData.submitted],
                ['Phones Screens',       graphData.phoneScreens],
                ['Onsite Interviews', graphData.interviews],
                ['Offers',    graphData.offers],
                ['Accepted Offers',    graphData.acceptedOffers]
            ]
        }],
    }
}
<|endoftext|>


<commit_before>/* global heimdall */
import { assert, warn } from 'ember-data/-private/debug';
import OrderedSet from '../../ordered-set';
import _normalizeLink from '../../normalize-link';

const {
  addCanonicalRecord,
  addCanonicalRecords,
  addRecord,
  addInternalModels,
  clear,
  findLink,
  flushCanonical,
  flushCanonicalLater,
  newRelationship,
  push,
  removeCanonicalRecord,
  removeCanonicalRecordFromInverse,
  removeCanonicalRecordFromOwn,
  removeCanonicalRecords,
  removeRecord,
  removeRecordFromInverse,
  removeRecordFromOwn,
  removeInternalModels,
  setHasData,
  setHasLoaded,
  updateLink,
  updateMeta,
  updateRecordsFromAdapter
} = heimdall.registerMonitor('system.relationships.state.relationship',
  'addCanonicalRecord',
  'addCanonicalRecords',
  'addRecord',
  'addInternalModels',
  'clear',
  'findLink',
  'flushCanonical',
  'flushCanonicalLater',
  'newRelationship',
  'push',
  'removeCanonicalRecord',
  'removeCanonicalRecordFromInverse',
  'removeCanonicalRecordFromOwn',
  'removeCanonicalRecords',
  'removeRecord',
  'removeRecordFromInverse',
  'removeRecordFromOwn',
  'removeInternalModels',
  'setHasData',
  'setHasLoaded',
  'updateLink',
  'updateMeta',
  'updateRecordsFromAdapter'
);

export default class Relationship {
  constructor(store, internalModel, inverseKey, relationshipMeta) {
    heimdall.increment(newRelationship);
    let async = relationshipMeta.options.async;
    let polymorphic = relationshipMeta.options.polymorphic;
    this.members = new OrderedSet();
    this.canonicalMembers = new OrderedSet();
    this.store = store;
    this.key = relationshipMeta.key;
    this.inverseKey = inverseKey;
    this.internalModel = internalModel;
    this.isAsync = typeof async === 'undefined' ? true : async;
    this.isPolymorphic = typeof polymorphic === 'undefined' ? true : polymorphic;
    this.relationshipMeta = relationshipMeta;
    //This probably breaks for polymorphic relationship in complex scenarios, due to
    //multiple possible modelNames
    this.inverseKeyForImplicit = this.internalModel.modelName + this.key;
    this.linkPromise = null;
    this.meta = null;
    this.hasData = false;
    this.hasLoaded = false;
  }

  // TODO @runspired deprecate this as it was never truly a record instance
  get record() {
    return this.internalModel;
  }

  get parentType() {
    return this.internalModel.modelName;
  }

  destroy() {
    if (!this.inverseKey) { return; }

    let allMembers =
      // we actually want a union of members and canonicalMembers
      // they should be disjoint but currently are not due to a bug
      this.members.toArray().concat(this.canonicalMembers.toArray());

    allMembers.forEach(inverseInternalModel => {
      let relationship = inverseInternalModel._relationships.get(this.inverseKey);
      // TODO: there is always a relationship in this case; this guard exists
      // because there are tests that fail in teardown after putting things in
      // invalid state
      if (relationship) {
        relationship.inverseDidDematerialize();
      }
    });
  }

  inverseDidDematerialize() {}

  updateMeta(meta) {
    heimdall.increment(updateMeta);
    this.meta = meta;
  }

  clear() {
    heimdall.increment(clear);

    let members = this.members.list;
    while (members.length > 0) {
      let member = members[0];
      this.removeRecord(member);
    }

    let canonicalMembers = this.canonicalMembers.list;
    while (canonicalMembers.length > 0) {
      let member = canonicalMembers[0];
      this.removeCanonicalRecord(member);
    }
  }

  removeInternalModels(internalModels) {
    heimdall.increment(removeInternalModels);
    internalModels.forEach((intenralModel) => this.removeRecord(intenralModel));
  }

  addInternalModels(internalModels, idx) {
    heimdall.increment(addInternalModels);
    internalModels.forEach(internalModel => {
      this.addRecord(internalModel, idx);
      if (idx !== undefined) {
        idx++;
      }
    });
  }

  addCanonicalRecords(records, idx) {
    heimdall.increment(addCanonicalRecords);
    for (let i=0; i<records.length; i++) {
      if (idx !== undefined) {
        this.addCanonicalRecord(records[i], i+idx);
      } else {
        this.addCanonicalRecord(records[i]);
      }
    }
  }

  addCanonicalRecord(record, idx) {
    heimdall.increment(addCanonicalRecord);
    if (!this.canonicalMembers.has(record)) {
      this.canonicalMembers.add(record);
      this.setupInverseRelationship(record);
    }
    this.flushCanonicalLater();
    this.setHasData(true);
  }

  setupInverseRelationship(internalModel) {
    if (this.inverseKey) {
      let relationships = internalModel._relationships;
      let relationshipExisted = relationships.has(this.inverseKey);
      let relationship = relationships.get(this.inverseKey);
      if (relationshipExisted || this.isPolymorphic) {
        // if we have only just initialized the inverse relationship, then it
        // already has this.internalModel in its canonicalMembers, so skip the
        // unnecessary work.  The exception to this is polymorphic
        // relationships whose members are determined by their inverse, as those
        // relationships cannot efficiently find their inverse payloads.
        relationship.addCanonicalRecord(this.internalModel);
      }
    } else {
      let relationships = internalModel._implicitRelationships;
      let relationship = relationships[this.inverseKeyForImplicit];
      if (!relationship) {
        relationship = relationships[this.inverseKeyForImplicit] =
          new Relationship(this.store, internalModel, this.key,  { options: {} });
      }
      relationship.addCanonicalRecord(this.internalModel);
    }
  }

  removeCanonicalRecords(records, idx) {
    heimdall.increment(removeCanonicalRecords);
    for (let i=0; i<records.length; i++) {
      if (idx !== undefined) {
        this.removeCanonicalRecord(records[i], i+idx);
      } else {
        this.removeCanonicalRecord(records[i]);
      }
    }
  }

  removeCanonicalRecord(record, idx) {
    heimdall.increment(removeCanonicalRecord);
    if (this.canonicalMembers.has(record)) {
      this.removeCanonicalRecordFromOwn(record);
      if (this.inverseKey) {
        this.removeCanonicalRecordFromInverse(record);
      } else {
        if (record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit].removeCanonicalRecord(this.record);
        }
      }
    }
    this.flushCanonicalLater();
  }

  addRecord(record, idx) {
    heimdall.increment(addRecord);
    if (!this.members.has(record)) {
      this.members.addWithIndex(record, idx);
      this.notifyRecordRelationshipAdded(record, idx);
      if (this.inverseKey) {
        record._relationships.get(this.inverseKey).addRecord(this.record);
      } else {
        if (!record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit] = new Relationship(this.store, record, this.key,  { options: {} });
        }
        record._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record);
      }
      this.record.updateRecordArrays();
    }
    this.setHasData(true);
  }

  removeRecord(record) {
    heimdall.increment(removeRecord);
    if (this.members.has(record)) {
      this.removeRecordFromOwn(record);
      if (this.inverseKey) {
        this.removeRecordFromInverse(record);
      } else {
        if (record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit].removeRecord(this.record);
        }
      }
    }
  }

  removeRecordFromInverse(record) {
    heimdall.increment(removeRecordFromInverse);
    let inverseRelationship = record._relationships.get(this.inverseKey);
    //Need to check for existence, as the record might unloading at the moment
    if (inverseRelationship) {
      inverseRelationship.removeRecordFromOwn(this.record);
    }
  }

  removeRecordFromOwn(record) {
    heimdall.increment(removeRecordFromOwn);
    this.members.delete(record);
    this.notifyRecordRelationshipRemoved(record);
    this.record.updateRecordArrays();
  }

  removeCanonicalRecordFromInverse(record) {
    heimdall.increment(removeCanonicalRecordFromInverse);
    let inverseRelationship = record._relationships.get(this.inverseKey);
    //Need to check for existence, as the record might unloading at the moment
    if (inverseRelationship) {
      inverseRelationship.removeCanonicalRecordFromOwn(this.record);
    }
  }

  removeCanonicalRecordFromOwn(record) {
    heimdall.increment(removeCanonicalRecordFromOwn);
    this.canonicalMembers.delete(record);
    this.flushCanonicalLater();
  }

  flushCanonical() {
    heimdall.increment(flushCanonical);
    let list = this.members.list;
    this.willSync = false;
    //a hack for not removing new records
    //TODO remove once we have proper diffing
    let newRecords = [];
    for (let i = 0; i < list.length; i++) {
      if (list[i].isNew()) {
        newRecords.push(list[i]);
      }
    }

    //TODO(Igor) make this less abysmally slow
    this.members = this.canonicalMembers.copy();
    for (let i = 0; i < newRecords.length; i++) {
      this.members.add(newRecords[i]);
    }
  }

  flushCanonicalLater() {
    heimdall.increment(flushCanonicalLater);
    if (this.willSync) {
      return;
    }
    this.willSync = true;
    this.store._updateRelationshipState(this);
  }

  updateLink(link) {
    heimdall.increment(updateLink);
    warn(`You pushed a record of type '${this.record.modelName}' with a relationship '${this.key}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, this.isAsync || this.hasData , {
      id: 'ds.store.push-link-for-sync-relationship'
    });
    assert(`You have pushed a record of type '${this.record.modelName}' with '${this.key}' as a link, but the value of that link is not a string.`, typeof link === 'string' || link === null);

    this.link = link;
    this.linkPromise = null;
    this.record.notifyPropertyChange(this.key);
  }

  findLink() {
    heimdall.increment(findLink);
    if (this.linkPromise) {
      return this.linkPromise;
    } else {
      let promise = this.fetchLink();
      this.linkPromise = promise;
      return promise.then((result) => result);
    }
  }

  updateRecordsFromAdapter(records) {
    heimdall.increment(updateRecordsFromAdapter);
    //TODO(Igor) move this to a proper place
    //TODO Once we have adapter support, we need to handle updated and canonical changes
    this.computeChanges(records);
  }

  notifyRecordRelationshipAdded() { }
  notifyRecordRelationshipRemoved() { }

  /*
   `hasData` for a relationship is a flag to indicate if we consider the
   content of this relationship "known". Snapshots uses this to tell the
   difference between unknown (`undefined`) or empty (`null`). The reason for
   this is that we wouldn't want to serialize unknown relationships as `null`
   as that might overwrite remote state.

   All relationships for a newly created (`store.createRecord()`) are
   considered known (`hasData === true`).
   */
  setHasData(value) {
    heimdall.increment(setHasData);
    this.hasData = value;
  }

  /*
   `hasLoaded` is a flag to indicate if we have gotten data from the adapter or
   not when the relationship has a link.

   This is used to be able to tell when to fetch the link and when to return
   the local data in scenarios where the local state is considered known
   (`hasData === true`).

   Updating the link will automatically set `hasLoaded` to `false`.
   */
  setHasLoaded(value) {
    heimdall.increment(setHasLoaded);
    this.hasLoaded = value;
  }

  /*
   `push` for a relationship allows the store to push a JSON API Relationship
   Object onto the relationship. The relationship will then extract and set the
   meta, data and links of that relationship.

   `push` use `updateMeta`, `updateData` and `updateLink` to update the state
   of the relationship.
   */
  push(payload, initial) {
    heimdall.increment(push);

    let hasData = false;
    let hasLink = false;

    if (payload.meta) {
      this.updateMeta(payload.meta);
    }

    if (payload.data !== undefined) {
      hasData = true;
      this.updateData(payload.data, initial);
    }

    if (payload.links && payload.links.related) {
      let relatedLink = _normalizeLink(payload.links.related);
      if (relatedLink && relatedLink.href && relatedLink.href !== this.link) {
        hasLink = true;
        this.updateLink(relatedLink.href, initial);
      }
    }

    /*
     Data being pushed into the relationship might contain only data or links,
     or a combination of both.

     If we got data we want to set both hasData and hasLoaded to true since
     this would indicate that we should prefer the local state instead of
     trying to fetch the link or call findRecord().

     If we have no data but a link is present we want to set hasLoaded to false
     without modifying the hasData flag. This will ensure we fetch the updated
     link next time the relationship is accessed.
     */
    if (hasData) {
      this.setHasData(true);
      this.setHasLoaded(true);
    } else if (hasLink) {
      this.setHasLoaded(false);
    }
  }

  updateData() {}
}
<commit_msg>Fix intenralModel typo<commit_after>/* global heimdall */
import { assert, warn } from 'ember-data/-private/debug';
import OrderedSet from '../../ordered-set';
import _normalizeLink from '../../normalize-link';

const {
  addCanonicalRecord,
  addCanonicalRecords,
  addRecord,
  addInternalModels,
  clear,
  findLink,
  flushCanonical,
  flushCanonicalLater,
  newRelationship,
  push,
  removeCanonicalRecord,
  removeCanonicalRecordFromInverse,
  removeCanonicalRecordFromOwn,
  removeCanonicalRecords,
  removeRecord,
  removeRecordFromInverse,
  removeRecordFromOwn,
  removeInternalModels,
  setHasData,
  setHasLoaded,
  updateLink,
  updateMeta,
  updateRecordsFromAdapter
} = heimdall.registerMonitor('system.relationships.state.relationship',
  'addCanonicalRecord',
  'addCanonicalRecords',
  'addRecord',
  'addInternalModels',
  'clear',
  'findLink',
  'flushCanonical',
  'flushCanonicalLater',
  'newRelationship',
  'push',
  'removeCanonicalRecord',
  'removeCanonicalRecordFromInverse',
  'removeCanonicalRecordFromOwn',
  'removeCanonicalRecords',
  'removeRecord',
  'removeRecordFromInverse',
  'removeRecordFromOwn',
  'removeInternalModels',
  'setHasData',
  'setHasLoaded',
  'updateLink',
  'updateMeta',
  'updateRecordsFromAdapter'
);

export default class Relationship {
  constructor(store, internalModel, inverseKey, relationshipMeta) {
    heimdall.increment(newRelationship);
    let async = relationshipMeta.options.async;
    let polymorphic = relationshipMeta.options.polymorphic;
    this.members = new OrderedSet();
    this.canonicalMembers = new OrderedSet();
    this.store = store;
    this.key = relationshipMeta.key;
    this.inverseKey = inverseKey;
    this.internalModel = internalModel;
    this.isAsync = typeof async === 'undefined' ? true : async;
    this.isPolymorphic = typeof polymorphic === 'undefined' ? true : polymorphic;
    this.relationshipMeta = relationshipMeta;
    //This probably breaks for polymorphic relationship in complex scenarios, due to
    //multiple possible modelNames
    this.inverseKeyForImplicit = this.internalModel.modelName + this.key;
    this.linkPromise = null;
    this.meta = null;
    this.hasData = false;
    this.hasLoaded = false;
  }

  // TODO @runspired deprecate this as it was never truly a record instance
  get record() {
    return this.internalModel;
  }

  get parentType() {
    return this.internalModel.modelName;
  }

  destroy() {
    if (!this.inverseKey) { return; }

    let allMembers =
      // we actually want a union of members and canonicalMembers
      // they should be disjoint but currently are not due to a bug
      this.members.toArray().concat(this.canonicalMembers.toArray());

    allMembers.forEach(inverseInternalModel => {
      let relationship = inverseInternalModel._relationships.get(this.inverseKey);
      // TODO: there is always a relationship in this case; this guard exists
      // because there are tests that fail in teardown after putting things in
      // invalid state
      if (relationship) {
        relationship.inverseDidDematerialize();
      }
    });
  }

  inverseDidDematerialize() {}

  updateMeta(meta) {
    heimdall.increment(updateMeta);
    this.meta = meta;
  }

  clear() {
    heimdall.increment(clear);

    let members = this.members.list;
    while (members.length > 0) {
      let member = members[0];
      this.removeRecord(member);
    }

    let canonicalMembers = this.canonicalMembers.list;
    while (canonicalMembers.length > 0) {
      let member = canonicalMembers[0];
      this.removeCanonicalRecord(member);
    }
  }

  removeInternalModels(internalModels) {
    heimdall.increment(removeInternalModels);
    internalModels.forEach((internalModel) => this.removeRecord(internalModel));
  }

  addInternalModels(internalModels, idx) {
    heimdall.increment(addInternalModels);
    internalModels.forEach(internalModel => {
      this.addRecord(internalModel, idx);
      if (idx !== undefined) {
        idx++;
      }
    });
  }

  addCanonicalRecords(records, idx) {
    heimdall.increment(addCanonicalRecords);
    for (let i=0; i<records.length; i++) {
      if (idx !== undefined) {
        this.addCanonicalRecord(records[i], i+idx);
      } else {
        this.addCanonicalRecord(records[i]);
      }
    }
  }

  addCanonicalRecord(record, idx) {
    heimdall.increment(addCanonicalRecord);
    if (!this.canonicalMembers.has(record)) {
      this.canonicalMembers.add(record);
      this.setupInverseRelationship(record);
    }
    this.flushCanonicalLater();
    this.setHasData(true);
  }

  setupInverseRelationship(internalModel) {
    if (this.inverseKey) {
      let relationships = internalModel._relationships;
      let relationshipExisted = relationships.has(this.inverseKey);
      let relationship = relationships.get(this.inverseKey);
      if (relationshipExisted || this.isPolymorphic) {
        // if we have only just initialized the inverse relationship, then it
        // already has this.internalModel in its canonicalMembers, so skip the
        // unnecessary work.  The exception to this is polymorphic
        // relationships whose members are determined by their inverse, as those
        // relationships cannot efficiently find their inverse payloads.
        relationship.addCanonicalRecord(this.internalModel);
      }
    } else {
      let relationships = internalModel._implicitRelationships;
      let relationship = relationships[this.inverseKeyForImplicit];
      if (!relationship) {
        relationship = relationships[this.inverseKeyForImplicit] =
          new Relationship(this.store, internalModel, this.key,  { options: {} });
      }
      relationship.addCanonicalRecord(this.internalModel);
    }
  }

  removeCanonicalRecords(records, idx) {
    heimdall.increment(removeCanonicalRecords);
    for (let i=0; i<records.length; i++) {
      if (idx !== undefined) {
        this.removeCanonicalRecord(records[i], i+idx);
      } else {
        this.removeCanonicalRecord(records[i]);
      }
    }
  }

  removeCanonicalRecord(record, idx) {
    heimdall.increment(removeCanonicalRecord);
    if (this.canonicalMembers.has(record)) {
      this.removeCanonicalRecordFromOwn(record);
      if (this.inverseKey) {
        this.removeCanonicalRecordFromInverse(record);
      } else {
        if (record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit].removeCanonicalRecord(this.record);
        }
      }
    }
    this.flushCanonicalLater();
  }

  addRecord(record, idx) {
    heimdall.increment(addRecord);
    if (!this.members.has(record)) {
      this.members.addWithIndex(record, idx);
      this.notifyRecordRelationshipAdded(record, idx);
      if (this.inverseKey) {
        record._relationships.get(this.inverseKey).addRecord(this.record);
      } else {
        if (!record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit] = new Relationship(this.store, record, this.key,  { options: {} });
        }
        record._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record);
      }
      this.record.updateRecordArrays();
    }
    this.setHasData(true);
  }

  removeRecord(record) {
    heimdall.increment(removeRecord);
    if (this.members.has(record)) {
      this.removeRecordFromOwn(record);
      if (this.inverseKey) {
        this.removeRecordFromInverse(record);
      } else {
        if (record._implicitRelationships[this.inverseKeyForImplicit]) {
          record._implicitRelationships[this.inverseKeyForImplicit].removeRecord(this.record);
        }
      }
    }
  }

  removeRecordFromInverse(record) {
    heimdall.increment(removeRecordFromInverse);
    let inverseRelationship = record._relationships.get(this.inverseKey);
    //Need to check for existence, as the record might unloading at the moment
    if (inverseRelationship) {
      inverseRelationship.removeRecordFromOwn(this.record);
    }
  }

  removeRecordFromOwn(record) {
    heimdall.increment(removeRecordFromOwn);
    this.members.delete(record);
    this.notifyRecordRelationshipRemoved(record);
    this.record.updateRecordArrays();
  }

  removeCanonicalRecordFromInverse(record) {
    heimdall.increment(removeCanonicalRecordFromInverse);
    let inverseRelationship = record._relationships.get(this.inverseKey);
    //Need to check for existence, as the record might unloading at the moment
    if (inverseRelationship) {
      inverseRelationship.removeCanonicalRecordFromOwn(this.record);
    }
  }

  removeCanonicalRecordFromOwn(record) {
    heimdall.increment(removeCanonicalRecordFromOwn);
    this.canonicalMembers.delete(record);
    this.flushCanonicalLater();
  }

  flushCanonical() {
    heimdall.increment(flushCanonical);
    let list = this.members.list;
    this.willSync = false;
    //a hack for not removing new records
    //TODO remove once we have proper diffing
    let newRecords = [];
    for (let i = 0; i < list.length; i++) {
      if (list[i].isNew()) {
        newRecords.push(list[i]);
      }
    }

    //TODO(Igor) make this less abysmally slow
    this.members = this.canonicalMembers.copy();
    for (let i = 0; i < newRecords.length; i++) {
      this.members.add(newRecords[i]);
    }
  }

  flushCanonicalLater() {
    heimdall.increment(flushCanonicalLater);
    if (this.willSync) {
      return;
    }
    this.willSync = true;
    this.store._updateRelationshipState(this);
  }

  updateLink(link) {
    heimdall.increment(updateLink);
    warn(`You pushed a record of type '${this.record.modelName}' with a relationship '${this.key}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, this.isAsync || this.hasData , {
      id: 'ds.store.push-link-for-sync-relationship'
    });
    assert(`You have pushed a record of type '${this.record.modelName}' with '${this.key}' as a link, but the value of that link is not a string.`, typeof link === 'string' || link === null);

    this.link = link;
    this.linkPromise = null;
    this.record.notifyPropertyChange(this.key);
  }

  findLink() {
    heimdall.increment(findLink);
    if (this.linkPromise) {
      return this.linkPromise;
    } else {
      let promise = this.fetchLink();
      this.linkPromise = promise;
      return promise.then((result) => result);
    }
  }

  updateRecordsFromAdapter(records) {
    heimdall.increment(updateRecordsFromAdapter);
    //TODO(Igor) move this to a proper place
    //TODO Once we have adapter support, we need to handle updated and canonical changes
    this.computeChanges(records);
  }

  notifyRecordRelationshipAdded() { }
  notifyRecordRelationshipRemoved() { }

  /*
   `hasData` for a relationship is a flag to indicate if we consider the
   content of this relationship "known". Snapshots uses this to tell the
   difference between unknown (`undefined`) or empty (`null`). The reason for
   this is that we wouldn't want to serialize unknown relationships as `null`
   as that might overwrite remote state.

   All relationships for a newly created (`store.createRecord()`) are
   considered known (`hasData === true`).
   */
  setHasData(value) {
    heimdall.increment(setHasData);
    this.hasData = value;
  }

  /*
   `hasLoaded` is a flag to indicate if we have gotten data from the adapter or
   not when the relationship has a link.

   This is used to be able to tell when to fetch the link and when to return
   the local data in scenarios where the local state is considered known
   (`hasData === true`).

   Updating the link will automatically set `hasLoaded` to `false`.
   */
  setHasLoaded(value) {
    heimdall.increment(setHasLoaded);
    this.hasLoaded = value;
  }

  /*
   `push` for a relationship allows the store to push a JSON API Relationship
   Object onto the relationship. The relationship will then extract and set the
   meta, data and links of that relationship.

   `push` use `updateMeta`, `updateData` and `updateLink` to update the state
   of the relationship.
   */
  push(payload, initial) {
    heimdall.increment(push);

    let hasData = false;
    let hasLink = false;

    if (payload.meta) {
      this.updateMeta(payload.meta);
    }

    if (payload.data !== undefined) {
      hasData = true;
      this.updateData(payload.data, initial);
    }

    if (payload.links && payload.links.related) {
      let relatedLink = _normalizeLink(payload.links.related);
      if (relatedLink && relatedLink.href && relatedLink.href !== this.link) {
        hasLink = true;
        this.updateLink(relatedLink.href, initial);
      }
    }

    /*
     Data being pushed into the relationship might contain only data or links,
     or a combination of both.

     If we got data we want to set both hasData and hasLoaded to true since
     this would indicate that we should prefer the local state instead of
     trying to fetch the link or call findRecord().

     If we have no data but a link is present we want to set hasLoaded to false
     without modifying the hasData flag. This will ensure we fetch the updated
     link next time the relationship is accessed.
     */
    if (hasData) {
      this.setHasData(true);
      this.setHasLoaded(true);
    } else if (hasLink) {
      this.setHasLoaded(false);
    }
  }

  updateData() {}
}
<|endoftext|>


<commit_before>/* global global */

// -------------------------------------
// Load Dependencies
// -------------------------------------

var LessCssClean = require('less-plugin-clean-css');

global.fs = require('fs-extra');
global.path = require('path');
global.browserSync = require('browser-sync');
global.JSCS = require('jscs');
global.jshint = require('jshint').JSHINT;
global.Wee = require('../script/wee').Wee;

// Load build utilities
require('./utils');

// -------------------------------------
// Configure Grunt
// -------------------------------------

module.exports = function(grunt) {
	global.config = {};
	global.server = {};
	global.moduleLegacy = [];
	global.legacy = {};
	global.reloadPaths = [];
	global.legacyBuild = [];
	global.legacyConvert = [];
	global.version = '3.0.0';

	grunt.initConfig({
		less: {
			options: {
				modifyVars: '<%= config.style.vars %>',
				strictMath: true,
				paths: [
					'<%= config.paths.root %>'
				],
				plugins: [
					new LessCssClean()
				]
			},
			core: {
				files: [
					{
						dest: '<%= config.paths.temp %>/wee.css',
						src: '<%= config.paths.temp %>/wee.less'
					}
				]
			},
			lib: {
				files: [{
					expand: true,
					cwd: '<%= config.paths.cssSource %>/lib',
					dest: '<%= config.paths.css %>/lib',
					src: [
						'**/*.{css,less}',
						'!**/*.min.css'
					],
					rename: function(dest, src) {
						return Wee.getMinExtension(dest, src, '.min.css');
					}
				}]
			}
		},
		uglify: {
			options: {
				compress: {
					drop_debugger: false
				}
			},
			core: {
				files: [{
					dest: '<%= config.paths.js %>script.min.js',
					src: '<%= config.script.files %>'
				}]
			},
			lib: {
				files: [{
					expand: true,
					cwd: '<%= config.paths.jsSource %>/lib',
					dest: '<%= config.paths.js %>/lib',
					src: [
						'**/*.js',
						'!**/*.min.js'
					],
					rename: function(dest, src) {
						return Wee.getMinExtension(dest, src, '.min.js');
					}
				}]
			}
		},
		concat: {
			style: {
				dest: '<%= config.paths.css %>/style.min.css',
				src: '<%= config.style.concat %>'
			}
		},
		imagemin: {
			options: {
				progressive: true,
				svgoPlugins: [
					{
						removeViewBox: false
					},
					{
						convertPathData: false
					}
				]
			},
			core: {
				files: [
					{
						expand: true,
						cwd: '<%= config.paths.imgSource %>',
						dest: '<%= config.paths.img %>',
						src: [
							'**/*.{gif,jpg,png,svg}'
						]
					},
					{
						expand: true,
						cwd: '<%= config.paths.modulesSource %>',
						dest: '<%= config.paths.modules %>',
						src: [
							'**/*.{gif,jpg,png,svg}'
						]
					}
				]
			}
		},
		watch: {
			options: {
				spawn: false
			},
			imgCore: {
				files: [
					'<%= config.paths.imgSource %>/**/*.{gif,jpg,png,svg}',
					'<%= config.paths.modulesSource %>/**/*.{gif,jpg,png,svg}'
				],
				tasks: [
					'newer:imagemin',
					'notify:images'
				]
			},
			scriptCore: {
				files: '<%= config.script.files %>',
				tasks: [
					'uglify:core',
					'notify:script'
				]
			},
			scriptLib: {
				files: [
					'<%= config.paths.jsSource %>/lib/**/*.js',
					'!<%= config.paths.jsSource %>/lib/**/*.min.js'
				],
				tasks: [
					'uglify:lib',
					'notify:script'
				]
			},
			styleCore: {
				files: [
					'wee/style/**/*.less',
					'<%= config.paths.cssSource %>/custom/**/*.less',
					'!<%= config.paths.temp %>wee.legacy.less'
				],
				tasks: [
					'less:core',
					'concat:style',
					'notify:style'
				]
			},
			styleLib: {
				files: [
					'<%= config.paths.cssSource %>/lib/**/*.{css,less}',
					'!<%= config.paths.cssSource %>/lib/**/*.min.css'
				],
				tasks: [
					'less:lib',
					'notify:style'
				]
			},
			styleBuild: {
				files: [
					'<%= config.paths.cssSource %>/build/**/*.{css,less}'
				],
				tasks: [
					'buildStyle',
					'notify:style'
				],
				options: {
					event: [
						'added',
						'deleted'
					]
				}
			},
			styleBuildUpdate: {
				files: [
					'<%= config.paths.cssSource %>/build/**/*.{css,less}'
				],
				tasks: [
					'less:core',
					'concat:style',
					'notify:style'
				],
				options: {
					event: [
						'changed'
					]
				}
			},
			styleConcat: {
				files: [
					'<%= config.paths.temp %>/**/*.css'
				],
				tasks: [
					'concat:style',
					'notify:style'
				]
			},
			fontSync: {
				files: [
					'<%= config.paths.fontSource %>/**/*.{eot,svg,ttf,woff,woff2}'
				],
				tasks: [
					'syncDirectory:fonts',
					'notify:fonts'
				]
			},
			project: {
				files: [
					'<%= config.path %>',
					'<%= config.paths.modulesSource %>/*/module.json'
				],
				tasks: [
					'default',
					'notify:project'
				]
			}
		}
	});

	// -------------------------------------
	// Load Plugins
	// -------------------------------------

	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-imagemin');
	grunt.loadNpmTasks('grunt-contrib-less');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-newer');

	// -----------------------------------
	// Grunt Tasks
	// -----------------------------------

	grunt.registerTask('default', [
		'init',
		'cleanup',
		'setup',
		'configStyle',
		'configScript',
		'configGenerator',
		'buildStyle',
		'buildModules',
		'buildLegacy',
		'uglify:core',
		'uglify:lib',
		'imagemin',
		'syncDirectory:fonts'
	]);

	// Build + Watch
	grunt.registerTask('local', [
		'default',
		'proxy',
		'sync',
		'checkUpdates',
		'watch'
	]);

	// Build + Server + Open + Watch
	grunt.registerTask('static', [
		'default',
		'server',
		'sync',
		'checkUpdates',
		'watch'
	]);

	// Validate
	grunt.registerTask('validate', [
		'init',
		'runValidation'
	]);

	// Generate Site
	grunt.registerTask('generate', [
		'init',
		'configGenerator'
	]);

	// Update
	grunt.registerTask('update', [
		'checkUpdates'
	]);
};<commit_msg>Remove redundant slashes in Grunt task paths<commit_after>/* global global */

// -------------------------------------
// Load Dependencies
// -------------------------------------

var LessCssClean = require('less-plugin-clean-css');

global.fs = require('fs-extra');
global.path = require('path');
global.browserSync = require('browser-sync');
global.JSCS = require('jscs');
global.jshint = require('jshint').JSHINT;
global.Wee = require('../script/wee').Wee;

// Load build utilities
require('./utils');

// -------------------------------------
// Configure Grunt
// -------------------------------------

module.exports = function(grunt) {
	global.config = {};
	global.server = {};
	global.moduleLegacy = [];
	global.legacy = {};
	global.reloadPaths = [];
	global.legacyBuild = [];
	global.legacyConvert = [];
	global.version = '3.0.0';

	grunt.initConfig({
		less: {
			options: {
				modifyVars: '<%= config.style.vars %>',
				strictMath: true,
				paths: [
					'<%= config.paths.root %>'
				],
				plugins: [
					new LessCssClean()
				]
			},
			core: {
				files: [
					{
						dest: '<%= config.paths.temp %>wee.css',
						src: '<%= config.paths.temp %>wee.less'
					}
				]
			},
			lib: {
				files: [{
					expand: true,
					cwd: '<%= config.paths.cssSource %>lib',
					dest: '<%= config.paths.css %>lib',
					src: [
						'**/*.{css,less}',
						'!**/*.min.css'
					],
					rename: function(dest, src) {
						return Wee.getMinExtension(dest, src, '.min.css');
					}
				}]
			}
		},
		uglify: {
			options: {
				compress: {
					drop_debugger: false
				}
			},
			core: {
				files: [{
					dest: '<%= config.paths.js %>script.min.js',
					src: '<%= config.script.files %>'
				}]
			},
			lib: {
				files: [{
					expand: true,
					cwd: '<%= config.paths.jsSource %>lib',
					dest: '<%= config.paths.js %>lib',
					src: [
						'**/*.js',
						'!**/*.min.js'
					],
					rename: function(dest, src) {
						return Wee.getMinExtension(dest, src, '.min.js');
					}
				}]
			}
		},
		concat: {
			style: {
				dest: '<%= config.paths.css %>style.min.css',
				src: '<%= config.style.concat %>'
			}
		},
		imagemin: {
			options: {
				progressive: true,
				svgoPlugins: [
					{
						removeViewBox: false
					},
					{
						convertPathData: false
					}
				]
			},
			core: {
				files: [
					{
						expand: true,
						cwd: '<%= config.paths.imgSource %>',
						dest: '<%= config.paths.img %>',
						src: [
							'**/*.{gif,jpg,png,svg}'
						]
					},
					{
						expand: true,
						cwd: '<%= config.paths.modulesSource %>',
						dest: '<%= config.paths.modules %>',
						src: [
							'**/*.{gif,jpg,png,svg}'
						]
					}
				]
			}
		},
		watch: {
			options: {
				spawn: false
			},
			imgCore: {
				files: [
					'<%= config.paths.imgSource %>**/*.{gif,jpg,png,svg}',
					'<%= config.paths.modulesSource %>**/*.{gif,jpg,png,svg}'
				],
				tasks: [
					'newer:imagemin',
					'notify:images'
				]
			},
			scriptCore: {
				files: '<%= config.script.files %>',
				tasks: [
					'uglify:core',
					'notify:script'
				]
			},
			scriptLib: {
				files: [
					'<%= config.paths.jsSource %>lib**/*.js',
					'!<%= config.paths.jsSource %>lib**/*.min.js'
				],
				tasks: [
					'uglify:lib',
					'notify:script'
				]
			},
			styleCore: {
				files: [
					'wee/style/**/*.less',
					'<%= config.paths.cssSource %>custom/**/*.less',
					'!<%= config.paths.temp %>wee.legacy.less'
				],
				tasks: [
					'less:core',
					'concat:style',
					'notify:style'
				]
			},
			styleLib: {
				files: [
					'<%= config.paths.cssSource %>lib/**/*.{css,less}',
					'!<%= config.paths.cssSource %>lib/**/*.min.css'
				],
				tasks: [
					'less:lib',
					'notify:style'
				]
			},
			styleBuild: {
				files: [
					'<%= config.paths.cssSource %>build/**/*.{css,less}'
				],
				tasks: [
					'buildStyle',
					'notify:style'
				],
				options: {
					event: [
						'added',
						'deleted'
					]
				}
			},
			styleBuildUpdate: {
				files: [
					'<%= config.paths.cssSource %>build/**/*.{css,less}'
				],
				tasks: [
					'less:core',
					'concat:style',
					'notify:style'
				],
				options: {
					event: [
						'changed'
					]
				}
			},
			styleConcat: {
				files: [
					'<%= config.paths.temp %>**/*.css'
				],
				tasks: [
					'concat:style',
					'notify:style'
				]
			},
			fontSync: {
				files: [
					'<%= config.paths.fontSource %>**/*.{eot,svg,ttf,woff,woff2}'
				],
				tasks: [
					'syncDirectory:fonts',
					'notify:fonts'
				]
			},
			project: {
				files: [
					'<%= config.path %>',
					'<%= config.paths.modulesSource %>*/module.json'
				],
				tasks: [
					'default',
					'notify:project'
				]
			}
		}
	});

	// -------------------------------------
	// Load Plugins
	// -------------------------------------

	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-imagemin');
	grunt.loadNpmTasks('grunt-contrib-less');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-newer');

	// -----------------------------------
	// Grunt Tasks
	// -----------------------------------

	grunt.registerTask('default', [
		'init',
		'cleanup',
		'setup',
		'configStyle',
		'configScript',
		'configGenerator',
		'buildStyle',
		'buildModules',
		'buildLegacy',
		'uglify:core',
		'uglify:lib',
		'imagemin',
		'syncDirectory:fonts'
	]);

	// Build + Watch
	grunt.registerTask('local', [
		'default',
		'proxy',
		'sync',
		'checkUpdates',
		'watch'
	]);

	// Build + Server + Open + Watch
	grunt.registerTask('static', [
		'default',
		'server',
		'sync',
		'checkUpdates',
		'watch'
	]);

	// Validate
	grunt.registerTask('validate', [
		'init',
		'runValidation'
	]);

	// Generate Site
	grunt.registerTask('generate', [
		'init',
		'configGenerator'
	]);

	// Update
	grunt.registerTask('update', [
		'checkUpdates'
	]);
};<|endoftext|>