<commit_before>/**
 * Copyright (c) 2015, Facebook, Inc.  All rights reserved.
 *
 * Facebook, Inc. ("Facebook") owns all right, title and interest, including
 * all intellectual property and other proprietary rights, in and to the React
 * Native CustomComponents software (the "Software").  Subject to your
 * compliance with these terms, you are hereby granted a non-exclusive,
 * worldwide, royalty-free copyright license to (1) use and copy the Software;
 * and (2) reproduce and distribute the Software as part of your own software
 * ("Your Software").  Facebook reserves all rights not expressly granted to
 * you in this license agreement.
 *
 * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
 * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
 * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
import React, {Animated, PixelRatio, Image, StyleSheet, Text, TouchableOpacity, View, NavigationExperimental} from "react-native";
import Actions from "./Actions";
const {
    AnimatedView: NavigationAnimatedView,
    Card: NavigationCard,
    RootContainer: NavigationRootContainer,
    Header: NavigationHeader,
    } = NavigationExperimental;

export default class NavBar extends React.Component {
    componentWillMount(){
        const state = this.props.navigationState;
        this._renderRightButton = this._renderRightButton.bind(this);
        this._renderBackButton = this._renderBackButton.bind(this);
        this._renderLeftButton = this._renderLeftButton.bind(this);
        this._renderTitle = this._renderTitle.bind(this);
    }
    render() {
        const state = this.props.navigationState;
        const child = state.children[state.index];
        let selected = state.children[state.index];
        while (selected.hasOwnProperty("children")) {
            selected = selected.children[selected.index]
        }
        if (state.navBar || selected.navBar){
            const Component =  selected.navBar || state.navBar;
            return <Component {...this.props} {...state} {...selected}/>
        }
        if (selected.component && selected.component.renderNavigationBar){
            return selected.component.renderNavigationBar({...this.props,...selected});
        }
        if (state.hideNavBar || child.hideNavBar || selected.hideNavBar){
            return null;
        }

        let renderLeftButton = selected.renderLeftButton || this._renderLeftButton;
        let renderRightButton = selected.renderRightButton || this._renderRightButton;
        let renderBackButton = selected.renderBackButton || this._renderBackButton;
        return (
            <Animated.View
                style={[styles.header, state.navigationBarStyle, selected.navigationBarStyle]}>
                {state.children.map(this._renderTitle, this)}
                {renderLeftButton(selected) || renderBackButton()}
                {renderRightButton(selected)}
            </Animated.View>
        );
    }

    _renderBackButton() {
        const drawer = this.context.drawer;
        const state = this.props.navigationState;
        const childState = state.children[state.index];
        let buttonImage = state.backButtonImage || require("./back_chevron.png");
        let onPress = Actions.pop;

        if (state.index === 0) {
            if (!!drawer && typeof drawer.toggle === "function") {
                buttonImage = state.drawerImage || require("./menu_burger.png");
                onPress = drawer.toggle;
            } else {
                return null;
            }
        }

        let text = childState.backTitle ? <Text style={[styles.barBackButtonText, childState.backButtonTextStyle]}>
            {childState.backTitle}
        </Text> : null;

        return (
            <TouchableOpacity style={[styles.backButton, state.leftButtonStyle]} onPress={onPress}>
                <Image source={buttonImage} style={[styles.backButtonImage, state.barButtonIconStyle]}/>
                {text}
            </TouchableOpacity>
        );
    }

    _renderRightButton() {
        function tryRender(state) {
            if (state.onRight && state.rightTitle) {
                return (
                    <TouchableOpacity style={[styles.rightButton, state.rightButtonStyle]}
                                      onPress={state.onRight.bind(null, state)}>
                        <Text style={[styles.barRightButtonText, state.rightButtonTextStyle]}>{state.rightTitle}</Text>
                    </TouchableOpacity>
                );
            }
            if ((!!state.onRight ^ !!state.rightTitle)) {
                console.warn('Both onRight and rightTitle must be specified for the scene: ' + state.name)
            }
        }
        const state = this.props.navigationState;
        return tryRender(state) || tryRender(state.children[state.index]);
    }

    _renderLeftButton() {
        function tryRender(state) {
            if (state.onLeft && state.leftTitle){
                return (
                    <TouchableOpacity style={[styles.leftButton, state.leftButtonStyle]} onPress={state.onLeft.bind(null, state)}>
                        <Text style={[styles.barLeftButtonText, state.leftButtonTextStyle]}>{state.leftTitle}</Text>
                    </TouchableOpacity>
                );
            }
            if ((!!state.onLeft ^ !!state.leftTitle)) {
                console.warn('Both onLeft and leftTitle must be specified for the scene: ' + state.name)
            }
        }
        const state = this.props.navigationState;
        return tryRender(state) || tryRender(state.children[state.index]);
    }

    _renderTitle(childState: NavigationState, index:number) {
        const title = childState.renderTitle ?
          childState.renderTitle():this.props.getTitle ? this.props.getTitle(childState) : childState.title;
        return (
            <Animated.Text
                key={childState.key}
                style={[
          styles.title, this.props.navigationState.titleStyle, childState.titleStyle,
          {
            opacity: this.props.position.interpolate({
              inputRange: [index - 1, index, index + 1],
              outputRange: [0, 1, 0],
            }),
            left: this.props.position.interpolate({
              inputRange: [index - 1, index + 1],
              outputRange: [200, -200],
            }),
            right: this.props.position.interpolate({
              inputRange: [index - 1, index + 1],
              outputRange: [-200, 200],
            }),
          },
        ]}>
                {title}
            </Animated.Text>
        );
    }

}

NavBar.contextTypes = {
  drawer: React.PropTypes.object
}

const styles = StyleSheet.create({
    title: {
        textAlign: "center",
        marginTop: 10,
        fontSize: 18,
        fontWeight: "500",
        color: "#0A0A0A",
        position: "absolute",
        top: 20,
        left: 0,
        right: 0,
    },
    header: {
        backgroundColor: "#EFEFF2",
        paddingTop: 20,
        top: 0,
        height: 64,
        right: 0,
        left: 0,
        borderBottomWidth: 0.5,
        borderBottomColor: "#828287",
        position: "absolute",
    },
    backButton: {
        width: 130,
        height: 37,
        position: "absolute",
        bottom: 4,
        left: 2,
        padding: 8,
        flexDirection: "row",
    },
    rightButton: {
        width: 100,
        height: 37,
        position: "absolute",
        bottom: 4,
        right: 2,
        padding: 8,
    },
    leftButton: {
        width: 100,
        height: 37,
        position: "absolute",
        bottom: 4,
        left: 2,
        padding: 8,
    },
    barRightButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "right",
        fontSize: 17,
    },
    barBackButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "left",
        fontSize: 17,
        paddingLeft: 6,
    },
    barLeftButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "left",
        fontSize: 17,
    },
    backButtonImage: {
        width: 13,
        height: 21,
    },
});
<commit_msg>add selected to renderBackButton as well<commit_after>/**
 * Copyright (c) 2015, Facebook, Inc.  All rights reserved.
 *
 * Facebook, Inc. ("Facebook") owns all right, title and interest, including
 * all intellectual property and other proprietary rights, in and to the React
 * Native CustomComponents software (the "Software").  Subject to your
 * compliance with these terms, you are hereby granted a non-exclusive,
 * worldwide, royalty-free copyright license to (1) use and copy the Software;
 * and (2) reproduce and distribute the Software as part of your own software
 * ("Your Software").  Facebook reserves all rights not expressly granted to
 * you in this license agreement.
 *
 * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
 * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
 * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
import React, {Animated, PixelRatio, Image, StyleSheet, Text, TouchableOpacity, View, NavigationExperimental} from "react-native";
import Actions from "./Actions";
const {
    AnimatedView: NavigationAnimatedView,
    Card: NavigationCard,
    RootContainer: NavigationRootContainer,
    Header: NavigationHeader,
    } = NavigationExperimental;

export default class NavBar extends React.Component {
    componentWillMount(){
        const state = this.props.navigationState;
        this._renderRightButton = this._renderRightButton.bind(this);
        this._renderBackButton = this._renderBackButton.bind(this);
        this._renderLeftButton = this._renderLeftButton.bind(this);
        this._renderTitle = this._renderTitle.bind(this);
    }
    render() {
        const state = this.props.navigationState;
        const child = state.children[state.index];
        let selected = state.children[state.index];
        while (selected.hasOwnProperty("children")) {
            selected = selected.children[selected.index]
        }
        if (state.navBar || selected.navBar){
            const Component =  selected.navBar || state.navBar;
            return <Component {...this.props} {...state} {...selected}/>
        }
        if (selected.component && selected.component.renderNavigationBar){
            return selected.component.renderNavigationBar({...this.props,...selected});
        }
        if (state.hideNavBar || child.hideNavBar || selected.hideNavBar){
            return null;
        }

        let renderLeftButton = selected.renderLeftButton || this._renderLeftButton;
        let renderRightButton = selected.renderRightButton || this._renderRightButton;
        let renderBackButton = selected.renderBackButton || this._renderBackButton;
        return (
            <Animated.View
                style={[styles.header, state.navigationBarStyle, selected.navigationBarStyle]}>
                {state.children.map(this._renderTitle, this)}
                {renderLeftButton(selected) || renderBackButton(selected)}
                {renderRightButton(selected)}
            </Animated.View>
        );
    }

    _renderBackButton() {
        const drawer = this.context.drawer;
        const state = this.props.navigationState;
        const childState = state.children[state.index];
        let buttonImage = state.backButtonImage || require("./back_chevron.png");
        let onPress = Actions.pop;

        if (state.index === 0) {
            if (!!drawer && typeof drawer.toggle === "function") {
                buttonImage = state.drawerImage || require("./menu_burger.png");
                onPress = drawer.toggle;
            } else {
                return null;
            }
        }

        let text = childState.backTitle ? <Text style={[styles.barBackButtonText, childState.backButtonTextStyle]}>
            {childState.backTitle}
        </Text> : null;

        return (
            <TouchableOpacity style={[styles.backButton, state.leftButtonStyle]} onPress={onPress}>
                <Image source={buttonImage} style={[styles.backButtonImage, state.barButtonIconStyle]}/>
                {text}
            </TouchableOpacity>
        );
    }

    _renderRightButton() {
        function tryRender(state) {
            if (state.onRight && state.rightTitle) {
                return (
                    <TouchableOpacity style={[styles.rightButton, state.rightButtonStyle]}
                                      onPress={state.onRight.bind(null, state)}>
                        <Text style={[styles.barRightButtonText, state.rightButtonTextStyle]}>{state.rightTitle}</Text>
                    </TouchableOpacity>
                );
            }
            if ((!!state.onRight ^ !!state.rightTitle)) {
                console.warn('Both onRight and rightTitle must be specified for the scene: ' + state.name)
            }
        }
        const state = this.props.navigationState;
        return tryRender(state) || tryRender(state.children[state.index]);
    }

    _renderLeftButton() {
        function tryRender(state) {
            if (state.onLeft && state.leftTitle){
                return (
                    <TouchableOpacity style={[styles.leftButton, state.leftButtonStyle]} onPress={state.onLeft.bind(null, state)}>
                        <Text style={[styles.barLeftButtonText, state.leftButtonTextStyle]}>{state.leftTitle}</Text>
                    </TouchableOpacity>
                );
            }
            if ((!!state.onLeft ^ !!state.leftTitle)) {
                console.warn('Both onLeft and leftTitle must be specified for the scene: ' + state.name)
            }
        }
        const state = this.props.navigationState;
        return tryRender(state) || tryRender(state.children[state.index]);
    }

    _renderTitle(childState: NavigationState, index:number) {
        const title = childState.renderTitle ?
          childState.renderTitle():this.props.getTitle ? this.props.getTitle(childState) : childState.title;
        return (
            <Animated.Text
                key={childState.key}
                style={[
          styles.title, this.props.navigationState.titleStyle, childState.titleStyle,
          {
            opacity: this.props.position.interpolate({
              inputRange: [index - 1, index, index + 1],
              outputRange: [0, 1, 0],
            }),
            left: this.props.position.interpolate({
              inputRange: [index - 1, index + 1],
              outputRange: [200, -200],
            }),
            right: this.props.position.interpolate({
              inputRange: [index - 1, index + 1],
              outputRange: [-200, 200],
            }),
          },
        ]}>
                {title}
            </Animated.Text>
        );
    }

}

NavBar.contextTypes = {
  drawer: React.PropTypes.object
}

const styles = StyleSheet.create({
    title: {
        textAlign: "center",
        marginTop: 10,
        fontSize: 18,
        fontWeight: "500",
        color: "#0A0A0A",
        position: "absolute",
        top: 20,
        left: 0,
        right: 0,
    },
    header: {
        backgroundColor: "#EFEFF2",
        paddingTop: 20,
        top: 0,
        height: 64,
        right: 0,
        left: 0,
        borderBottomWidth: 0.5,
        borderBottomColor: "#828287",
        position: "absolute",
    },
    backButton: {
        width: 130,
        height: 37,
        position: "absolute",
        bottom: 4,
        left: 2,
        padding: 8,
        flexDirection: "row",
    },
    rightButton: {
        width: 100,
        height: 37,
        position: "absolute",
        bottom: 4,
        right: 2,
        padding: 8,
    },
    leftButton: {
        width: 100,
        height: 37,
        position: "absolute",
        bottom: 4,
        left: 2,
        padding: 8,
    },
    barRightButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "right",
        fontSize: 17,
    },
    barBackButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "left",
        fontSize: 17,
        paddingLeft: 6,
    },
    barLeftButtonText: {
        color: 'rgb(0, 122, 255)',
        textAlign: "left",
        fontSize: 17,
    },
    backButtonImage: {
        width: 13,
        height: 21,
    },
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import cx from 'classnames';
import Col from './Col';
import Icon from './Icon';

class Navbar extends Component {
  constructor (props) {
    super(props);
    this.renderSideNav = this.renderSideNav.bind(this);
  }

  componentDidMount () {
    if ($ !== undefined) {
      $('.button-collapse').sideNav();
    }
  }

  renderSideNav () {
    return (

        {this.props.children}

    );
  }

  render () {
    const {
      brand,
      className,
      left,
      right,
      href,
      ...other
    } = this.props;

    let classes = {
      right: right,
      'hide-on-med-and-down': true
    };

    let brandClasses = {
      'brand-logo': true,
      right: left
    };

    return (

          <Col s={12}>
            {brand}

              {this.props.children}

            {this.renderSideNav()}

              <Icon>view_headline</Icon>

          </Col>

    );
  }
}

Navbar.propTypes = {
  brand: PropTypes.node,
  children: PropTypes.node,
  className: PropTypes.string,
  left: PropTypes.bool,
  right: PropTypes.bool,
  href: PropTypes.string
};

Navbar.defaultProps = {
  href: '/'
};

export default Navbar;
<commit_msg>Fix condition in `componentDidMount` for `Navbar` component (#224)<commit_after>import React, { Component, PropTypes } from 'react';
import cx from 'classnames';
import Col from './Col';
import Icon from './Icon';

class Navbar extends Component {
  constructor (props) {
    super(props);
    this.renderSideNav = this.renderSideNav.bind(this);
  }

  componentDidMount () {
    if (typeof $ !== 'undefined') {
      $('.button-collapse').sideNav();
    }
  }

  renderSideNav () {
    return (

        {this.props.children}

    );
  }

  render () {
    const {
      brand,
      className,
      left,
      right,
      href,
      ...other
    } = this.props;

    let classes = {
      right: right,
      'hide-on-med-and-down': true
    };

    let brandClasses = {
      'brand-logo': true,
      right: left
    };

    return (

          <Col s={12}>
            {brand}

              {this.props.children}

            {this.renderSideNav()}

              <Icon>view_headline</Icon>

          </Col>

    );
  }
}

Navbar.propTypes = {
  brand: PropTypes.node,
  children: PropTypes.node,
  className: PropTypes.string,
  left: PropTypes.bool,
  right: PropTypes.bool,
  href: PropTypes.string
};

Navbar.defaultProps = {
  href: '/'
};

export default Navbar;
<|endoftext|>


<commit_before>import chalk from "chalk";
import outdent from "outdent";
import execa from "execa";
import semver from "semver";
import {
  getBlogPostInfo,
  getChangelogContent,
  logPromise,
  waitForEnter,
} from "../utils.js";

const outdentString = outdent.string;

/**
 * Retry "npm publish" when to enter OTP is failed.
 */
