<commit_before>import React, { Component } from 'react';
import { View, StyleSheet, TouchableOpacity, Dimensions, Text } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { getPlatformValue } from '../utils';

const { height, width } = Dimensions.get('window');

export default class Points extends Component {

  constructor() {
    super();
    this.state = {
      CurrentPoints: 0,
      dailyPoints: 0,
      userLocalRank: 0,
      userGlobalRank: 0,
      friends: 0,
    };
  }

  componentWillMount() {
    this._localRank();
    this._getBoard();
    this.setFriends();
    this.setPoints();
  }

  async setFriends() {
    try {
      const _this = this;
      await this.props.Firebase.auth().currentUser;

      const uid = this.props.Firebase.auth().currentUser.uid;
      const ref = this.props.Firebase.database().ref();
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName, uid: snapshot.val().uid });
        });
        return friendList;
      }).then((value) => {
        if ((value.length > 0)) {
          _this.setState({
            friends: value.length,
          });
        } else {
          _this.setState({
            friends: 0,
          });
        }
      });
    } catch (e) {
    }
  }

  async _getBoard() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userRankingRef.orderByChild('points').once('value').then((snap) => {
        snap.forEach((snapshot) => {
          leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
        });
        return Promise.all(leaderBoard);
      })
      .then((leaderBoard) => {
        const newleaderBoard = leaderBoard.reverse();
        return newleaderBoard;
      })
      .then((newleaderBoard) => {
        const rankings = [];
        const ranks = Object.keys(newleaderBoard);
        ranks.forEach((ranked) => {
          const name = newleaderBoard[ranked][0];
          const rank = +ranked + 1;
          rankings.push([name, `${rank}`]);
        });
        return rankings;
      })
      .then((rankings) => {
        rankings.forEach((Rank) => {
          if (Rank[0] === user.displayName) {
            this.setState({ userGlobalRank: Rank[1] });
          }
        });
      });
    } catch (e) {
    }
  }

  async _localRank() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName });
        });
        return friendList;
      })
      .then((friendList) => {
        userRankingRef.orderByChild('points').once('value').then((snap) => {
          snap.forEach((snapshot) => {
            leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
          });
          return Promise.all(leaderBoard);
        })
          .then((leaderBoard) => {
            const newleaderBoard = leaderBoard.reverse();
            return newleaderBoard;
          })
          .then((newleaderBoard) => {
            const friendRank = [];
            friendList.forEach((element) => {
              for (let i = 0; i < newleaderBoard.length; i++) {
                if ((newleaderBoard[i][0] === `${element.displayName}`)) {
                  friendRank.push([newleaderBoard[i][1], newleaderBoard[i][0]]);
                }
              }
            });
            newleaderBoard.forEach((element) => {
              if (element[0] === user.displayName) {
                friendRank.push([element[1], element[0]]);
              }
            });
            function sortNumber(a, b) {
              return b[0] - a[0];
            }
            const sortedFriends = friendRank.sort(sortNumber);
            const rankings = [];
            const ranks = Object.keys(friendRank);
            ranks.forEach((ranked) => {
              const name = sortedFriends[ranked][1];
              const rank = +ranked + 1;
              rankings.push([name, `${rank}`]);
            });
            return rankings;
          })
          .then((rankings) => {
            const localRank = 0;
            rankings.forEach((Rank) => {
              if (Rank[0] === user.displayName) {
                this.setState({ userLocalRank: Rank[1] });
              }
            });
          });
      });
    } catch (e) {
    }
  }

  async setPoints() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userPointsRef = ref.child('userReadable/userPoints').child(uid);
      const userDailyPointsRef = ref.child('userReadable/userDailyPoints').child(uid);

      userDailyPointsRef.once('value').then((snap) => {
        const dailyPoints = snap.val().points;
        this.setState({ dailyPoints });
      });

      userPointsRef.once('value').then((snap) => {
        const points = snap.val().points;
        return points;
      })
      .then((points) => {
        this.setState({ CurrentPoints: points });
      });
    } catch (e) {
    }
  }

  async _localRank() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName });
        });
        return friendList;
      })
      .then((friendList) => {
        userRankingRef.orderByChild('points').once('value').then((snap) => {
          snap.forEach((snapshot) => {
            leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
          });
          return Promise.all(leaderBoard);
        })
          .then((leaderBoard) => {
            const newleaderBoard = leaderBoard.reverse();
            return newleaderBoard;
          })
          .then((newleaderBoard) => {
            const friendRank = [];
            friendList.forEach((element) => {
              for (let i = 0; i < newleaderBoard.length; i++) {
                if ((newleaderBoard[i][0] === `${element.displayName}`)) {
                  friendRank.push([newleaderBoard[i][1], newleaderBoard[i][0]]);
                }
              }
            });
            newleaderBoard.forEach((element) => {
              if (element[0] === user.displayName) {
                friendRank.push([element[1], element[0]]);
              }
            });
            function sortNumber(a, b) {
              return b[0] - a[0];
            }
            const sortedFriends = friendRank.sort(sortNumber);
            const rankings = [];
            const ranks = Object.keys(friendRank);
            ranks.forEach((ranked) => {
              const name = sortedFriends[ranked][1];
              const rank = +ranked + 1;
              rankings.push([name, `${rank}`]);
            });
            return rankings;
          })
          .then((rankings) => {
            rankings.forEach((Rank) => {
              if (Rank[0] === user.displayName) {
                this.setState({ userLocalRank: Rank[1] });
              }
            });
          });
      });
    } catch (e) {
    }
  }

  async _getBoard() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userRankingRef.orderByChild('points').once('value').then((snap) => {
        snap.forEach((snapshot) => {
          leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
        });
        return Promise.all(leaderBoard);
      })
      .then((leaderBoard) => {
        const newleaderBoard = leaderBoard.reverse();
        return newleaderBoard;
      })
      .then((newleaderBoard) => {
        const rankings = [];
        const ranks = Object.keys(newleaderBoard);
        ranks.forEach((ranked) => {
          const name = newleaderBoard[ranked][0];
          const rank = +ranked + 1;
          rankings.push([name, `${rank}`]);
        });
        return rankings;
      })
      .then((rankings) => {
        rankings.forEach((Rank) => {
          if (Rank[0] === user.displayName) {
            this.setState({ userRank: Rank[1] });
          }
        });
      });
    } catch (e) {
    }
  }

  render() {
    return (
      <View style={{ flex: 1, backgroundColor: 'black' }}>
        <View style={styles.header}>
          <TouchableOpacity>
            <Icon
              name="bars"
              size={30}
              color="white"
              onPress={this.props.sideMenu}
            />
          </TouchableOpacity>
          <Text
            style={{
              fontSize: 25,
              textAlign: 'center',
              width: 250,
              color: 'white',
              fontWeight: '300',
              marginBottom: 5,
            }}
          >
            POINTS
          </Text>
          <Icon name="diamond" size={20} color="#ffc107" />
        </View>
        <View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', width, height: height * 0.25 }}>
          <Text style={{ fontFamily: 'OpenSans', fontFamily: 'OpenSans', fontSize: 100, color: '#bdbdbd', fontFamily: 'OpenSans', fontWeight: '100', textAlign: 'left' }}>{this.state.CurrentPoints}</Text>
          <Text style={{ fontFamily: 'OpenSans', fontFamily: 'OpenSans', color: '#ffc107', textAlign: 'left' }}>Total Pts</Text>
        </View>
        <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#212121', width, height: height * 0.20, borderBottomWidth: 1, borderTopWidth: 1, borderColor: '#ffc107' }}>
          <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 30 }}>Today's Points</Text>
          <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 40 }}>
            {this.state.dailyPoints}
            <Text style={{ fontFamily: 'OpenSans', fontSize: 17 }}>Pts</Text>
          </Text>
        </View>
        <View style={{ width, height: height * 0.22 }}>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+2 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>Checking In</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+10 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>Under Budget</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+5 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>New Goal</Text>
          </View>
        </View>
        <View style={{ justifyContent: 'center', backgroundColor: '#212121', padding: 5, borderBottomWidth: 1, borderTopWidth: 1, borderColor: '#ffc107' }}>
          <Text style={{ fontFamily: 'OpenSans', textAlign: 'center', color: 'white', fontSize: 20 }}>Ranking</Text>
        </View>
        <View style={{ width, height: height * 0.19, padding: 15, paddingTop: 0, paddingBottom: 0 }}>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 0.5, borderColor: '#e0e0e0' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>Local Rank</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>{this.state.userLocalRank}</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 0.5, borderColor: '#e0e0e0' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>World Rank</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>{this.state.userGlobalRank}</Text>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  totalPoints: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 60,
  },
  red: {
    color: 'red',
  },
  headline: {
    fontWeight: 'bold',
    fontSize: 18,
    marginTop: 0,
    width: 200,
    textAlign: 'center',
    backgroundColor: 'yellow',
  },
  header: {
    paddingTop: getPlatformValue('android', 25, 20),
    flex: 0,
    flexDirection: 'row',
    height: 60,
    backgroundColor: 'black',
    justifyContent: 'space-around',
    alignItems: 'center',
    borderBottomWidth: 1,
    borderColor: '#424242',
    zIndex: 999999,
  },
});
<commit_msg>fix spacing in points scene<commit_after>import React, { Component } from 'react';
import { View, StyleSheet, TouchableOpacity, Dimensions, Text } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { getPlatformValue } from '../utils';