async function retryNpmPublish() {
  const runNpmPublish = () =>
    execa("npm", ["publish"], {
      cwd: "./dist",
      stdio: "inherit", // we need to input OTP if 2FA enabled
    });
  for (let i = 5; i > 0; i--) {
    try {
      return await runNpmPublish();
    } catch (error) {
      if (error.code === "EOTP" && i > 0) {
        console.log(`To enter OTP is failed, you can retry it ${i} times.`);
        continue;
      }
      throw error;
    }
  }
}

export function getReleaseUrl(version, previousVersion) {
  const semverDiff = semver.diff(version, previousVersion);
  const isPatch = semverDiff === "patch";
  let body;
  if (isPatch) {
    const urlToChangelog =
      "https://github.com/prettier/prettier/blob/main/CHANGELOG.md#" +
      version.split(".").join("");
    body = `🔗 [Changelog](${urlToChangelog})`;
  } else {
    const blogPostInfo = getBlogPostInfo(version);
    body = getChangelogContent({
      version,
      previousVersion,
      body: `🔗 [Release note](https://prettier.io/${blogPostInfo.path})`,
    });
  }
  body = encodeURIComponent(body);
  return `https://github.com/prettier/prettier/releases/new?tag=${version}&title=${version}&body=${body}`;
}

export default async function publishToNpm({ dry, version, previousVersion }) {
  if (dry) {
    return;
  }

  await logPromise("Publishing to npm", retryNpmPublish());

  const releaseUrl = getReleaseUrl(version, previousVersion);

  console.log(
    outdentString(chalk`
      {green.bold Prettier ${version} published!}

      {yellow.bold Some manual steps are necessary.}

      {bold.underline Create a GitHub Release}
      - Go to {cyan.underline ${releaseUrl}}
      - Copy release notes from {yellow CHANGELOG.md}
      - Press {bgGreen.black  Publish release }

      {bold.underline Test the new release}
      - In a new session, run {yellow npm i prettier@latest} in another directory
      - Test the API and CLI

      After that, we can proceed to bump this repo's Prettier dependency.
      Press ENTER to continue.
    `)
  );
  await waitForEnter();
}
<commit_msg>Remove sentence for copying from CHANGELOG (#11530)<commit_after>import chalk from "chalk";
import outdent from "outdent";
import execa from "execa";
import semver from "semver";
import {
  getBlogPostInfo,
  getChangelogContent,
  logPromise,
  waitForEnter,
} from "../utils.js";

const outdentString = outdent.string;

/**
 * Retry "npm publish" when to enter OTP is failed.
 */
async function retryNpmPublish() {
  const runNpmPublish = () =>
    execa("npm", ["publish"], {
      cwd: "./dist",
      stdio: "inherit", // we need to input OTP if 2FA enabled
    });
  for (let i = 5; i > 0; i--) {
    try {
      return await runNpmPublish();
    } catch (error) {
      if (error.code === "EOTP" && i > 0) {
        console.log(`To enter OTP is failed, you can retry it ${i} times.`);
        continue;
      }
      throw error;
    }
  }
}

export function getReleaseUrl(version, previousVersion) {
  const semverDiff = semver.diff(version, previousVersion);
  const isPatch = semverDiff === "patch";
  let body;
  if (isPatch) {
    const urlToChangelog =
      "https://github.com/prettier/prettier/blob/main/CHANGELOG.md#" +
      version.split(".").join("");
    body = `🔗 [Changelog](${urlToChangelog})`;
  } else {
    const blogPostInfo = getBlogPostInfo(version);
    body = getChangelogContent({
      version,
      previousVersion,
      body: `🔗 [Release note](https://prettier.io/${blogPostInfo.path})`,
    });
  }
  body = encodeURIComponent(body);
  return `https://github.com/prettier/prettier/releases/new?tag=${version}&title=${version}&body=${body}`;
}

export default async function publishToNpm({ dry, version, previousVersion }) {
  if (dry) {
    return;
  }

  await logPromise("Publishing to npm", retryNpmPublish());

  const releaseUrl = getReleaseUrl(version, previousVersion);

  console.log(
    outdentString(chalk`
      {green.bold Prettier ${version} published!}

      {yellow.bold Some manual steps are necessary.}

      {bold.underline Create a GitHub Release}
      - Go to {cyan.underline ${releaseUrl}}
      - Press {bgGreen.black  Publish release }

      {bold.underline Test the new release}
      - In a new session, run {yellow npm i prettier@latest} in another directory
      - Test the API and CLI

      After that, we can proceed to bump this repo's Prettier dependency.
      Press ENTER to continue.
    `)
  );
  await waitForEnter();
}
<|endoftext|>


<commit_before>import { createHistory, createMemoryHistory } from 'history';

let history;
if (typeof document !== 'undefined') {
  history = createHistory();
} else {
  history = createMemoryHistory();
}

export default history;
<commit_msg>Removed unused RouteHistory.<commit_after><|endoftext|>


<commit_before>// Load in dependencies
var EventEmitter = require('events').EventEmitter;
var _ = require('underscore');

// Define our bookmark parser
function BookmarkCollection(bookmarks, options) {
  // Inherit from EventEmitter
  EventEmitter.call(this);

  // Fallback options
  options = options || {};

  // Parse now
  var bookmarksArr = BookmarkCollection.parse(bookmarks, options);
  this.bookmarksArr = bookmarksArr;

  // Save options for later
  this.options = options;
}

// Extend from EventEmitter
BookmarkCollection.parse = function (bookmarks, options) {
  // Denote the root of the bookmarks
  var bookmarksRoot = bookmarks;

  // Find the first child which contains all our bookmarks
  var whitelistedFolders = options.folders;
  var rootChildren = bookmarksRoot.children;
  var bookmarkMenu = rootChildren.filter(function (container) {
    // TODO: Consider container.root === 'bookmarksMenuFolder'
    return container.title === 'Bookmarks Menu';
  })[0];
  var bookmarkFolders = bookmarkMenu.children;
  var approvedFolders = bookmarkFolders;
  if (whitelistedFolders) {
    // TODO: It is possible for there to be bookmarks in the menu itself...
    approvedFolders = bookmarkFolders.filter(function (folder) {
      return whitelistedFolders.indexOf(folder.title) !== -1;
    });
  }

  // Format content
  function parseFolder(folder) {
    var children = folder.children || [];
    return {
      type: 'folder',
      title: folder.title,
      children: children.map(parseBookmark)
    };
  }
  function parseBookmark(bookmark) {
    // Find the proper description
    var annos = bookmark.annos || [];
    var descriptionNode = annos.filter(function (anno) {
      return anno.name === 'bookmarkProperties/description';
    })[0] || {};
    var description = descriptionNode.value || bookmark.title;

    // Grab the title and bookmark
    var title = bookmark.title;
    var uri = bookmark.uri;

    // If the uri is not defined, add the bookmark as a folder
    if (uri === undefined) {
      return parseFolder(bookmark);
    }

    // Create and return the object
    return {
      type: 'bookmark',
      title: title,
      dateAdded: bookmark.dateAdded,
      lastModified: bookmark.lastModified,
      description: description,
      uri: uri
    };
  }

  // Map and return the approved folders
  var retArr = approvedFolders.map(parseFolder);
  return retArr;
};

BookmarkCollection.prototype = _.extend({
  toArray: function () {
    return this.bookmarksArr;
  }
}, EventEmitter.prototype);

// TODO: Delete me into cli folder
// Create sugar fn for parsing bookmarks
function parseBookmarks(bookmarks, options) {
  // Generate a new collection
  var collection = new BookmarkCollection(bookmarks, options);

  // Return the bookmarks as an array
  return collection.toArray();
}

// Expose the BookmarkCollection via parseBookmarks
parseBookmarks.BookmarkCollection = BookmarkCollection;

// Expose parseBookmarks
module.exports = parseBookmarks;<commit_msg>Outlining flatten method<commit_after>// Load in dependencies
var EventEmitter = require('events').EventEmitter;
var _ = require('underscore');

// Define our bookmark parser
function BookmarkCollection(rawBookmarks, options) {
  // Inherit from EventEmitter
  EventEmitter.call(this);

  // Fallback options
  options = options || {};

  // Parse now
  var bookmarks = BookmarkCollection.parse(rawBookmarks, options);
  this.bookmarks = bookmarks;

  // Save options for later
  this.options = options;
}

// Extend from EventEmitter
BookmarkCollection.parse = function (rawBookmarks, options) {
  // Denote the root of the bookmarks
  var bookmarksRoot = rawBookmarks;

  // Find the first child which contains all our bookmarks
  var whitelistedFolders = options.folders;
  var rootChildren = bookmarksRoot.children;
  var bookmarkMenu = rootChildren.filter(function (container) {
    // TODO: Consider container.root === 'bookmarksMenuFolder'
    return container.title === 'Bookmarks Menu';
  })[0];
  var bookmarkFolders = bookmarkMenu.children;
  var approvedFolders = bookmarkFolders;
  if (whitelistedFolders) {
    // TODO: It is possible for there to be bookmarks in the menu itself...
    approvedFolders = bookmarkFolders.filter(function (folder) {
      return whitelistedFolders.indexOf(folder.title) !== -1;
    });
  }

  // Format content
  function parseFolder(folder) {
    var children = folder.children || [];
    return {
      type: 'folder',
      title: folder.title,
      children: children.map(parseBookmark)
    };
  }
  function parseBookmark(bookmark) {
    // Find the proper description
    var annos = bookmark.annos || [];
    var descriptionNode = annos.filter(function (anno) {
      return anno.name === 'bookmarkProperties/description';
    })[0] || {};
    var description = descriptionNode.value || bookmark.title;

    // Grab the title and bookmark
    var title = bookmark.title;
    var uri = bookmark.uri;

    // If the uri is not defined, add the bookmark as a folder
    if (uri === undefined) {
      return parseFolder(bookmark);
    }

    // Create and return the object
    return {
      type: 'bookmark',
      title: title,
      dateAdded: bookmark.dateAdded,
      lastModified: bookmark.lastModified,
      description: description,
      uri: uri
    };
  }

  // Map and return the approved folders
  var retArr = approvedFolders.map(parseFolder);
  return retArr;
};

BookmarkCollection.prototype = _.defaults({
  toArray: function () {
    return this.bookmarks;
  },
  flatten: function () {
    // Flatten the structure via underscore

    // Filter out non-bookmarks

    // Remove unnecessary `type`

    // Return data
  }
}, EventEmitter.prototype);

// TODO: Delete me into cli folder
// Create sugar fn for parsing bookmarks
function parseBookmarks(bookmarks, options) {
  // Generate a new collection
  var collection = new BookmarkCollection(bookmarks, options);

  // Return the bookmarks as an array
  return collection.toArray();
}

// Expose the BookmarkCollection via parseBookmarks
parseBookmarks.BookmarkCollection = BookmarkCollection;

// Expose parseBookmarks
module.exports = parseBookmarks;<|endoftext|>


<commit_before>'use strict'

/**
 * adonis-framework
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
*/

const CatLog = require('cat-log')
const helpers = require('./helpers')
const http = require('http')
const NE = require('node-exceptions')

/**
 * Http server for adonis framework
 * @class
 */
class Server {

  constructor (Request, Response, Route, Helpers, Middleware, Static, Session, Config) {
    this.Request = Request
    this.Response = Response
    this.Session = Session
    this.Route = Route
    this.middleware = Middleware
    this.static = Static
    this.helpers = Helpers
    this.config = Config
    this.log = new CatLog('adonis:framework')
  }

  /**
   * responds to request by finding registered
   * route or fallbacks to static resource.
   *
   * @param  {Object}      request  [description]
   * @param  {Object}      response [description]
   * @return {void}               [description]
   *
   * @private
   */
  _finalHandler (resolvedRoute, request, response) {
    if (!resolvedRoute.handler) {
      throw new NE.HttpException(`Route not found ${request.url()}`, 404)
    }

    helpers.callRouteAction(
      resolvedRoute,
      request,
      response,
      this.middleware,
      this.helpers.appNameSpace()
    )
  }

  /**
   * serves static resource using static server
   *
   * @param  {Object}       request  [description]
   * @param  {Object}       response [description]
   * @return {Promise}                [description]
   *
   * @private
   */
  _staticHandler (request, response) {
    return this.static.serve(request.request, request.response)
  }

  /**
   * request handler to respond to a given http request
   *
   * @param  {Object} req
   * @param  {Object} res
   *
   * @example
   * http
   *   .createServer(Server.handle.bind(Server))
   *   .listen(3333)
   *
   * @public
   */
  handle (req, res) {
    const self = this
    const request = new this.Request(req, res, this.config)
    const response = new this.Response(request, res)
    const session = new this.Session(req, res)
    const requestUrl = request.url()
    request.session = session
    this.log.verbose('request on url %s ', req.url)

    /**
     * making request verb/method based upon _method or falling
     * back to original method
     * @type {String}
     */
    const method = request.input('_method', request.method()).toUpperCase()
    const resolvedRoute = this.Route.resolve(requestUrl, method, request.hostname())
    request._params = resolvedRoute.params

    const finalHandler = function * () {
      self._finalHandler(resolvedRoute, request, response)
    }

    /**
     * do not serve static resources when request method is not
     * GET or HEAD
     */
    if (method !== 'GET' && method !== 'HEAD') {
      helpers.respondRequest(this.middleware, request, response, finalHandler)
      return
    }

    this._staticHandler(request, response)
    .catch((e) => {
      if (e.status === 404) {
        helpers.respondRequest(this.middleware, request, response, finalHandler)
        return
      }
      helpers.handleRequestError(e, request, response)
    })
  }

  /**
   * starting a server on a given port and host
   *
   * @param {String} host
   * @param {String} port
   *
   * @example
   * Server.listen('localhost', 3333)
   *
   * @public
   */
  listen (host, port) {
    this.log.info('serving app on %s:%s', host, port)
    http.createServer(this.handle.bind(this)).listen(port, host)
  }

}

module.exports = Server
<commit_msg>feat(server): add support to disable _method spoofing<commit_after>'use strict'

/**
 * adonis-framework
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
*/

const CatLog = require('cat-log')
const helpers = require('./helpers')
const http = require('http')
const NE = require('node-exceptions')

/**
 * Http server for adonis framework
 * @class
 */
class Server {

  constructor (Request, Response, Route, Helpers, Middleware, Static, Session, Config) {
    this.Request = Request
    this.Response = Response
    this.Session = Session
    this.Route = Route
    this.middleware = Middleware
    this.static = Static
    this.helpers = Helpers
    this.config = Config
    this.log = new CatLog('adonis:framework')
  }

  /**
   * responds to request by finding registered
   * route or fallbacks to static resource.
   *
   * @param  {Object}      request
   * @param  {Object}      response
   * @return {void}
   *
   * @private
   */
  _finalHandler (resolvedRoute, request, response) {
    if (!resolvedRoute.handler) {
      throw new NE.HttpException(`Route not found ${request.url()}`, 404)
    }

    helpers.callRouteAction(
      resolvedRoute,
      request,
      response,
      this.middleware,
      this.helpers.appNameSpace()
    )
  }

  /**
   * serves static resource using static server
   *
   * @param  {Object}       request
   * @param  {Object}       response
   * @return {Promise}
   *
   * @private
   */
  _staticHandler (request, response) {
    return this.static.serve(request.request, request.response)
  }

  /**
   * returns request method by spoofing the _method only
   * if allowed by the applicatin
   *
   * @param  {Object}          request
   * @return {String}
   *
   * @private
   */
  _getRequestMethod (request) {
    if (!this.config.get('app.http.allowMethodSpoofing')) {
      return request.method().toUpperCase()
    }
    return request.input('_method', request.method()).toUpperCase()
  }

  /**
   * request handler to respond to a given http request
   *
   * @param  {Object} req
   * @param  {Object} res
   *
   * @example
   * http
   *   .createServer(Server.handle.bind(Server))
   *   .listen(3333)
   *
   * @public
   */
  handle (req, res) {
    const self = this
    const request = new this.Request(req, res, this.config)
    const response = new this.Response(request, res)
    const session = new this.Session(req, res)
    const requestUrl = request.url()
    request.session = session
    this.log.verbose('request on url %s ', req.url)

    /**
     * making request verb/method based upon _method or falling
     * back to original method
     * @type {String}
     */
    const method = this._getRequestMethod(request)
    const resolvedRoute = this.Route.resolve(requestUrl, method, request.hostname())
    request._params = resolvedRoute.params

    const finalHandler = function * () {
      self._finalHandler(resolvedRoute, request, response)
    }

    /**
     * do not serve static resources when request method is not
     * GET or HEAD
     */
    if (method !== 'GET' && method !== 'HEAD') {
      helpers.respondRequest(this.middleware, request, response, finalHandler)
      return
    }

    this._staticHandler(request, response)
    .catch((e) => {
      if (e.status === 404) {
        helpers.respondRequest(this.middleware, request, response, finalHandler)
        return
      }
      helpers.handleRequestError(e, request, response)
    })
  }

  /**
   * starting a server on a given port and host
   *
   * @param {String} host
   * @param {String} port
   *
   * @example
   * Server.listen('localhost', 3333)
   *
   * @public
   */
  listen (host, port) {
    this.log.info('serving app on %s:%s', host, port)
    http.createServer(this.handle.bind(this)).listen(port, host)
  }

}

module.exports = Server
<|endoftext|>


<commit_before>"use strict";

/*global nodeca, _*/

var UserGroup = nodeca.models.users.UserGroup;

var usergroup_schema = nodeca.config.setting_schemas['usergroup'];

// Validate input parameters
//
var params_schema = {
  short_name: {
    type: 'string',
    required: true
  },
  parent: {
    type: 'string',
    default: null
  }
};

// Add usergroup settings as input params to validate schema
//
_.keys(usergroup_schema).forEach(function(name) {
  var item_type = usergroup_schema[name]['type'];
  // FIXME Implement complex types
  if (!_.any(['string', 'number', 'boolean'],
      function(t){ return t === item_type; })) {
    item_type = 'string';
  }
  params_schema[name] = { type: item_type };
});
nodeca.validate(params_schema);

/**
 * admin.usergroups.create(params, callback) -> Void
 *
 *
 * Create new usergroup
 *
 **/
module.exports = function (params, next) {
  var env = this;
  var usergroup;

  var raw_settings = _.clone(params);

  // remove short_name and parent group from settings set
  delete raw_settings['short_name'];
  delete raw_settings['parent'];

  // Check if group already exists
  UserGroup.findOne({ short_name: params.short_name }).exec(function(err, group) {
    if (err) {
      next(err);
      return;
    }

    // group already exists
    if (group) {
      next({
        code: nodeca.io.BAD_REQUEST,
        data: {
          short_name: env.helpers.t('admin.usergroups.form.error.short_name_busy')
        }
      });
      return;
    }

    // set default values
    _.keys(usergroup_schema).forEach(function(key) {
      if (_.isNull(raw_settings[key])) {
        raw_settings[key] = usergroup_schema[key]['default'];
      }
      // FIXME eval before_save code
    });

    usergroup = new UserGroup({
      short_name: params.short_name,
      parent: params.parent,
      raw_settings: raw_settings
    });

    usergroup.save(function(err){
      if (err) {
        next(err);
        return;
      }
      // FIXME calculate and save settings in store
      next();
    });
  });
};
<commit_msg>Fixed create usergroup without parent<commit_after>"use strict";

/*global nodeca, _*/

var UserGroup = nodeca.models.users.UserGroup;

var usergroup_schema = nodeca.config.setting_schemas['usergroup'];

// Validate input parameters
//
var params_schema = {
  short_name: {
    type: 'string',
    required: true
  },
  parent: {
    type: 'string',
    default: null
  }
};

// Add usergroup settings as input params to validate schema
//
_.keys(usergroup_schema).forEach(function(name) {
  var item_type = usergroup_schema[name]['type'];
  // FIXME Implement complex types
  if (!_.any(['string', 'number', 'boolean'],
      function(t){ return t === item_type; })) {
    item_type = 'string';
  }
  params_schema[name] = { type: item_type };
});
nodeca.validate(params_schema);

/**
 * admin.usergroups.create(params, callback) -> Void
 *
 *
 * Create new usergroup
 *
 **/
module.exports = function (params, next) {
  var env = this;
  var usergroup;

  var raw_settings = _.clone(params);

  // remove short_name and parent group from settings set
  delete raw_settings['short_name'];
  delete raw_settings['parent'];

  // Check if group already exists
  UserGroup.findOne({ short_name: params.short_name }).exec(function(err, group) {
    if (err) {
      next(err);
      return;
    }

    // group already exists
    if (group) {
      next({
        code: nodeca.io.BAD_REQUEST,
        data: {
          short_name: env.helpers.t('admin.usergroups.form.error.short_name_busy')
        }
      });
      return;
    }

    // set default values
    _.keys(usergroup_schema).forEach(function(key) {
      if (_.isNull(raw_settings[key])) {
        raw_settings[key] = usergroup_schema[key]['default'];
      }
      // FIXME eval before_save code
    });

    usergroup = new UserGroup({
      short_name: params.short_name,
      raw_settings: raw_settings
    });
    if (!_.isEmpty(params.parent)) {
      usergroup.parent = params.parent;
    }

    usergroup.save(function(err){
      if (err) {
        next(err);
        return;
      }
      // FIXME calculate and save settings in store
      next();
    });
  });
};
<|endoftext|>


<commit_before>/**
 * Control constructor
 *
 * @class Roguelike.Group
 * @classdesc The object that holds multiple entities and is able to search them
 */
Roguelike.Group = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

	/**
	 * @property {array} entities - Collection of all the entities in this group
	 */
	this.entities = [];

};