const { height, width } = Dimensions.get('window');

export default class Points extends Component {

  constructor() {
    super();
    this.state = {
      CurrentPoints: 0,
      dailyPoints: 0,
      userLocalRank: 0,
      userGlobalRank: 0,
      friends: 0,
    };
  }

  componentWillMount() {
    this._localRank();
    this._getBoard();
    this.setFriends();
    this.setPoints();
  }

  async setFriends() {
    try {
      const _this = this;
      await this.props.Firebase.auth().currentUser;

      const uid = this.props.Firebase.auth().currentUser.uid;
      const ref = this.props.Firebase.database().ref();
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName, uid: snapshot.val().uid });
        });
        return friendList;
      }).then((value) => {
        if ((value.length > 0)) {
          _this.setState({
            friends: value.length,
          });
        } else {
          _this.setState({
            friends: 0,
          });
        }
      });
    } catch (e) {
    }
  }

  async _getBoard() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userRankingRef.orderByChild('points').once('value').then((snap) => {
        snap.forEach((snapshot) => {
          leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
        });
        return Promise.all(leaderBoard);
      })
      .then((leaderBoard) => {
        const newleaderBoard = leaderBoard.reverse();
        return newleaderBoard;
      })
      .then((newleaderBoard) => {
        const rankings = [];
        const ranks = Object.keys(newleaderBoard);
        ranks.forEach((ranked) => {
          const name = newleaderBoard[ranked][0];
          const rank = +ranked + 1;
          rankings.push([name, `${rank}`]);
        });
        return rankings;
      })
      .then((rankings) => {
        rankings.forEach((Rank) => {
          if (Rank[0] === user.displayName) {
            this.setState({ userGlobalRank: Rank[1] });
          }
        });
      });
    } catch (e) {
    }
  }

  async _localRank() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName });
        });
        return friendList;
      })
      .then((friendList) => {
        userRankingRef.orderByChild('points').once('value').then((snap) => {
          snap.forEach((snapshot) => {
            leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
          });
          return Promise.all(leaderBoard);
        })
          .then((leaderBoard) => {
            const newleaderBoard = leaderBoard.reverse();
            return newleaderBoard;
          })
          .then((newleaderBoard) => {
            const friendRank = [];
            friendList.forEach((element) => {
              for (let i = 0; i < newleaderBoard.length; i++) {
                if ((newleaderBoard[i][0] === `${element.displayName}`)) {
                  friendRank.push([newleaderBoard[i][1], newleaderBoard[i][0]]);
                }
              }
            });
            newleaderBoard.forEach((element) => {
              if (element[0] === user.displayName) {
                friendRank.push([element[1], element[0]]);
              }
            });
            function sortNumber(a, b) {
              return b[0] - a[0];
            }
            const sortedFriends = friendRank.sort(sortNumber);
            const rankings = [];
            const ranks = Object.keys(friendRank);
            ranks.forEach((ranked) => {
              const name = sortedFriends[ranked][1];
              const rank = +ranked + 1;
              rankings.push([name, `${rank}`]);
            });
            return rankings;
          })
          .then((rankings) => {
            const localRank = 0;
            rankings.forEach((Rank) => {
              if (Rank[0] === user.displayName) {
                this.setState({ userLocalRank: Rank[1] });
              }
            });
          });
      });
    } catch (e) {
    }
  }

  async setPoints() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userPointsRef = ref.child('userReadable/userPoints').child(uid);
      const userDailyPointsRef = ref.child('userReadable/userDailyPoints').child(uid);

      userDailyPointsRef.once('value').then((snap) => {
        const dailyPoints = snap.val().points;
        this.setState({ dailyPoints });
      });

      userPointsRef.once('value').then((snap) => {
        const points = snap.val().points;
        return points;
      })
      .then((points) => {
        this.setState({ CurrentPoints: points });
      });
    } catch (e) {
    }
  }

  async _localRank() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const uid = user.uid;
      const userFriendsRef = ref.child('userReadable/userFriends').child(uid);
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userFriendsRef.orderByKey().once('value').then((snap) => {
        const friendList = [];
        snap.forEach((snapshot) => {
          friendList.push({ displayName: snapshot.val().displayName });
        });
        return friendList;
      })
      .then((friendList) => {
        userRankingRef.orderByChild('points').once('value').then((snap) => {
          snap.forEach((snapshot) => {
            leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
          });
          return Promise.all(leaderBoard);
        })
          .then((leaderBoard) => {
            const newleaderBoard = leaderBoard.reverse();
            return newleaderBoard;
          })
          .then((newleaderBoard) => {
            const friendRank = [];
            friendList.forEach((element) => {
              for (let i = 0; i < newleaderBoard.length; i++) {
                if ((newleaderBoard[i][0] === `${element.displayName}`)) {
                  friendRank.push([newleaderBoard[i][1], newleaderBoard[i][0]]);
                }
              }
            });
            newleaderBoard.forEach((element) => {
              if (element[0] === user.displayName) {
                friendRank.push([element[1], element[0]]);
              }
            });
            function sortNumber(a, b) {
              return b[0] - a[0];
            }
            const sortedFriends = friendRank.sort(sortNumber);
            const rankings = [];
            const ranks = Object.keys(friendRank);
            ranks.forEach((ranked) => {
              const name = sortedFriends[ranked][1];
              const rank = +ranked + 1;
              rankings.push([name, `${rank}`]);
            });
            return rankings;
          })
          .then((rankings) => {
            rankings.forEach((Rank) => {
              if (Rank[0] === user.displayName) {
                this.setState({ userLocalRank: Rank[1] });
              }
            });
          });
      });
    } catch (e) {
    }
  }

  async _getBoard() {
    try {
      const ref = this.props.Firebase.database().ref();
      const user = this.props.Firebase.auth().currentUser;
      const userRankingRef = ref.child('userReadable/userPoints');
      const leaderBoard = [];

      userRankingRef.orderByChild('points').once('value').then((snap) => {
        snap.forEach((snapshot) => {
          leaderBoard.push([snapshot.val().displayName, snapshot.val().points]);
        });
        return Promise.all(leaderBoard);
      })
      .then((leaderBoard) => {
        const newleaderBoard = leaderBoard.reverse();
        return newleaderBoard;
      })
      .then((newleaderBoard) => {
        const rankings = [];
        const ranks = Object.keys(newleaderBoard);
        ranks.forEach((ranked) => {
          const name = newleaderBoard[ranked][0];
          const rank = +ranked + 1;
          rankings.push([name, `${rank}`]);
        });
        return rankings;
      })
      .then((rankings) => {
        rankings.forEach((Rank) => {
          if (Rank[0] === user.displayName) {
            this.setState({ userRank: Rank[1] });
          }
        });
      });
    } catch (e) {
    }
  }

  render() {
    return (
      <View style={{ flex: 1, backgroundColor: 'black' }}>
        <View style={styles.header}>
          <TouchableOpacity>
            <Icon
              name="bars"
              size={30}
              color="white"
              onPress={this.props.sideMenu}
            />
          </TouchableOpacity>
          <Text
            style={{
              fontSize: 25,
              textAlign: 'center',
              width: 250,
              color: 'white',
              fontWeight: '300',
              marginBottom: 5,
            }}
          >
            POINTS
          </Text>
          <Icon name="diamond" size={20} color="#ffc107" />
        </View>
        <View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', width, height: height * 0.25 }}>
          <Text style={{ marginLeft: 10, fontFamily: 'OpenSans', fontFamily: 'OpenSans', fontSize: 100, color: '#bdbdbd', fontFamily: 'OpenSans', fontWeight: '100', textAlign: 'left' }}>{this.state.CurrentPoints}</Text>
          <Text style={{ marginLeft: 10, fontFamily: 'OpenSans', fontFamily: 'OpenSans', color: '#ffc107', textAlign: 'left' }}>Total Pts</Text>
        </View>
        <View style={{ padding: 10, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#212121', width, height: height * 0.20, borderBottomWidth: 1, borderTopWidth: 1, borderColor: '#ffc107' }}>
          <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 30 }}>Today's Points</Text>
          <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 40 }}>
            {this.state.dailyPoints}
            <Text style={{ fontFamily: 'OpenSans', fontSize: 17 }}>Pts</Text>
          </Text>
        </View>
        <View style={{ width, height: height * 0.22, padding: 10 }}>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+2 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>Checking In</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+10 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>Under Budget</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>+5 Pts</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white' }}>New Goal</Text>
          </View>
        </View>
        <View style={{ justifyContent: 'center', backgroundColor: '#212121', padding: 5, borderBottomWidth: 1, borderTopWidth: 1, borderColor: '#ffc107' }}>
          <Text style={{ fontFamily: 'OpenSans', textAlign: 'center', color: 'white', fontSize: 20 }}>Ranking</Text>
        </View>
        <View style={{ width, height: height * 0.19, padding: 15, paddingTop: 0, paddingBottom: 0 }}>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 0.5, borderColor: '#e0e0e0' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>Local Rank</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>{this.state.userLocalRank}</Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 0.5, borderColor: '#e0e0e0' }}>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>World Rank</Text>
            <Text style={{ fontFamily: 'OpenSans', color: 'white', fontSize: 17 }}>{this.state.userGlobalRank}</Text>
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  totalPoints: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 60,
  },
  red: {
    color: 'red',
  },
  headline: {
    fontWeight: 'bold',
    fontSize: 18,
    marginTop: 0,
    width: 200,
    textAlign: 'center',
    backgroundColor: 'yellow',
  },
  header: {
    paddingTop: getPlatformValue('android', 25, 20),
    flex: 0,
    flexDirection: 'row',
    height: 60,
    backgroundColor: 'black',
    justifyContent: 'space-around',
    alignItems: 'center',
    borderBottomWidth: 1,
    borderColor: '#424242',
    zIndex: 999999,
  },
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Kurahen Premium
// @namespace   karachan.org
// @description Zestaw dodatkowych opcji dla forum młodzieżowo-katolickiego
// @version     1.0
// @include     http://www.karachan.org/*
// @include     http://karachan.org/*
// @exclude     http://www.karachan.org/*/src/*
// @exclude     http://karachan.org/*/src/*
// ==/UserScript==