Roguelike.Group.prototype = {

	/**
	 * Function to add a new entity to this group
	 * @protected
	 */
	addEntity: function(entity) {

		//Check if the entity is the correct object
		if(typeof entity !== "Roguelike.Entity") {
			return;
		}

		//Add the current entity to the list
		this.entities.push(entity);

	},

	/**
	 * Function to remove an entity from this group
	 * @protected
	 */
	removeEntity: function(entity) {

		//Check if the entity exists
		if(this.entities) {
			return;
		}

		//Add the current entity to the list
		this.entities.push(entity);

	}

};
<commit_msg>It's now possible to add entities and remove entities from a group!<commit_after>/**
 * Control constructor
 *
 * @class Roguelike.Group
 * @classdesc The object that holds multiple entities and is able to search them
 *
 * @param {Roguelike.Game} game - A reference to the current game object
 */
Roguelike.Group = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

	/**
	 * @property {array} entities - Collection of all the entities in this group
	 */
	this.entities = [];

};

Roguelike.Group.prototype = {

	/**
	 * Function to add a new entity to this group
	 * @protected
	 */
	addEntity: function(entity) {

		//Check if the entity is the correct object
		if(!entity instanceof Roguelike.Entity) {
			return;
		}

		//Add the current entity to the list
		this.entities.push(entity);

	},

	/**
	 * Function to remove an entity from this group
	 * @protected
	 */
	removeEntity: function(entity) {

		//Check if the entity exists, if not, we don't have to delete it
		var position = Roguelike.Utils.contains(entity, this.entities);

		//The element doesn't exist in the list
		if(position === false) {
			return;
		}

		//Remove the current entity from the group
		this.entities.splice(position, 1);

	}

};
<|endoftext|>


<commit_before>/*!
 Copyright 2013 Hewlett-Packard Development Company, L.P.

 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.
 */
'use strict';
/**
 * A transactional plug to manage internal state safely.
 *
 * CAF goal is to create and manage billions of long running, active, stateful
 * proxies, i.e., CAs, where "long running" means years. In order to tolerate
 *  -without human intervention- failures, upgrades, migration, or other errors,
 * the CA state has to be managed carefully.
 *
 * A complication is that CA state is not only application state, but state
 * associated with the plugins that the application uses.
 *
 * Also, CAF always ensures that CA state is consistent with
 * the externalized view of that state, i.e., CA actions that affect the
 * external world.
 *
 * For example, if a CA sends a message, and it keeps track of
 * sent messages in its internal state, even in the presence of failures
 * it should never forget that it sent that message.
 *
 * CAF approach assumes:
 *
 * 1. Operations that affect the external world are mediated by a
 *  plugin that makes them idempotent.
 *
 * 2. Plugins defer these operations until commit time, ensuring that, before
 *  execution, a persistent record of them has been checkpointed to an external
 *  service.
 *
 * 3. All plugins and application code coordinate using a two-phase commit
 * protocol, so that disaggregated state is managed consistently.
 *
 * 4. During recovery the last committed state is reloaded, and deferred
 * operations in the checkpoint are retried until they succeed.
 *
 * Methods `__ca_setLogActionsTarget__` and  `__ca_lazyApply__` defer methods.
 *
 * Methods `__ca_init__` and  `__ca_resume__` handle initialization and
 * recovery.
 *
 * Methods `__ca_begin__`,  `__ca_prepare__`, `__ca_commit__` and `__ca_abort__`
 * implement the two-phase commit protocol.
 *
 * @module caf_components/gen_transactional
 * @augments module:caf_components/gen_container
 */
// @ts-ignore: augments not attached to a class
var genContainer = require('./gen_container');
var myUtils = require('./myUtils');
var async = require('async');

/**
 * Helper constructor method for a transactional component.
 *
 * Description of types in file `types.js`.
 *
 * @param {ctxType} $ A context containing references to other components.
 * @param {specType} spec Configuration data for this component.
 * @return {Object} A new generic component.
 *
 * @throws {Error} If inputs are invalid.
 */
exports.constructor = function($, spec) {

    var that = genContainer.constructor($, spec);

    var logActions = [];

    var logActionsTarget = that;

    var childrenSpec = that.__ca_getChildrenSpec__();

    var transChildrenObj = null;

    var applyFun = function(method, args) {
        return function(x, cb0) {
            try {
                var argsAll = (args || []).concat([cb0]);
                var wrappedMethod = myUtils.wrapAsyncFunction(x.obj[method],
                                                              x.obj);
                wrappedMethod.apply(x.obj, argsAll);
            } catch (err) {
                cb0(err);
            }
        };
    };

    var childrenSeriesTransF = function(f, cb) {
        var findTrans = function() {
            var result = {};
            childrenSpec.forEach(function(x) {
                if (!that.$[x.name]) {
                    throw new Error('Missing child ' + x.name);
                } else if (that.$[x.name].__ca_isTransactional__) {
                    result[x.name] = x;
                }
            });
            return result;
        };
        transChildrenObj = findTrans(); // throw if any child missing
        var transSpec = childrenSpec.filter(function(x) {
            return transChildrenObj[x.name];
        });
        var transComp = [];
        transSpec.forEach(function(x) {
            var obj = that.$[x.name];
            if (obj) {
                transComp.push({obj: obj, name: x.name});
            }
        });
        async.mapSeries(transComp, f, function(err, res) {
            if (err) {
                cb(err, res);
            } else {
                var result = {};
                transComp.forEach(function(x, i) {
                    result[x.name] = res[i];
                });
                cb(err, result);
            }
        });
    };

    /**
     * Run-time type information.
     *
     * @type {boolean}
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_isTransactional__
     */
    that.__ca_isTransactional__ = true;

    var replayLog = function(cb) {
        async.eachSeries(logActions, function(x, cb0) {
            try {
                var args = (x.args && x.args.slice(0) || []);
                args.push(cb0);
                var wrappedMethod = myUtils.wrapAsyncFunction(
                    logActionsTarget[x.method],
                    logActionsTarget
                );
                wrappedMethod.apply(logActionsTarget, args);
            } catch (ex) {
                ex.method = x.method;
                ex.args = x.args;
                cb0(ex);
            }
        }, function(err, data) {
            if (err) {
                cb(err);
            } else {
                logActions = [];
                cb(err, data);
            }
        });
    };

    /**
     * Sets a receiver object implementing all the delayed methods.
     *
     * @param {Object} obj A receiver for delayed methods.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_setLogActionsTarget__
     */
    that.__ca_setLogActionsTarget__ = function(obj) {
        logActionsTarget = obj;
    };

    /**
     * Queues an operation to be executed at commit time.
     *
     * Internally, operations are made asynchronous and executed serially by
     * adding an extra callback. The actual implementation of these operations
     * is delegated to the `logActionsTarget` object.
     *
     * Operations are assumed to be idempotent.
     *
     * @param {string} method A method name to execute.
     * @param {Array.<any>}  args An array of method arguments.
     *
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_lazyApply__
     */
    that.__ca_lazyApply__ = function(method, args) {
        logActions.push({method: method, args: args});
    };

    /**
     * Initializes the state of this plug from scratch.
     *
     * This method is called only once, when the plug is created.
     *
     * @param {cbType} cb A callback to continue after initialization.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_init__
     */
    that.__ca_init__ = function(cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_init__', []), cb);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Reloads the state of this plug from a previous checkpoint.
     *
     * It also retries deferred operations in the checkpoint.
     *
     * This method is called many times, for example, after
     * recovering  from a failure or restarting after migration.
     *
     * @param {Object} cp The last checkpoint of the state of this plug.
     * @param {cbType} cb A callback to continue after resuming.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_resume__
     */
    that.__ca_resume__ = function(cp, cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    logActions = cp.logActions || [];
                    replayLog(cb);
                }
            };
            childrenSeriesTransF(function(x, cb1) {
                try {
                    var wrappedMethod = myUtils.wrapAsyncFunction(
                        x.obj.__ca_resume__,
                        x.obj
                    );
                    wrappedMethod.apply(x.obj, [cp[x.name], cb1]);
                } catch (err) {
                    cb1(err);
                }
            }, cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Begins a two phase commit transaction.
     *
     * CAF calls this method before the application handler processes
     * a message. A read-only copy of the message is passed as an argument
     * to facilitate configuration.
     *
     * @param {Object} msg The message to be processed.
     * @param {cbType} cb A callback to continue the transaction.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_begin__
     *
     */
    that.__ca_begin__ = function(msg, cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_begin__', [msg]), cb);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Prepares to commit the transaction.
     *
     * CAF calls this method after the handler has succesfully
     * processed the message.
     *
     * If ready to commit, it returns in the callback a JSON
     * serializable data structure reflecting the new state after
     * processing the message.
     *
     * Then, CAF checkpoints this data structure using a remote service.
     *
     * To abort the transaction we return an error in the (node.js) callback.
     * This will abort all the transactional plugs associated with the CA.
     *
     * @param {cbType} cb A callback to continue or abort the transaction.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_prepare__
     */
    that.__ca_prepare__ = function(cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    data.logActions = logActions;
                    cb(err, data);
                }
            };
            childrenSeriesTransF(applyFun('__ca_prepare__', []), cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Commits the transaction.
     *
     * Called by CAF when all the `prepare` calls to transactional
     * plugs were successful, and the new state of those plugs has been
     * checkpointed using an external service.
     *
     * An error during commit will shutdown the CA since we cannot abort
     * committed transactions. See `__ca_resume__` for the recovery strategy.
     *
     * @param {cbType} cb A callback to continue after commiting.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_commit__
     */
    that.__ca_commit__ = function(cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    replayLog(cb);
                }
            };
            childrenSeriesTransF(applyFun('__ca_commit__', []), cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Aborts the transaction.
     *
     * CAF calls this method when an error was returned
     * by the handler, or any transactional plugs propagated an error during
     *  `prepare`.
     *
     * Note that an error during remote checkpointing cannot
     * guarantee that the checkpoint was not made durable, and we need to
     * assume that it did. This means that we need to shutdown the CA.
     *
     * An implementation of this method should undo state changes and
     * ignore deferred operations.
     *
     * @param {cbType} cb A callback to continue after aborting.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_abort__
     */
    that.__ca_abort__ = function(cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_abort__', []), cb);
        } catch (err) {
            cb(err);
        }
    };

    return that;
};
<commit_msg>Cleanup checkpoint<commit_after>/*!
 Copyright 2013 Hewlett-Packard Development Company, L.P.

 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.
 */
'use strict';
/**
 * A transactional plug to manage internal state safely.
 *
 * CAF goal is to create and manage billions of long running, active, stateful
 * proxies, i.e., CAs, where "long running" means years. In order to tolerate
 *  -without human intervention- failures, upgrades, migration, or other errors,
 * the CA state has to be managed carefully.
 *
 * A complication is that CA state is not only application state, but state
 * associated with the plugins that the application uses.
 *
 * Also, CAF always ensures that CA state is consistent with
 * the externalized view of that state, i.e., CA actions that affect the
 * external world.
 *
 * For example, if a CA sends a message, and it keeps track of
 * sent messages in its internal state, even in the presence of failures
 * it should never forget that it sent that message.
 *
 * CAF approach assumes:
 *
 * 1. Operations that affect the external world are mediated by a
 *  plugin that makes them idempotent.
 *
 * 2. Plugins defer these operations until commit time, ensuring that, before
 *  execution, a persistent record of them has been checkpointed to an external
 *  service.
 *
 * 3. All plugins and application code coordinate using a two-phase commit
 * protocol, so that disaggregated state is managed consistently.
 *
 * 4. During recovery the last committed state is reloaded, and deferred
 * operations in the checkpoint are retried until they succeed.
 *
 * Methods `__ca_setLogActionsTarget__` and  `__ca_lazyApply__` defer methods.
 *
 * Methods `__ca_init__` and  `__ca_resume__` handle initialization and
 * recovery.
 *
 * Methods `__ca_begin__`,  `__ca_prepare__`, `__ca_commit__` and `__ca_abort__`
 * implement the two-phase commit protocol.
 *
 * @module caf_components/gen_transactional
 * @augments module:caf_components/gen_container
 */
// @ts-ignore: augments not attached to a class
var genContainer = require('./gen_container');
var myUtils = require('./myUtils');
var async = require('async');

/**
 * Helper constructor method for a transactional component.
 *
 * Description of types in file `types.js`.
 *
 * @param {ctxType} $ A context containing references to other components.
 * @param {specType} spec Configuration data for this component.
 * @return {Object} A new generic component.
 *
 * @throws {Error} If inputs are invalid.
 */
exports.constructor = function($, spec) {

    var that = genContainer.constructor($, spec);

    var logActions = [];

    var logActionsTarget = that;

    var childrenSpec = that.__ca_getChildrenSpec__();

    var transChildrenObj = null;

    var applyFun = function(method, args) {
        return function(x, cb0) {
            try {
                var argsAll = (args || []).concat([cb0]);
                var wrappedMethod = myUtils.wrapAsyncFunction(x.obj[method],
                                                              x.obj);
                wrappedMethod.apply(x.obj, argsAll);
            } catch (err) {
                cb0(err);
            }
        };
    };

    var childrenSeriesTransF = function(f, cb) {
        var findTrans = function() {
            var result = {};
            childrenSpec.forEach(function(x) {
                if (!that.$[x.name]) {
                    throw new Error('Missing child ' + x.name);
                } else if (that.$[x.name].__ca_isTransactional__) {
                    result[x.name] = x;
                }
            });
            return result;
        };
        transChildrenObj = findTrans(); // throw if any child missing
        var transSpec = childrenSpec.filter(function(x) {
            return transChildrenObj[x.name];
        });
        var transComp = [];
        transSpec.forEach(function(x) {
            var obj = that.$[x.name];
            if (obj) {
                transComp.push({obj: obj, name: x.name});
            }
        });
        async.mapSeries(transComp, f, function(err, res) {
            if (err) {
                cb(err, res);
            } else {
                var result = {};
                transComp.forEach(function(x, i) {
                    result[x.name] = res[i];
                });
                cb(err, result);
            }
        });
    };

    /**
     * Run-time type information.
     *
     * @type {boolean}
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_isTransactional__
     */
    that.__ca_isTransactional__ = true;

    var replayLog = function(cb) {
        async.eachSeries(logActions, function(x, cb0) {
            try {
                var args = (x.args && x.args.slice(0) || []);
                args.push(cb0);
                var wrappedMethod = myUtils.wrapAsyncFunction(
                    logActionsTarget[x.method],
                    logActionsTarget
                );
                wrappedMethod.apply(logActionsTarget, args);
            } catch (ex) {
                ex.method = x.method;
                ex.args = x.args;
                cb0(ex);
            }
        }, function(err, data) {
            if (err) {
                cb(err);
            } else {
                logActions = [];
                cb(err, data);
            }
        });
    };

    /**
     * Sets a receiver object implementing all the delayed methods.
     *
     * @param {Object} obj A receiver for delayed methods.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_setLogActionsTarget__
     */
    that.__ca_setLogActionsTarget__ = function(obj) {
        logActionsTarget = obj;
    };

    /**
     * Queues an operation to be executed at commit time.
     *
     * Internally, operations are made asynchronous and executed serially by
     * adding an extra callback. The actual implementation of these operations
     * is delegated to the `logActionsTarget` object.
     *
     * Operations are assumed to be idempotent.
     *
     * @param {string} method A method name to execute.
     * @param {Array.<any>}  args An array of method arguments.
     *
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_lazyApply__
     */
    that.__ca_lazyApply__ = function(method, args) {
        logActions.push({method: method, args: args});
    };

    /**
     * Initializes the state of this plug from scratch.
     *
     * This method is called only once, when the plug is created.
     *
     * @param {cbType} cb A callback to continue after initialization.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_init__
     */
    that.__ca_init__ = function(cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_init__', []), cb);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Reloads the state of this plug from a previous checkpoint.
     *
     * It also retries deferred operations in the checkpoint.
     *
     * This method is called many times, for example, after
     * recovering  from a failure or restarting after migration.
     *
     * @param {Object} cp The last checkpoint of the state of this plug.
     * @param {cbType} cb A callback to continue after resuming.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_resume__
     */
    that.__ca_resume__ = function(cp, cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    logActions = cp.logActions || [];
                    replayLog(cb);
                }
            };
            childrenSeriesTransF(function(x, cb1) {
                try {
                    var wrappedMethod = myUtils.wrapAsyncFunction(
                        x.obj.__ca_resume__,
                        x.obj
                    );
                    wrappedMethod.apply(x.obj, [cp[x.name], cb1]);
                } catch (err) {
                    cb1(err);
                }
            }, cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Begins a two phase commit transaction.
     *
     * CAF calls this method before the application handler processes
     * a message. A read-only copy of the message is passed as an argument
     * to facilitate configuration.
     *
     * @param {Object} msg The message to be processed.
     * @param {cbType} cb A callback to continue the transaction.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_begin__
     *
     */
    that.__ca_begin__ = function(msg, cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_begin__', [msg]), cb);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Prepares to commit the transaction.
     *
     * CAF calls this method after the handler has succesfully
     * processed the message.
     *
     * If ready to commit, it returns in the callback a JSON
     * serializable data structure reflecting the new state after
     * processing the message.
     *
     * Then, CAF checkpoints this data structure using a remote service.
     *
     * To abort the transaction we return an error in the (node.js) callback.
     * This will abort all the transactional plugs associated with the CA.
     *
     * @param {cbType} cb A callback to continue or abort the transaction.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_prepare__
     */
    that.__ca_prepare__ = function(cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    if (logActions.length > 0) {
                        data.logActions = logActions;
                    }
                    cb(err, data);
                }
            };
            childrenSeriesTransF(applyFun('__ca_prepare__', []), cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Commits the transaction.
     *
     * Called by CAF when all the `prepare` calls to transactional
     * plugs were successful, and the new state of those plugs has been
     * checkpointed using an external service.
     *
     * An error during commit will shutdown the CA since we cannot abort
     * committed transactions. See `__ca_resume__` for the recovery strategy.
     *
     * @param {cbType} cb A callback to continue after commiting.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_commit__
     */
    that.__ca_commit__ = function(cb) {
        try {
            var cb0 = function(err, data) {
                if (err) {
                    cb(err, data);
                } else {
                    replayLog(cb);
                }
            };
            childrenSeriesTransF(applyFun('__ca_commit__', []), cb0);
        } catch (err) {
            cb(err);
        }
    };

    /**
     * Aborts the transaction.
     *
     * CAF calls this method when an error was returned
     * by the handler, or any transactional plugs propagated an error during
     *  `prepare`.
     *
     * Note that an error during remote checkpointing cannot
     * guarantee that the checkpoint was not made durable, and we need to
     * assume that it did. This means that we need to shutdown the CA.
     *
     * An implementation of this method should undo state changes and
     * ignore deferred operations.
     *
     * @param {cbType} cb A callback to continue after aborting.
     *
     * @memberof! module:caf_components/gen_transactional#
     * @alias __ca_abort__
     */
    that.__ca_abort__ = function(cb) {
        try {
            logActions = [];
            childrenSeriesTransF(applyFun('__ca_abort__', []), cb);
        } catch (err) {
            cb(err);
        }
    };

    return that;
};
<|endoftext|>


<commit_before>'use strict';

/**
 * @file /hydrate endpoint
 *
 * Will queue requests onto the system file
 */

var restify = require('restify');

/**
 * This handler receives a document to hydrate on a POST request and processes it.
 *
 * @param {Object} req Request object from the client
 * @param {Object} res Response we want to return
 * @param {Object} server Current server. See implementation in index.js
 * @param {Function} next Callback to call once res has been populated.
 */
module.exports = function(req, res, server, logger, next) {
  if(!req.params.callback && !req.params.long_poll) {
    return next(new restify.MissingParameterError('No specified callback'));
  }

  // Prepare the new task
  var task = {};
  task.file_path = (req.params.file_path) ? req.params.file_path : null;
  task.callback = req.params.callback;

  if(req.params.long_poll) {
    task.res = res;
    task.next = next;
    delete req.params.long_poll;
  }
  else {
    res.send(202);
    next();
  }

  task.document = req.params.document;
  task.document.metadata = task.document.metadata || {};
  task.document.data = task.document.data || {};

  // Push it to the queue
  server.queue.push(task);
  logger("Queuing: " + ((task.file_path) ? task.file_path : task.document.id));
};
<commit_msg>Check for document existence<commit_after>'use strict';

/**
 * @file /hydrate endpoint
 *
 * Will queue requests onto the system file
 */

var restify = require('restify');

/**
 * This handler receives a document to hydrate on a POST request and processes it.
 *
 * @param {Object} req Request object from the client
 * @param {Object} res Response we want to return
 * @param {Object} server Current server. See implementation in index.js
 * @param {Function} next Callback to call once res has been populated.
 */
module.exports = function(req, res, server, logger, next) {
  if(!req.params.callback && !req.params.long_poll) {
    return next(new restify.MissingParameterError('No specified callback'));
  }

  // Prepare the new task
  var task = {};
  task.file_path = (req.params.file_path) ? req.params.file_path : null;
  task.callback = req.params.callback;

  if(req.params.long_poll) {
    task.res = res;
    task.next = next;
    delete req.params.long_poll;
  }
  else {
    res.send(202);
    next();
  }

  task.document = req.params.document;
  task.document.metadata = task.document ? task.document.metadata || {} : {};
  task.document.data = task.document ? task.document.data || {} : {};

  // Push it to the queue
  server.queue.push(task);
  logger("Queuing: " + ((task.file_path) ? task.file_path : task.document.id));
};
<|endoftext|>


<commit_before>/**
 * @module ShortestPath
 * @private
 */

/*eslint-disable*/
import { fillArray } from './Array.fill'

let prevTime = Date.now()

/**
 * @private
 * @todo tidy code
 * @todo implement faster algorithm (SMAWK)
 */
function getBestFit(tokens, spaceSize, offsets, width, height, fontSize, lineHeight, maxTokenSize, maxLineHeight, minLineHeight, truncatedToken, truncatedTokenSize, context) {
    let currentTime = Date.now()
    prevTime = currentTime
    const count = tokens.length
    let maxLines

    // heightRatio is how many times the unscaled fontsize * desired line height fit into the height of the box.
    let heightRatio = height/(fontSize*lineHeight)

    // Use the maxTokenSize and maxLineHeight to caclulate the minimum lines
    let lines

    lines = Math.ceil(maxTokenSize * heightRatio / width)

    if (maxLineHeight > 0) {
        const maxLineHeightLines = Math.ceil(height / maxLineHeight)
        lines = Math.max(lines, maxLineHeightLines)
    }

    if (minLineHeight > 0) {
        maxLines = Math.floor(height/ minLineHeight)
    }

    // figure out minimum lines
    // should implement a binary search for this
    let i = lines
    let finished = false
    let previousBreakpoint
    while (!finished) {
        let maxSpace = width/heightRatio * i * i
        for (let j = previousBreakpoint || 0; j < count+1; j++) {
            if (offsets[j] + (j + i - 1) * spaceSize > maxSpace) {
                let needsNewLine = false
                let newMaxSpace = width/heightRatio * (i + 1) * i // scale width as if new line, but don't actually use an i + 1 th line
                for (let k = j+1; k < count+1; k++) {
                    if (offsets[k] + ( k + i - 1) * spaceSize > newMaxSpace) {
                        needsNewLine = true
                        previousBreakpoint = k - 1 // shouldn't find the breakpoint earlier than this
                        break
                    }
                }
                if (!needsNewLine) {
                    // we have min
                    finished = true // finish the while
                    break // from the for, not the while
                } else {
                    // we need moar lines
                    i++
                }
                break // from the for, not the while
            } else if (j === count) {
                // from the for, and end while
                finished = true
                break
            }
        }
    }
    let minLines = i

    // make sure min lines isn't greater than max lines
    if (maxLines) {
        if (minLines > maxLines) {
            minLines = maxLines
        }
    }

    let largestLineSize

    function truncateLine(line) {
        let lineOffsets = new Array(line.length + 1)
        lineOffsets[0] = 0

        for (let i = 0; i < line.length; i++) {
            lineOffsets[i + 1] = context.measureText(line.slice(0, i)).width
        }

        let j
        for (j = lineOffsets.length; j > 0; j--) {
            if ((lineOffsets[j] + truncatedTokenSize + spaceSize) < largestLineSize) {
                let newLineSize = context.measureText(line.slice(0, j - 1) + truncatedToken).width;
                if (newLineSize + 1 < largestLineSize) { // + 1 to avoid rounding errors
                    break;
                }
            }
        }

        return line.slice(0, j - 1) + truncatedToken
    }

    function findMinima(scaledWidth, targetLines) {
        let minima = [0].concat(fillArray(Array(count), Infinity))
        let breaks = fillArray(Array(count + 1), 0)
        largestLineSize = 0
        for (let i = 0; i < count; i++) {
            let j = i + 1
            while (j <= count) {
                let w = offsets[j] - offsets[i] + (j - i - 1) *spaceSize
                if (w > scaledWidth) {
                    break
                }

                let cost = minima[i] + Math.pow((scaledWidth - w), 2)

                if (cost < minima[j]) {
                    minima[j] = cost
                    breaks[j] = i
                }
                j += 1
            }
        }

        let lines = []
        let lineIndexes = []
        let j = count

        while (j > 0) {
            let i = breaks[j]
            if (lineIndexes.length + 1 > targetLines && (!maxLines || (maxLines > targetLines))) {
                return false
            } else {
                lineIndexes.push({ start: i, end: j })
            }
            let width = offsets[j] - offsets[i] + (j - i) * spaceSize
            largestLineSize = Math.max(largestLineSize, width)
            j = i
        }

        const truncate = maxLines && (lineIndexes.length > maxLines) && (targetLines === maxLines)

        if (truncate) {
            lineIndexes = lineIndexes.slice(lineIndexes.length - maxLines, lineIndexes.length)
        }

        function countLinesFromBreaks (nextBreak) {
            let lineCount = 0

            while (nextBreak !== 0) {
                nextBreak = breaks[nextBreak]
                lineCount++
            }

            return lineCount
        }

        let currentStartingBreak = 0
        if (truncate) {
            // Need to find the break that fits the most words into the maxLines
            j = 0
            for (let i = 0; i < breaks.length; i++) {
                if (i !== 0) {
                    let lineCount = countLinesFromBreaks(i)

                    if (lineCount === maxLines) {
                        currentStartingBreak = i
                    }

                    if (lineCount > maxLines) {
                        break
                    }
                }
            }

            lineIndexes = []
            j = currentStartingBreak
            let i = breaks[j]
            lineIndexes.push({ start: i, end: j + 1 })

            let width = offsets[j] - offsets[i] + (j - i) * spaceSize
            largestLineSize = Math.max(largestLineSize, width)

            j = i
            // recalculate line indexes with truncated text
            while (j > 0) {
                let i = breaks[j]
                lineIndexes.push({ start: i, end: j })
                let width = offsets[j] - offsets[i] + (j - i) * spaceSize
                largestLineSize = Math.max(largestLineSize, width)
                j = i
            }
        }

        for (let l = lineIndexes.length - 1; l >= 0; l--) {
            const lineIndex = lineIndexes[l]
            let line = tokens.slice(lineIndex.start, lineIndex.end).join(' ')
            if (l === 0 && truncate) {
                line = truncateLine(line)
            }
            lines.push({ line: line })
        }

        return lines
    }

    let currentLines = minLines
    let results
    let maxLineWidth
    let attempts = 0
    let trying = true
    while (trying) {
        maxLineWidth = currentLines * width/heightRatio
        results = findMinima(maxLineWidth, currentLines)

        if (attempts > 100) {
            throw new Error(`Can't fit text after ${attempts} attempts`);
        }
        attempts++

        if (!results) {
            currentLines++
        } else {
            trying = false
        }
    }
    return {
        results: results,
        targetLines: currentLines,
        maxLineWidth: maxLineWidth,
        largestLineSize: largestLineSize
    }
}

export { getBestFit }
<commit_msg>Encapsulate width calculation into function, also add +1 to width calculations to avoid rounding errors when calculating fill ratio<commit_after>/**
 * @module ShortestPath
 * @private
 */

/*eslint-disable*/
import { fillArray } from './Array.fill'

let prevTime = Date.now()

/**
 * @private
 * @todo tidy code
 * @todo implement faster algorithm (SMAWK)
 */
function getBestFit(tokens, spaceSize, offsets, width, height, fontSize, lineHeight, maxTokenSize, maxLineHeight, minLineHeight, truncatedToken, truncatedTokenSize, context) {
    let currentTime = Date.now()
    prevTime = currentTime
    const count = tokens.length
    let maxLines

    // heightRatio is how many times the unscaled fontsize * desired line height fit into the height of the box.
    let heightRatio = height/(fontSize*lineHeight)

    // Use the maxTokenSize and maxLineHeight to caclulate the minimum lines
    let lines

    lines = Math.ceil(maxTokenSize * heightRatio / width)

    if (maxLineHeight > 0) {
        const maxLineHeightLines = Math.ceil(height / maxLineHeight)
        lines = Math.max(lines, maxLineHeightLines)
    }

    if (minLineHeight > 0) {
        maxLines = Math.floor(height/ minLineHeight)
    }

    // figure out minimum lines
    // should implement a binary search for this
    let i = lines
    let finished = false
    let previousBreakpoint
    while (!finished) {
        let maxSpace = width/heightRatio * i * i
        for (let j = previousBreakpoint || 0; j < count+1; j++) {
            if (offsets[j] + (j + i - 1) * spaceSize > maxSpace) {
                let needsNewLine = false
                let newMaxSpace = width/heightRatio * (i + 1) * i // scale width as if new line, but don't actually use an i + 1 th line
                for (let k = j+1; k < count+1; k++) {
                    if (offsets[k] + ( k + i - 1) * spaceSize > newMaxSpace) {
                        needsNewLine = true
                        previousBreakpoint = k - 1 // shouldn't find the breakpoint earlier than this
                        break
                    }
                }
                if (!needsNewLine) {
                    // we have min
                    finished = true // finish the while
                    break // from the for, not the while
                } else {
                    // we need moar lines
                    i++
                }
                break // from the for, not the while
            } else if (j === count) {
                // from the for, and end while
                finished = true
                break
            }
        }
    }
    let minLines = i

    // make sure min lines isn't greater than max lines
    if (maxLines) {
        if (minLines > maxLines) {
            minLines = maxLines
        }
    }

    let largestLineSize

    function truncateLine(line) {
        let lineOffsets = new Array(line.length + 1)
        lineOffsets[0] = 0

        for (let i = 0; i < line.length; i++) {
            lineOffsets[i + 1] = context.measureText(line.slice(0, i)).width
        }

        let j
        for (j = lineOffsets.length; j > 0; j--) {
            if ((lineOffsets[j] + truncatedTokenSize + spaceSize) < largestLineSize) {
                let newLineSize = context.measureText(line.slice(0, j - 1) + truncatedToken).width;
                if (newLineSize + 1 < largestLineSize) { // + 1 to avoid rounding errors
                    break;
                }
            }
        }

        return line.slice(0, j - 1) + truncatedToken
    }

    function calcWidth(i, j) {
        return offsets[j] - offsets[i] + 1 + (j - i - 1) * spaceSize // there is a plus one to avoid rounding errors
    }

    function findMinima(scaledWidth, targetLines) {
        let minima = [0].concat(fillArray(Array(count), Infinity))
        let breaks = fillArray(Array(count + 1), 0)
        largestLineSize = 0
        for (let i = 0; i < count; i++) {
            let j = i + 1
            while (j <= count) {
                let w = calcWidth(i, j)
                if (w > scaledWidth) {
                    break
                }

                let cost = minima[i] + Math.pow((scaledWidth - w), 2)

                if (cost < minima[j]) {
                    minima[j] = cost
                    breaks[j] = i
                }
                j += 1
            }
        }

        let lines = []
        let lineIndexes = []
        let j = count

        while (j > 0) {
            let i = breaks[j]
            if (lineIndexes.length + 1 > targetLines && (!maxLines || (maxLines > targetLines))) {
                return false
            } else {
                lineIndexes.push({ start: i, end: j })
            }
            let width = calcWidth(i, j)
            largestLineSize = Math.max(largestLineSize, width)
            j = i
        }

        const truncate = maxLines && (lineIndexes.length > maxLines) && (targetLines === maxLines)

        if (truncate) {
            lineIndexes = lineIndexes.slice(lineIndexes.length - maxLines, lineIndexes.length)
        }

        function countLinesFromBreaks (nextBreak) {
            let lineCount = 0

            while (nextBreak !== 0) {
                nextBreak = breaks[nextBreak]
                lineCount++
            }

            return lineCount
        }

        let currentStartingBreak = 0
        if (truncate) {
            // Need to find the break that fits the most words into the maxLines
            j = 0
            for (let i = 0; i < breaks.length; i++) {
                if (i !== 0) {
                    let lineCount = countLinesFromBreaks(i)

                    if (lineCount === maxLines) {
                        currentStartingBreak = i
                    }

                    if (lineCount > maxLines) {
                        break
                    }
                }
            }

            lineIndexes = []
            j = currentStartingBreak
            let i = breaks[j]
            lineIndexes.push({ start: i, end: j + 1 })

            let width = calcWidth(i, j)
            largestLineSize = Math.max(largestLineSize, width)

            j = i
            // recalculate line indexes with truncated text
            while (j > 0) {
                let i = breaks[j]
                lineIndexes.push({ start: i, end: j })
                let width = calcWidth(i, j)
                largestLineSize = Math.max(largestLineSize, width)
                j = i
            }
        }

        for (let l = lineIndexes.length - 1; l >= 0; l--) {
            const lineIndex = lineIndexes[l]
            let line = tokens.slice(lineIndex.start, lineIndex.end).join(' ')
            if (l === 0 && truncate) {
                line = truncateLine(line)
            }
            lines.push({ line: line })
        }

        return lines
    }

    let currentLines = minLines
    let results
    let maxLineWidth
    let attempts = 0
    let trying = true
    while (trying) {
        maxLineWidth = currentLines * width/heightRatio
        results = findMinima(maxLineWidth, currentLines)

        if (attempts > 100) {
            throw new Error(`Can't fit text after ${attempts} attempts`);
        }
        attempts++

        if (!results) {
            currentLines++
        } else {
            trying = false
        }
    }
    return {
        results: results,
        targetLines: currentLines,
        maxLineWidth: maxLineWidth,
        largestLineSize: largestLineSize
    }
}

export { getBestFit }
<|endoftext|>


<commit_before>import MediumEditor from 'medium-editor';

const MediumEditorAutofocus = MediumEditor.Extension.extend({
  name: 'autofocus',

  init() {
    if (this.getEditorElements().length < 1) {
      return;
    }

    this.getEditorElements()[0].focus();
  }
});

export default MediumEditorAutofocus;
<commit_msg>Autofocus first child node if one is present<commit_after>import MediumEditor from 'medium-editor';

const MediumEditorAutofocus = MediumEditor.Extension.extend({
  name: 'autofocus',

  init() {
    if (this.getEditorElements().length < 1) {
      return;
    }

    if(!this.getEditorElements()[0].children.length) {
      this.getEditorElements()[0].focus();
    } else {
      this.base.selectElement(this.getEditorElements()[0].children[0]);
      MediumEditor.selection.clearSelection(document, true);
    }
  }
});

export default MediumEditorAutofocus;
<|endoftext|>


<commit_before>import AriaListMixin from './AriaListMixin.js';
import DirectionSelectionMixin from './DirectionSelectionMixin.js';
import FocusVisibleMixin from './FocusVisibleMixin.js';
import KeyboardDirectionMixin from './KeyboardDirectionMixin.js';
import KeyboardMixin from './KeyboardMixin.js';
import SlidingViewport from './SlidingViewport.js';
import SwipeDirectionMixin from './SwipeDirectionMixin.js';
import TouchSwipeMixin from './TouchSwipeMixin.js';
import TrackpadSwipeMixin from './TrackpadSwipeMixin.js';

const Base =
  AriaListMixin(
  DirectionSelectionMixin(
  FocusVisibleMixin(
  KeyboardDirectionMixin(
  KeyboardMixin(
  SwipeDirectionMixin(
  TouchSwipeMixin(
  TrackpadSwipeMixin(
    SlidingViewport
  ))))))));

/**
 * Allows a user to navigate a horizontal set of items with touch, mouse,
 * keyboard, or trackpad. Shows a sliding effect when moving between items.
 *
 * @inherits SlidingViewport
 * @mixes AriaListMixin
 * @mixes DirectionSelectionMixin
 * @mixes FocusVisibleMixin
 * @mixes KeyboardDirectionMixin
 * @mixes KeyboardMixin
 * @mixes SwipeDirectionMixin
 * @mixes TouchSwipeMixin
 * @mixes TrackpadSwipeMixin
 */
class SlidingPages extends Base {}

customElements.define('elix-sliding-pages', SlidingPages);
export default SlidingPages;
<commit_msg>Workaround Edge bug.<commit_after>import * as symbols from './symbols.js';
import AriaListMixin from './AriaListMixin.js';
import DirectionSelectionMixin from './DirectionSelectionMixin.js';
import FocusVisibleMixin from './FocusVisibleMixin.js';
import KeyboardDirectionMixin from './KeyboardDirectionMixin.js';
import KeyboardMixin from './KeyboardMixin.js';
import SlidingViewport from './SlidingViewport.js';
import SwipeDirectionMixin from './SwipeDirectionMixin.js';
import TouchSwipeMixin from './TouchSwipeMixin.js';
import TrackpadSwipeMixin from './TrackpadSwipeMixin.js';

const Base =
  AriaListMixin(
  DirectionSelectionMixin(
  FocusVisibleMixin(
  KeyboardDirectionMixin(
  KeyboardMixin(
  SwipeDirectionMixin(
  TouchSwipeMixin(
  TrackpadSwipeMixin(
    SlidingViewport
  ))))))));

/**
 * Allows a user to navigate a horizontal set of items with touch, mouse,
 * keyboard, or trackpad. Shows a sliding effect when moving between items.
 *
 * @inherits SlidingViewport
 * @mixes AriaListMixin
 * @mixes DirectionSelectionMixin
 * @mixes FocusVisibleMixin
 * @mixes KeyboardDirectionMixin
 * @mixes KeyboardMixin
 * @mixes SwipeDirectionMixin
 * @mixes TouchSwipeMixin
 * @mixes TrackpadSwipeMixin
 */
class SlidingPages extends Base {

  // Workaround Edge bug: https://github.com/Microsoft/ChakraCore/issues/4835.
  // When that's fixed, we can remove this.
  get [symbols.swipeTarget]() {
    return this;
  }

}

customElements.define('elix-sliding-pages', SlidingPages);
export default SlidingPages;
<|endoftext|>


<commit_before>/**
 *
 * Created by aleckim on 2017. 12. 08..
 */

'use strict';

var router = require('express').Router();

var ControllerTown24h = require('../../controllers/controllerTown24h');

var cTown = new ControllerTown24h();

router.use(function timestamp(req, res, next){
    var printTime = new Date();
    log.info('+ kma/addr > request | Time[', printTime.toISOString(), ']');

    next();
});

router.get('/', function(req, res) {
    var meta = {};

    var result = {};

    meta.method = '/';

    log.info('##', meta);

    if(req.summary){
        result.summary = req.summary;
    }

    result.usage = [
        '/{도,특별시,광역시} : response summarized weather information on matched region',
        '/{도,특별시,광역시}/{시,군,구} : response summarized weather information on matched city',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍} : response weather data for all three types such as short, shortest, current',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/short : response only short information',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/shortest : response only shortest information',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/current : response only current information'
    ];
    res.json(result);
});

/**
 * getCurrent가는 getShortest, getShort보다 앞에 올 수 없음.
 * getSummary는 getShortest, getCurrent보다 앞에 올수 없음.
 * 기존의 getSummary를 단위변환때문에 setYesterDay와 getSummaryAfterUnitConverter로 분리함.
 */
var routerList = [cTown.checkQueryValidation, cTown.getAllDataFromDb, cTown.checkDBValidation, cTown.getShort,
    cTown.getShortRss, cTown.getShortest, cTown.getCurrent, cTown.updateCurrentListForValidation,
    cTown.mergeCurrentByStnHourly, cTown.getKmaStnMinuteWeather, cTown.convert0Hto24H, cTown.mergeShortWithCurrentList,
    cTown.mergeByShortest, cTown.adjustShort, cTown.getMid, cTown.getMidRss, cTown.convertMidKorStrToSkyInfo,
    cTown.getPastMid, cTown.mergeMidWithShort, cTown.updateMidTempMaxMin, cTown.getLifeIndexKma, cTown.getHealthDay, cTown.getKeco,
    cTown.getKecoDustForecast, cTown.getRiseSetInfo, cTown.insertIndex, cTown.insertStrForData, cTown.insertSkyIcon,
    cTown.setYesterday, cTown.AirkoreaForecast, cTown.convertUnits, cTown.getSummaryAfterUnitConverter, cTown.makeResult, cTown.sendResult];

router.get('/:region', routerList);

router.get('/:region/:city', routerList);

router.get('/:region/:city/:town', routerList);

module.exports = router;
<commit_msg>insert string after convert units #1903<commit_after>/**
 *
 * Created by aleckim on 2017. 12. 08..
 */

'use strict';

var router = require('express').Router();

var ControllerTown24h = require('../../controllers/controllerTown24h');

var cTown = new ControllerTown24h();

router.use(function timestamp(req, res, next){
    var printTime = new Date();
    log.info('+ kma/addr > request | Time[', printTime.toISOString(), ']');

    next();
});

router.get('/', function(req, res) {
    var meta = {};

    var result = {};

    meta.method = '/';

    log.info('##', meta);

    if(req.summary){
        result.summary = req.summary;
    }

    result.usage = [
        '/{도,특별시,광역시} : response summarized weather information on matched region',
        '/{도,특별시,광역시}/{시,군,구} : response summarized weather information on matched city',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍} : response weather data for all three types such as short, shortest, current',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/short : response only short information',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/shortest : response only shortest information',
        '/{도,특별시,광역시}/{시,군,구}/{동,면,읍}/current : response only current information'
    ];
    res.json(result);
});

/**
 * getCurrent가는 getShortest, getShort보다 앞에 올 수 없음.
 * getSummary는 getShortest, getCurrent보다 앞에 올수 없음.
 * 기존의 getSummary를 단위변환때문에 setYesterDay와 getSummaryAfterUnitConverter로 분리함.
 * skyIcon은 convertUnits 전에 불러야 함.
 * insrtStr은 convertUnits 후에 불러야함.
 */
var routerList = [cTown.checkQueryValidation, cTown.getAllDataFromDb, cTown.checkDBValidation, cTown.getShort,
    cTown.getShortRss, cTown.getShortest, cTown.getCurrent, cTown.updateCurrentListForValidation,
    cTown.mergeCurrentByStnHourly, cTown.getKmaStnMinuteWeather, cTown.convert0Hto24H, cTown.mergeShortWithCurrentList,
    cTown.mergeByShortest, cTown.adjustShort, cTown.getMid, cTown.getMidRss, cTown.convertMidKorStrToSkyInfo,
    cTown.getPastMid, cTown.mergeMidWithShort, cTown.updateMidTempMaxMin, cTown.getLifeIndexKma, cTown.getHealthDay, cTown.getKeco,
    cTown.getKecoDustForecast, cTown.getRiseSetInfo, cTown.insertIndex, cTown.AirkoreaForecast, cTown.insertSkyIcon,
    cTown.setYesterday, cTown.convertUnits, cTown.insertStrForData, cTown.getSummaryAfterUnitConverter,
    cTown.makeResult, cTown.sendResult];

router.get('/:region', routerList);

router.get('/:region/:city', routerList);

router.get('/:region/:city/:town', routerList);

module.exports = router;
<|endoftext|>