(function () {
	'use strict';

	// Konfiguracja
	var customBBoardTitle = '/b/ - Random';
	var enableBetterFonts = true; // Podmienia domyślne czcionki na Roboto

	// Zaawansowana konfiguracja
	var bbCodes = ['b', 'i', 'u', 's', 'small', 'code', 'spoiler'];
	var wordfilters = [
		['#nowocioty', 'STAROCIOTY PAMIĘTAJĄ'],
		['#gimbo', 'xD'],
		['#penis', 'pisiorek'],
		['#wagina', 'cipuszka'],
		['#m__b', 'groźny WYKOPEK wykryty'],
		['#Lasoupeauxchoux', 'kapuśniaczek'],
		['#homoś', 'pedał'],
		['#korwinkrulempolski', 'kongres nowej prawicy'],
		['#1%', 'groźny LEWAK wykryty']
	];
	var boardsWithId = ['b', 'fz', 'z'];
	var colors = [
		'#FF8080',
		'#FFDD80',
		'#80FFB7',
		'#80D0FF',
		'#C680FF',
		'#FFAE80',
		'#D5FF80',
		'#80FFFD',
		'#8097FF',
		'#FF80CA',
		"#ff7f7f",
		"#779aef",
		"#b0de6f",
		"#cc66c0",
		"#5cb9a9",
		"#f3bb79",
		"#8d71e2",
		"#6dd168",
		"#be5f7e",
		"#7bc8f6"
	];

	var KurahenPremium = function () {
		var currentBoardName = this.getCurrentBoardName();

		if (currentBoardName === '') {
			return; // We are not on any useful page
		} else if (currentBoardName === 'b') {
			this.changeBoardTitle(customBBoardTitle);
		}
		this.updatePageTitle();
		this.disableNightStyle();
		this.setCookie('regulamin', 'accepted');
		this.insertButtonBar();
		this.replaceEmailFieldWithSelect();
		this.showAllPostersEmails();

		if (boardsWithId.indexOf(currentBoardName) > -1 && this.isCurrentWebpageThread()) {
			this.colorizeAndNamePosters();
		}

		if (enableBetterFonts) {
			this.changeFonts();
		}
	};

	KurahenPremium.prototype.changeBoardTitle = function (newTitle) {
		document.title = newTitle;
		document.getElementsByClassName('boardTitle')[0].textContent = newTitle;
	};

	KurahenPremium.prototype.updatePageTitle = function () {
		var page = parseInt(window.location.pathname.split('/')[2]);
		var prefix = '';

		if (this.isCurrentWebpageThread()) {
			prefix = this.getTopicFromFirstPostContent();
		} else if (!isNaN(page)) {
			prefix = 'Strona ' + page;
		}

		if (prefix.length > 0) {
			prefix += ' - ';
		}

		document.title = prefix + document.title;
	};

	KurahenPremium.prototype.setCookie = function (name, value) {
		document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + '; path=/; max-age=2592000';
	};

	KurahenPremium.prototype.changeFonts = function () {
		var newLink = document.createElement('link');
		newLink.href = '//fonts.googleapis.com/css?family=Roboto:400,700&subset=latin,latin-ext';
		newLink.rel = 'stylesheet';
		var existingLink = document.getElementsByTagName('link')[0];
		existingLink.parentNode.insertBefore(newLink, existingLink);
		document.body.style.fontFamily = 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif';
	};

	KurahenPremium.prototype.getCurrentBoardName = function () {
		return window.location.pathname.split('/')[1];
	};

	KurahenPremium.prototype.isCurrentWebpageThread = function () {
		return window.location.pathname.split('/')[2] === 'res';
	};

	KurahenPremium.prototype.getTopicFromFirstPostContent = function () {
		var postMessage = document.querySelector('.thread .postMessage').cloneNode(true);

		var backlinks = postMessage.getElementsByClassName('backlinks');
		if (backlinks.length > 0) {
			postMessage.removeChild(backlinks[0]);
		}

		var links = postMessage.getElementsByClassName('postlink');
		for (var i = 0; i < links.length; i++) {
			postMessage.removeChild(links[i]);
		}

		var postContent = postMessage.textContent;
		return postContent.substr(0, Math.min(postContent.length, 70));
	};

	KurahenPremium.prototype.disableNightStyle = function () {
		var option = document.querySelector('#stylechanger option[value$="night.css"]');
		option.disabled = true;
	};

	KurahenPremium.prototype.replaceEmailFieldWithSelect = function () {
		var emailField = document.querySelector('#postform input[name="email"]');

		var select = document.createElement('select');
		select.name = 'email';
		select.style.margin = '0';
		select.style.width = '236px';
		select.addEventListener('change', function () {
			//noinspection JSPotentiallyInvalidUsageOfThis
			if (this.options[this.selectedIndex].value === 'custom') {
				var textField = document.createElement('input');
				textField.type = 'text';
				textField.className = 'board-input';
				textField.name = 'email';
				select.parentNode.replaceChild(textField, select);
				textField.focus();
			}
		}, false);

		var optionBump = document.createElement('option');
		optionBump.value = '';
		optionBump.selected = true;
		optionBump.textContent = 'Podbij';
		select.appendChild(optionBump);

		var optionSage = document.createElement('option');
		optionSage.value = 'sage';
		optionSage.textContent = 'Saguj';
		select.appendChild(optionSage);

		var optionSpoiler = document.createElement('option');
		optionSpoiler.value = 'spoiler';
		optionSpoiler.textContent = 'Ukryj obrazek';
		select.appendChild(optionSpoiler);

		var optionCustom = document.createElement('option');
		optionCustom.value = 'custom';
		optionCustom.textContent = 'Wpisz własny...';
		select.appendChild(optionCustom);

		emailField.parentNode.replaceChild(select, emailField);
	};

	KurahenPremium.prototype.showAllPostersEmails = function () {
		var postersEmails = document.getElementsByClassName('useremail');

		for (var i = 0; i < postersEmails.length; i++) {
			postersEmails[i].textContent += ' (' + this.parseMailto(postersEmails[i].getAttribute('href')) + ') ';
			postersEmails[i].removeAttribute('href');
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.parseMailto = function (mailto) {
		return mailto.replace('mailto:', '');
	};

	KurahenPremium.prototype.colorizeAndNamePosters = function () {
		var postersIds = document.getElementsByClassName("posteruid");
		var postersStats = {};

		var opId;
		for (var i = 0; i < postersIds.length; i++) {
			var posterId = this.parsePosterId(postersIds[i].textContent);
			if (i === 0) {
				opId = posterId;
			}

			postersIds[i].className += ' poster-id-' + posterId;
			if (posterId === opId) {
				postersIds[i].textContent = '\u00a0OP nitki';
			} else {
				postersIds[i].textContent = '\u00a0' + posterId;
			}

			if (isNaN(postersStats[posterId])) {
				postersStats[posterId] = 1;
			} else {
				postersStats[posterId]++;
			}
		}

		var style = document.createElement('style');
		style.type = 'text/css';
		for (var id in postersStats) {
			if (postersStats.hasOwnProperty(id) && postersStats[id] > 1) {
				style.textContent += '.poster-id-' + id + '{color:#000;background-color: ' + this.getNextColor() + ';}';
				style.textContent += '.poster-id-' + id + ':after{content:" (' + postersStats[id] + ' postów)\u00a0"}';
			}
		}
		document.getElementsByTagName('head')[0].appendChild(style);
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.getNextColor = function () {
		if (colors.length > 0) {
			return colors.shift();
		} else {
			return "#"+((1<<24)*Math.random()|0).toString(16); // Random color
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.parsePosterId = function (text) {
		return text.trim().substr(5, 8).replace(/[\.|\/|\+|\-]/g, '_');
	};

	KurahenPremium.prototype.insertButtonBar = function () {
		var postForm = document.getElementById('postform');
		var textarea = document.querySelector("#postform textarea");
		var buttonBar = document.createElement('div');
		buttonBar.style.textAlign = 'center';

		this.insertTextFormattingButtons(textarea, buttonBar);
		this.insertWordfilterList(textarea, buttonBar);

		postForm.insertBefore(buttonBar, postForm.firstChild);
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.insertTextFormattingButtons = function (textarea, buttonBar) {
		var onButtonClick = function () {
			var startTag = '[' + this.value + ']';
			var endTag = '[/' + this.value + ']';

			var textBeforeSelection = textarea.value.substring(0, textarea.selectionStart);
			var selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
			var textAfterSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);

			textarea.value = textBeforeSelection + startTag + selectedText + endTag + textAfterSelection;

			textarea.focus();
			textarea.selectionStart += startTag.length;
			textarea.selectionEnd = textarea.selectionStart + selectedText.length;
		};

		for (var i = 0; i < bbCodes.length; i++) {
			var button = document.createElement('input');
			button.type = 'button';
			button.value = bbCodes[i];
			button.addEventListener('click', onButtonClick, false);
			buttonBar.appendChild(button);
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.insertWordfilterList = function (textarea, buttonBar) {
		var wordfiltersSelect = document.createElement('select');

		var defaultOption = document.createElement('option');
		defaultOption.value = '';
		defaultOption.disabled = true;
		defaultOption.selected = true;
		defaultOption.textContent = 'WORDFILTRY';
		wordfiltersSelect.appendChild(defaultOption);

		wordfiltersSelect.addEventListener('change', function () {
			//noinspection JSPotentiallyInvalidUsageOfThis
			var textToInsert = this.options[this.selectedIndex].value;
			var textBeforeEndOfSelection = textarea.value.substring(0, textarea.selectionEnd);
			var textAfterEndOfSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);

			textarea.value = textBeforeEndOfSelection + textToInsert + textAfterEndOfSelection;

			textarea.focus();
			textarea.selectionStart = textBeforeEndOfSelection.length + textToInsert.length;
			textarea.selectionEnd = textarea.selectionStart;

			//noinspection JSPotentiallyInvalidUsageOfThis
			this.selectedIndex = 0;
		}, false);

		for (var j = 0; j < wordfilters.length; j++) {
			var option = document.createElement('option');
			option.value = wordfilters[j][0];
			option.textContent = wordfilters[j][1];
			wordfiltersSelect.appendChild(option);
		}

		buttonBar.appendChild(wordfiltersSelect);
	};

	// Initialize script
	window.KurahenPremium = new KurahenPremium();
})();
<commit_msg>Add fixing external links in posts<commit_after>// ==UserScript==
// @name        Kurahen Premium
// @namespace   karachan.org
// @description Zestaw dodatkowych opcji dla forum młodzieżowo-katolickiego
// @version     1.0
// @include     http://www.karachan.org/*
// @include     http://karachan.org/*
// @exclude     http://www.karachan.org/*/src/*
// @exclude     http://karachan.org/*/src/*
// ==/UserScript==

(function () {
	'use strict';

	// Konfiguracja
	var customBBoardTitle = '/b/ - Random';
	var enableBetterFonts = true; // Podmienia domyślne czcionki na Roboto

	// Zaawansowana konfiguracja
	var bbCodes = ['b', 'i', 'u', 's', 'small', 'code', 'spoiler'];
	var wordfilters = [
		['#nowocioty', 'STAROCIOTY PAMIĘTAJĄ'],
		['#gimbo', 'xD'],
		['#penis', 'pisiorek'],
		['#wagina', 'cipuszka'],
		['#m__b', 'groźny WYKOPEK wykryty'],
		['#Lasoupeauxchoux', 'kapuśniaczek'],
		['#homoś', 'pedał'],
		['#korwinkrulempolski', 'kongres nowej prawicy'],
		['#1%', 'groźny LEWAK wykryty']
	];
	var boardsWithId = ['b', 'fz', 'z'];
	var colors = [
		'#FF8080',
		'#FFDD80',
		'#80FFB7',
		'#80D0FF',
		'#C680FF',
		'#FFAE80',
		'#D5FF80',
		'#80FFFD',
		'#8097FF',
		'#FF80CA',
		"#ff7f7f",
		"#779aef",
		"#b0de6f",
		"#cc66c0",
		"#5cb9a9",
		"#f3bb79",
		"#8d71e2",
		"#6dd168",
		"#be5f7e",
		"#7bc8f6"
	];

	var KurahenPremium = function () {
		var currentBoardName = this.getCurrentBoardName();

		if (currentBoardName === '') {
			return; // We are not on any useful page
		} else if (currentBoardName === 'b') {
			this.changeBoardTitle(customBBoardTitle);
		}
		this.updatePageTitle();
		this.disableNightStyle();
		this.setCookie('regulamin', 'accepted');
		this.insertButtonBar();
		this.replaceEmailFieldWithSelect();
		this.showAllPostersEmails();
		this.fixAllExternalLinks();

		if (boardsWithId.indexOf(currentBoardName) > -1 && this.isCurrentWebpageThread()) {
			this.colorizeAndNamePosters();
		}

		if (enableBetterFonts) {
			this.changeFonts();
		}
	};

	KurahenPremium.prototype.changeBoardTitle = function (newTitle) {
		document.title = newTitle;
		document.getElementsByClassName('boardTitle')[0].textContent = newTitle;
	};

	KurahenPremium.prototype.updatePageTitle = function () {
		var page = parseInt(window.location.pathname.split('/')[2]);
		var prefix = '';

		if (this.isCurrentWebpageThread()) {
			prefix = this.getTopicFromFirstPostContent();
		} else if (!isNaN(page)) {
			prefix = 'Strona ' + page;
		}

		if (prefix.length > 0) {
			prefix += ' - ';
		}

		document.title = prefix + document.title;
	};

	KurahenPremium.prototype.setCookie = function (name, value) {
		document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + '; path=/; max-age=2592000';
	};

	KurahenPremium.prototype.changeFonts = function () {
		var newLink = document.createElement('link');
		newLink.href = '//fonts.googleapis.com/css?family=Roboto:400,700&subset=latin,latin-ext';
		newLink.rel = 'stylesheet';
		var existingLink = document.getElementsByTagName('link')[0];
		existingLink.parentNode.insertBefore(newLink, existingLink);
		document.body.style.fontFamily = 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif';
	};

	KurahenPremium.prototype.getCurrentBoardName = function () {
		return window.location.pathname.split('/')[1];
	};

	KurahenPremium.prototype.isCurrentWebpageThread = function () {
		return window.location.pathname.split('/')[2] === 'res';
	};

	KurahenPremium.prototype.getTopicFromFirstPostContent = function () {
		var postMessage = document.querySelector('.thread .postMessage').cloneNode(true);

		var backlinks = postMessage.getElementsByClassName('backlinks');
		if (backlinks.length > 0) {
			postMessage.removeChild(backlinks[0]);
		}

		var links = postMessage.getElementsByClassName('postlink');
		for (var i = 0; i < links.length; i++) {
			postMessage.removeChild(links[i]);
		}

		var postContent = postMessage.textContent;
		return postContent.substr(0, Math.min(postContent.length, 70));
	};

	KurahenPremium.prototype.disableNightStyle = function () {
		var option = document.querySelector('#stylechanger option[value$="night.css"]');
		option.disabled = true;
	};

	KurahenPremium.prototype.replaceEmailFieldWithSelect = function () {
		var emailField = document.querySelector('#postform input[name="email"]');

		var select = document.createElement('select');
		select.name = 'email';
		select.style.margin = '0';
		select.style.width = '236px';
		select.addEventListener('change', function () {
			//noinspection JSPotentiallyInvalidUsageOfThis
			if (this.options[this.selectedIndex].value === 'custom') {
				var textField = document.createElement('input');
				textField.type = 'text';
				textField.className = 'board-input';
				textField.name = 'email';
				select.parentNode.replaceChild(textField, select);
				textField.focus();
			}
		}, false);

		var optionBump = document.createElement('option');
		optionBump.value = '';
		optionBump.selected = true;
		optionBump.textContent = 'Podbij';
		select.appendChild(optionBump);

		var optionSage = document.createElement('option');
		optionSage.value = 'sage';
		optionSage.textContent = 'Saguj';
		select.appendChild(optionSage);

		var optionSpoiler = document.createElement('option');
		optionSpoiler.value = 'spoiler';
		optionSpoiler.textContent = 'Ukryj obrazek';
		select.appendChild(optionSpoiler);

		var optionCustom = document.createElement('option');
		optionCustom.value = 'custom';
		optionCustom.textContent = 'Wpisz własny...';
		select.appendChild(optionCustom);

		emailField.parentNode.replaceChild(select, emailField);
	};

	KurahenPremium.prototype.showAllPostersEmails = function () {
		var postersEmails = document.getElementsByClassName('useremail');

		for (var i = 0; i < postersEmails.length; i++) {
			postersEmails[i].textContent += ' (' + this.parseMailto(postersEmails[i].getAttribute('href')) + ') ';
			postersEmails[i].removeAttribute('href');
		}
	};

	KurahenPremium.prototype.fixAllExternalLinks = function () {
		var links = document.getElementsByClassName('postlink');
		for (var i = 0; i < links.length; i++) {
			links[i].setAttribute('href', links[i].getAttribute('href').replace('https://href.li/?', ''));
			links[i].setAttribute('target', '_blank');
			links[i].setAttribute('rel', 'noreferrer');
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.parseMailto = function (mailto) {
		return mailto.replace('mailto:', '');
	};

	KurahenPremium.prototype.colorizeAndNamePosters = function () {
		var postersIds = document.getElementsByClassName("posteruid");
		var postersStats = {};

		var opId;
		for (var i = 0; i < postersIds.length; i++) {
			var posterId = this.parsePosterId(postersIds[i].textContent);
			if (i === 0) {
				opId = posterId;
			}

			postersIds[i].className += ' poster-id-' + posterId;
			if (posterId === opId) {
				postersIds[i].textContent = '\u00a0OP nitki';
			} else {
				postersIds[i].textContent = '\u00a0' + posterId;
			}

			if (isNaN(postersStats[posterId])) {
				postersStats[posterId] = 1;
			} else {
				postersStats[posterId]++;
			}
		}

		var style = document.createElement('style');
		style.type = 'text/css';
		for (var id in postersStats) {
			if (postersStats.hasOwnProperty(id) && postersStats[id] > 1) {
				style.textContent += '.poster-id-' + id + '{color:#000;background-color: ' + this.getNextColor() + ';}';
				style.textContent += '.poster-id-' + id + ':after{content:" (' + postersStats[id] + ' postów)\u00a0"}';
			}
		}
		document.getElementsByTagName('head')[0].appendChild(style);
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.getNextColor = function () {
		if (colors.length > 0) {
			return colors.shift();
		} else {
			return "#"+((1<<24)*Math.random()|0).toString(16); // Random color
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.parsePosterId = function (text) {
		return text.trim().substr(5, 8).replace(/[\.|\/|\+|\-]/g, '_');
	};

	KurahenPremium.prototype.insertButtonBar = function () {
		var postForm = document.getElementById('postform');
		var textarea = document.querySelector("#postform textarea");
		var buttonBar = document.createElement('div');
		buttonBar.style.textAlign = 'center';

		this.insertTextFormattingButtons(textarea, buttonBar);
		this.insertWordfilterList(textarea, buttonBar);

		postForm.insertBefore(buttonBar, postForm.firstChild);
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.insertTextFormattingButtons = function (textarea, buttonBar) {
		var onButtonClick = function () {
			var startTag = '[' + this.value + ']';
			var endTag = '[/' + this.value + ']';

			var textBeforeSelection = textarea.value.substring(0, textarea.selectionStart);
			var selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
			var textAfterSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);

			textarea.value = textBeforeSelection + startTag + selectedText + endTag + textAfterSelection;

			textarea.focus();
			textarea.selectionStart += startTag.length;
			textarea.selectionEnd = textarea.selectionStart + selectedText.length;
		};

		for (var i = 0; i < bbCodes.length; i++) {
			var button = document.createElement('input');
			button.type = 'button';
			button.value = bbCodes[i];
			button.addEventListener('click', onButtonClick, false);
			buttonBar.appendChild(button);
		}
	};

	/**
	 * @private
	 */
	KurahenPremium.prototype.insertWordfilterList = function (textarea, buttonBar) {
		var wordfiltersSelect = document.createElement('select');

		var defaultOption = document.createElement('option');
		defaultOption.value = '';
		defaultOption.disabled = true;
		defaultOption.selected = true;
		defaultOption.textContent = 'WORDFILTRY';
		wordfiltersSelect.appendChild(defaultOption);

		wordfiltersSelect.addEventListener('change', function () {
			//noinspection JSPotentiallyInvalidUsageOfThis
			var textToInsert = this.options[this.selectedIndex].value;
			var textBeforeEndOfSelection = textarea.value.substring(0, textarea.selectionEnd);
			var textAfterEndOfSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);

			textarea.value = textBeforeEndOfSelection + textToInsert + textAfterEndOfSelection;

			textarea.focus();
			textarea.selectionStart = textBeforeEndOfSelection.length + textToInsert.length;
			textarea.selectionEnd = textarea.selectionStart;

			//noinspection JSPotentiallyInvalidUsageOfThis
			this.selectedIndex = 0;
		}, false);

		for (var j = 0; j < wordfilters.length; j++) {
			var option = document.createElement('option');
			option.value = wordfilters[j][0];
			option.textContent = wordfilters[j][1];
			wordfiltersSelect.appendChild(option);
		}

		buttonBar.appendChild(wordfiltersSelect);
	};

	// Initialize script
	window.KurahenPremium = new KurahenPremium();
})();
<|endoftext|>


<commit_before>var mongoose = require('mongoose');

var RecipeSchema = new mongoose.Schema({
    name: String,
    author: String,
    ingredients: [{type: String}],
    prepTime: {type: Number, default: 30},
    link: String,
    instructions: String
});

mongoose.model('Recipe', RecipeSchema);<commit_msg>Recipe model now uses Food objects for ingredients list<commit_after>var mongoose = require('mongoose');

var RecipeSchema = new mongoose.Schema({
    name: String,
    author: String,
    ingredients: [{type: mongoose.Schema.Types.ObjectId, ref: 'Food' }],
    prepTime: {type: Number, default: 30},
    link: String,
    instructions: String
});

mongoose.model('Recipe', RecipeSchema);<|endoftext|>


<commit_before>Avatars = new FS.Collection('avatars', {
  stores: [new FS.Store.GridFS('avatars')],
  filter: {
    maxSize: 520000,
    allow: {
      contentTypes: ['image/*'],
    },
  },
});

function isOwner(userId, file) {
  return userId && userId === file.userId;
}

Avatars.allow({
  insert: isOwner,
  update: isOwner,
  remove: isOwner,
  download() {
    return true;
  },
  fetch: ['userId'],
});

Avatars.files.before.insert((userId, doc) => {
  doc.userId = userId;
});

export default Avatars;
<commit_msg>Ref: Avatars to use modern gridfs<commit_after>import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
import { createBucket } from './lib/grid/createBucket';
import { createOnAfterUpload } from './lib/fsHooks/createOnAfterUpload';
import { createInterceptDownload } from './lib/fsHooks/createInterceptDownload';
import { createOnAfterRemove } from './lib/fsHooks/createOnAfterRemove';

const avatarsBucket = createBucket('avatars');

export const Avatars = new FilesCollection({
  debug: false, // Change to `true` for debugging
  collectionName: 'avatars',
  allowClientCode: false,
  onBeforeUpload(file) {
    if (file.size <= 72000 && file.isImage) return true;
    return 'Please upload image, with size equal or less than 72KB';
  },
  onAfterUpload: createOnAfterUpload(avatarsBucket),
  interceptDownload: createInterceptDownload(avatarsBucket),
  onAfterRemove: createOnAfterRemove(avatarsBucket),
});

function isOwner(userId, doc) {
  return userId && userId === doc.userId;
}

Avatars.allow({
  insert: isOwner,
  update: isOwner,
  remove: isOwner,
  fetch: ['userId'],
});

export default Avatars;
<|endoftext|>


<commit_before>// Polyfills
import fill from 'core-js/library/fn/array/virtual/fill';
import repeat from 'core-js/library/fn/string/virtual/repeat';

import { assertTrue, isInteger, withinRange } from './util';

/**
 * A {@link BitSet} implementation limited to 31 bits due to bits being stored in a Number type.
 *
 * @public
 * @class
 * @implements {BitSet}
 */
class BitField {
	/**
	 * The bitfields' current value.
	 *
	 * @private
	 * @member {Number}
	 */
	value = 0;

	/**
	 * The bitfields' minimum length.
	 * Example: a bitfield with a value of 110 (base 2) and a minimum length of 4 makes it so that the value is treated
	 * as 0110. Thus the flipAll method will yield 1001, instead of 001, which would be the result without pre-assigned
	 * length.
	 *
	 * @private
	 * @readonly
	 * @member {Number}
	 */
	minLength;

	/**
	 * @public
	 * @constructor
	 * @param {Number} [minLength = 1] The minimum length of the bitfield.
     * @throws {Error} In case length exceeds 31 (consider using BitArray instead if u may reach this limit).
     * @throws {Error} In case 'minLength' is equals to or smaller than zero.
	 */
	constructor(minLength) {
		assertTrue(minLength === undefined || minLength > 0, 'Illegal argument: parameter \'minLength\' must be larger than 0');

		this.minLength = minLength || 1;

		if (this.minLength > 31) {
			throw new Error('BitField is limited to 31 flags');
		}
	}

	/**
	 * Gets the integer value of a bitsetlike value or instance.
	 *
	 * @private
	 * @static
	 * @param {BitSetLike} value
	 * @returns {Number} The value.
	 */
	static valueOf(value) {
		if (typeof value === 'object') {
			return value.valueOf();
		}

		return value;
	}

	/**
	 * Combines masks. This is equivalent to a OR operation.
	 *
	 * @private
	 * @static
	 * @param {...BitSetLike} masks The masks to combine.
	 * @returns {Number} The resulting mask.
	 */
	static combineMasks(...masks) {
		return masks.reduce((prev, curr) =>
			prev | curr
		, 0);
	}

	/**
	 * Produces a new BitField instance from an array. The value may contain anything, the resulting bitfield is based
	 * on the truthiness of the value contents.
	 * Example: [true, 0, {}] will yield 101.
	 *
	 * @public
	 * @static
	 * @param {Array<*>} array
	 * @throws {Error} In case length exceeds 31 (consider using BitArray instead if u may reach this limit).
	 * @returns {BitField} A new BitField instance.
	 */
	static fromArray(array) {
		let length = 0;

		const bitMask = array.reduce((prev, curr) => {
			length++;
			prev <<= 1;

			if (curr) {
				prev++;
			}

			return prev;
		}, 0);

		return new BitField(length).on(bitMask);
	}

	get length() {
		let value = this.value;
		let length = 0;

		while (value > 0) {
			length++;
			value >>= 1;
		}

		return Math.max(this.minLength, length);
	}

	count() {
		let value = this.value;
		let count = 0;

		while (value > 0) {
			if (value & 1) {
				count++;
			}

			value >>= 1;
		}

		return count;
	}

	intersects(bitset) {
		return (this.value & BitField.valueOf(bitset)) !== 0;
	}

	get(index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		return Boolean((this.value >> index) & 1);
	}

	getRange(from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		const length = to - from;
		const mask = (1 << length) - 1;
		const bitField = new BitField(length);
		bitField.on((this.value >> from) & mask);

		return bitField;
	}

	test(...masks) {
		const mask = BitField.combineMasks(...masks);

		return (this.value & mask) === mask;
	}

	testAny(...masks) {
		const mask = BitField.combineMasks(...masks);

		return (this.value & mask) !== 0;
	}

	testAt(value, index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		return this.get(index) === Boolean(value);
	}

	testAll(value) {
		let mask = 0;

		if (value > 0) {
			mask = (value << this.length) - 1;
		}

		return this.value === mask;
	}

	on(...masks) {
		return this.set(1, ...masks);
	}

	off(...masks) {
		return this.set(0, ...masks);
	}

	set(value, ...masks) {
		const mask = BitField.combineMasks(...masks);

		if (value > 0) {
			this.value |= mask;
		} else {
			this.value &= ~mask;
		}

		return this;
	}

	setAll(value) {
		const mask = (1 << this.length) - 1;

		return this.set(value, mask);
	}

	setAt(value, index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		const mask = 1 << index;

		return this.set(value, mask);
	}

	setRange(value, from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		let mask = (1 << (to - from)) - 1;

		if (from > 0) {
			mask *= 2 * from;
		}

		return this.set(value, mask);
	}

	flip(...masks) {
		this.value ^= BitField.combineMasks(...masks);

		return this;
	}

	flipAll() {
		const mask = (1 << this.length) - 1;

		return this.flip(mask);
	}

	flipAt(index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		const mask = 1 << index;

		return this.flip(mask);
	}

	flipRange(from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		let mask = (1 << (to - from)) - 1;

		if (from > 0) {
			mask *= 2 * from;
		}

		return this.flip(mask);
	}

	copy(bitset) {
		this.value = BitField.valueOf(bitset);

		return this;
	}

	valueOf() {
		return this.value;
	}

	serialize() {
		let output = this.value.toString(2);

		if (this.minLength > output.length) {
			output = '0'::repeat(this.minLength - output.length) + output;
		}

		return output;
	}

	/**
	 * Deserializes a string and returns a new instance.
	 *
	 * @public
	 * @static
	 * @param {String} input
	 * @throws {Error} In case input could not be parsed.
	 * @returns {BitField} A new instance.
	 */
	static deserialize(input) {
		if (isNaN(Number(input))) {
			throw new Error('Failed to deserialize input');
		}

		const array = input.split('');

		return BitField.fromArray(array.map(Number));
	}

	/**
	 * Produces a new BitField instance equal to this.
	 *
	 * @public
	 * @returns {BitField} A new BitField instance.
	 */
	clone() {
		return new BitField().copy(this);
	}

	equals(other) {
		return this.value === BitField.valueOf(other);
	}

	toArray() {
		let value = this.value;
		let length = 0;
		let array = [];

		while (value > 0) {
			length++;
			array.push(Boolean(value & 1));
			value >>= 1;
		}

		if (this.minLength) {
			const filler = new Array(this.minLength - (length || 1))::fill(false);
			array = array.concat(filler);
		}

		return array.reverse();
	}

	toString() {
		return `BitField(${this.serialize()})`;
	}
}

export default BitField;
<commit_msg>fix lint issue<commit_after>// Polyfills
import fill from 'core-js/library/fn/array/virtual/fill';
import repeat from 'core-js/library/fn/string/virtual/repeat';

import { assertTrue, isInteger, withinRange } from './util';

/**
 * A {@link BitSet} implementation limited to 31 bits due to bits being stored in a Number type.
 *
 * @public
 * @class
 * @implements {BitSet}
 */
class BitField {
	/**
	 * The bitfields' current value.
	 *
	 * @private
	 * @member {Number}
	 */
	value = 0;

	/**
	 * The bitfields' minimum length.
	 * Example: a bitfield with a value of 110 (base 2) and a minimum length of 4 makes it so that the value is treated
	 * as 0110. Thus the flipAll method will yield 1001, instead of 001, which would be the result without pre-assigned
	 * length.
	 *
	 * @private
	 * @readonly
	 * @member {Number}
	 */
	minLength;

	/**
	 * @public
	 * @constructor
	 * @param {Number} [minLength = 1] The minimum length of the bitfield.
     * @throws {Error} In case length exceeds 31 (consider using BitArray instead if u may reach this limit).
     * @throws {Error} In case 'minLength' is equals to or smaller than zero.
	 */
	constructor(minLength) {
		assertTrue(minLength === undefined || minLength > 0, 'Illegal argument: parameter \'minLength\' must be larger than 0');

		this.minLength = minLength || 1;

		if (this.minLength > 31) {
			throw new Error('BitField is limited to 31 flags');
		}
	}

	/**
	 * Gets the integer value of a bitsetlike value or instance.
	 *
	 * @private
	 * @static
	 * @param {BitSetLike} value
	 * @returns {Number} The value.
	 */
	static valueOf(value) {
		if (typeof value === 'object') {
			return value.valueOf();
		}

		return value;
	}

	/**
	 * Combines masks. This is equivalent to a OR operation.
	 *
	 * @private
	 * @static
	 * @param {...BitSetLike} masks The masks to combine.
	 * @returns {Number} The resulting mask.
	 */
	static combineMasks(...masks) {
		return masks.reduce((prev, curr) => prev | curr, 0);
	}

	/**
	 * Produces a new BitField instance from an array. The value may contain anything, the resulting bitfield is based
	 * on the truthiness of the value contents.
	 * Example: [true, 0, {}] will yield 101.
	 *
	 * @public
	 * @static
	 * @param {Array<*>} array
	 * @throws {Error} In case length exceeds 31 (consider using BitArray instead if u may reach this limit).
	 * @returns {BitField} A new BitField instance.
	 */
	static fromArray(array) {
		let length = 0;

		const bitMask = array.reduce((prev, curr) => {
			length++;
			prev <<= 1;

			if (curr) {
				prev++;
			}

			return prev;
		}, 0);

		return new BitField(length).on(bitMask);
	}

	get length() {
		let value = this.value;
		let length = 0;

		while (value > 0) {
			length++;
			value >>= 1;
		}

		return Math.max(this.minLength, length);
	}

	count() {
		let value = this.value;
		let count = 0;

		while (value > 0) {
			if (value & 1) {
				count++;
			}

			value >>= 1;
		}

		return count;
	}

	intersects(bitset) {
		return (this.value & BitField.valueOf(bitset)) !== 0;
	}

	get(index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		return Boolean((this.value >> index) & 1);
	}

	getRange(from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		const length = to - from;
		const mask = (1 << length) - 1;
		const bitField = new BitField(length);
		bitField.on((this.value >> from) & mask);

		return bitField;
	}

	test(...masks) {
		const mask = BitField.combineMasks(...masks);

		return (this.value & mask) === mask;
	}

	testAny(...masks) {
		const mask = BitField.combineMasks(...masks);

		return (this.value & mask) !== 0;
	}

	testAt(value, index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		return this.get(index) === Boolean(value);
	}

	testAll(value) {
		let mask = 0;

		if (value > 0) {
			mask = (value << this.length) - 1;
		}

		return this.value === mask;
	}

	on(...masks) {
		return this.set(1, ...masks);
	}

	off(...masks) {
		return this.set(0, ...masks);
	}

	set(value, ...masks) {
		const mask = BitField.combineMasks(...masks);

		if (value > 0) {
			this.value |= mask;
		} else {
			this.value &= ~mask;
		}

		return this;
	}

	setAll(value) {
		const mask = (1 << this.length) - 1;

		return this.set(value, mask);
	}

	setAt(value, index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		const mask = 1 << index;

		return this.set(value, mask);
	}

	setRange(value, from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		let mask = (1 << (to - from)) - 1;

		if (from > 0) {
			mask *= 2 * from;
		}

		return this.set(value, mask);
	}

	flip(...masks) {
		this.value ^= BitField.combineMasks(...masks);

		return this;
	}

	flipAll() {
		const mask = (1 << this.length) - 1;

		return this.flip(mask);
	}

	flipAt(index) {
		assertTrue(isInteger(index), 'Illegal argument: parameter \'index\' is not an integer');
		assertTrue(withinRange(index, 0, 31), 'Illegal argument: parameter \'index\' is out of bounds');

		const mask = 1 << index;

		return this.flip(mask);
	}

	flipRange(from, to) {
		assertTrue(isInteger(from), 'Illegal argument: parameter \'from\' is not an integer');
		assertTrue(isInteger(to), 'Illegal argument: parameter \'to\' is not an integer');
		assertTrue(withinRange(from, 0, 31), 'Illegal argument: parameter \'from\' is out of bounds');
		assertTrue(withinRange(to, 0, 31), 'Illegal argument: parameter \'to\' is out of bounds');
		assertTrue(to > from, 'Illegal argument: parameter \'to\' must be larger than parameter \'from\'');

		let mask = (1 << (to - from)) - 1;

		if (from > 0) {
			mask *= 2 * from;
		}

		return this.flip(mask);
	}

	copy(bitset) {
		this.value = BitField.valueOf(bitset);

		return this;
	}

	valueOf() {
		return this.value;
	}

	serialize() {
		let output = this.value.toString(2);

		if (this.minLength > output.length) {
			output = '0'::repeat(this.minLength - output.length) + output;
		}

		return output;
	}

	/**
	 * Deserializes a string and returns a new instance.
	 *
	 * @public
	 * @static
	 * @param {String} input
	 * @throws {Error} In case input could not be parsed.
	 * @returns {BitField} A new instance.
	 */
	static deserialize(input) {
		if (isNaN(Number(input))) {
			throw new Error('Failed to deserialize input');
		}

		const array = input.split('');

		return BitField.fromArray(array.map(Number));
	}

	/**
	 * Produces a new BitField instance equal to this.
	 *
	 * @public
	 * @returns {BitField} A new BitField instance.
	 */
	clone() {
		return new BitField().copy(this);
	}

	equals(other) {
		return this.value === BitField.valueOf(other);
	}

	toArray() {
		let value = this.value;
		let length = 0;
		let array = [];

		while (value > 0) {
			length++;
			array.push(Boolean(value & 1));
			value >>= 1;
		}

		if (this.minLength) {
			const filler = new Array(this.minLength - (length || 1))::fill(false);
			array = array.concat(filler);
		}

		return array.reverse();
	}

	toString() {
		return `BitField(${this.serialize()})`;
	}
}

export default BitField;
<|endoftext|>


<commit_before>/**
 * DEVELOPMENT WEBPACK CONFIGURATION
 */

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;

// PostCSS plugins
const cssnext = require('postcss-cssnext');
const postcssFocus = require('postcss-focus');
const postcssReporter = require('postcss-reporter');

const plugins = [
  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
    templateContent: templateContent(), // eslint-disable-line no-use-before-define
  }),
];

module.exports = require('./webpack.base.babel')({
  // Add hot reloading in development
  entry: [
    'eventsource-polyfill', // Necessary for hot reloading with IE
    'webpack-hot-middleware/client',
    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
  ],

  // Don't use hashes in dev mode for better performance
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  // Add development plugins
  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define

  // Load the SCSS in a style tag in development
  cssLoaders: 'style-loader!css-loader?localIdentName=[local]__[path][name]__[hash:base64:5]&modules&importLoaders=1&sourceMap!postcss-loader!sass-loader',

  // Process the CSS with PostCSS
  postcssPlugins: [
    postcssFocus(), // Add a :focus to every :hover
    cssnext({ // Allow future CSS features to be used, also auto-prefixes the CSS...
      browsers: ['last 2 versions', 'IE > 10'], // ...based on this browser list
    }),
    postcssReporter({ // Posts messages from plugins to the terminal
      clearMessages: true,
    }),
  ],

  // Tell babel that we want to hot-reload
  babelQuery: {
    presets: ['react-hmre'],
  },

  // Emit a source map for easier debugging
  devtool: 'cheap-module-eval-source-map',
});

/**
 * Select which plugins to use to optimize the bundle's handling of
 * third party dependencies.
 *
 * If there is a dllPlugin key on the project's package.json, the
 * Webpack DLL Plugin will be used.  Otherwise the CommonsChunkPlugin
 * will be used.
 *
 */
function dependencyHandlers() {
  // Don't do anything during the DLL Build step
  if (process.env.BUILDING_DLL) { return []; }

  // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
  if (!dllPlugin) {
    return [
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
    ];
  }

  const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');

  /**
   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
   *
   * @see https://github.com/mxstbr/react-boilerplate/tree/master/docs/general/webpack.md
   */
  if (!dllPlugin.dlls) {
    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');

    if (!fs.existsSync(manifestPath)) {
      logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
      process.exit(0);
    }

    return [
      new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require(manifestPath), // eslint-disable-line global-require
      }),
    ];
  }

  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
  const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`));

  return dllManifests.map((manifestPath) => {
    if (!fs.existsSync(path)) {
      if (!fs.existsSync(manifestPath)) {
        logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
        logger.error(`Expected to find it in ${dllPath}`);
        logger.error('Please run: npm run build:dll');

        process.exit(0);
      }
    }

    return new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require(manifestPath), // eslint-disable-line global-require
    });
  });
}

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach(dllName => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}
<commit_msg>Fix font import<commit_after>/**
 * DEVELOPMENT WEBPACK CONFIGURATION
 */

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const argv = require('minimist')(process.argv.slice(2));

// PostCSS plugins
const cssnext = require('postcss-cssnext');
const postcssFocus = require('postcss-focus');
const postcssReporter = require('postcss-reporter');

const plugins = [
  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    favicon: 'app/favicon.ico',
    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
    templateContent: templateContent(), // eslint-disable-line no-use-before-define
  }),
];

module.exports = require('./webpack.base.babel')({
  // Add hot reloading in development
  entry: [
    'eventsource-polyfill', // Necessary for hot reloading with IE
    'webpack-hot-middleware/client',
    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
  ],

  // Don't use hashes in dev mode for better performance
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
    publicPath: `http://127.0.0.1:${argv.port || process.env.PORT || 3000}/`,
  },

  // Add development plugins
  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define

  // Load the SCSS in a style tag in development
  cssLoaders: 'style-loader!css-loader?localIdentName=[local]__[path][name]__[hash:base64:5]&modules&importLoaders=1&sourceMap!postcss-loader!sass-loader',

  // Process the CSS with PostCSS
  postcssPlugins: [
    postcssFocus(), // Add a :focus to every :hover
    cssnext({ // Allow future CSS features to be used, also auto-prefixes the CSS...
      browsers: ['last 2 versions', 'IE > 10'], // ...based on this browser list
    }),
    postcssReporter({ // Posts messages from plugins to the terminal
      clearMessages: true,
    }),
  ],

  // Tell babel that we want to hot-reload
  babelQuery: {
    presets: ['react-hmre'],
  },

  // Emit a source map for easier debugging
  devtool: 'cheap-module-eval-source-map',
});

/**
 * Select which plugins to use to optimize the bundle's handling of
 * third party dependencies.
 *
 * If there is a dllPlugin key on the project's package.json, the
 * Webpack DLL Plugin will be used.  Otherwise the CommonsChunkPlugin
 * will be used.
 *
 */
function dependencyHandlers() {
  // Don't do anything during the DLL Build step
  if (process.env.BUILDING_DLL) { return []; }

  // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
  if (!dllPlugin) {
    return [
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
    ];
  }

  const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');

  /**
   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
   *
   * @see https://github.com/mxstbr/react-boilerplate/tree/master/docs/general/webpack.md
   */
  if (!dllPlugin.dlls) {
    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');

    if (!fs.existsSync(manifestPath)) {
      logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
      process.exit(0);
    }

    return [
      new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require(manifestPath), // eslint-disable-line global-require
      }),
    ];
  }

  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
  const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`));

  return dllManifests.map((manifestPath) => {
    if (!fs.existsSync(path)) {
      if (!fs.existsSync(manifestPath)) {
        logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
        logger.error(`Expected to find it in ${dllPath}`);
        logger.error('Please run: npm run build:dll');

        process.exit(0);
      }
    }

    return new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require(manifestPath), // eslint-disable-line global-require
    });
  });
}

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach(dllName => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}
<|endoftext|>