<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

function check_page_exists_and_redirect(event) {

    const path_to_try = event.target.value;

    const base_path = path_to_try.match("(.*\/r\/)?")[0];
    let tryUrl = path_to_try;
    $.ajax({
        type: 'HEAD',
        url: tryUrl,
        success: function() {
            location.href = tryUrl;
        }
    }).fail(function() {
        location.href = base_path;
    });
    return false;
}

(function () {
  // Load the rmarkdown tabset script
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.async = true;
  script.src =
    "https://cdn.jsdelivr.net/gh/rstudio/rmarkdown@47d837d3d9cd5e8e212b05767454f058db7d2789/inst/rmd/h/navigation-1.1/tabsets.js";
  script.integrity = "sha256-Rs54TE1FCN1uLM4f7VQEMiRTl1Ia7TiQLkMruItwV+Q=";
  script.crossOrigin = "anonymous";

  // Run the processing as the onload callback
  script.onload = () => {
    // Monkey patch the .html method to use the .text method
    $(document).ready(function () {
      (function ($) {
        $.fn.html = function (content) {
          return this.text();
        };
      })(jQuery);

      window.buildTabsets("toc");
    });

    $(document).ready(function () {
      $(".tabset-dropdown > .nav-tabs > li").click(function () {
        $(this).parent().toggleClass("nav-tabs-open");
      });
    });

    $(document).ready(function () {
      /**
       * The tabset creation above sometimes relies on empty headers to stop the
       * tabbing. Though they shouldn't be included in the TOC in the first place,
       * this will remove empty headers from the TOC after it's created.
       */

      // find all the empty  elements and remove them (and their parents)
      var empty_a = $("#toc").find("a").filter(":empty");
      empty_a.parent().remove();

      // now find any empty
s and remove them too
      var empty_ul = $("#toc").find("ul").filter(":empty");
      empty_ul.remove();
    });

    $(document).ready(function () {

      /**
       * This replaces the package version number in the docs with a
       * dropdown where you can select the version of the docs to view.
       */

        $pathStart = function(){
    	  return window.location.origin + "/docs/";
        }

        $pathEnd  = function(){
      	  var current_path = window.location.pathname;
      	  return current_path.match("(?<=\/r).*");
        }

        $.getJSON("https://arrow.apache.org/docs/r/versions.json", function( data ) {
          // get the current page's version number:
		  var displayed_version = $('.version').text();
          const sel = document.createElement("select");
          sel.name = "version-selector";
          sel.id = "version-selector";
          sel.classList.add("navbar-default");
          sel.onchange = check_page_exists_and_redirect;

		  $.each( data, function( key, val ) {
            const opt = document.createElement("option");
            opt.value = $pathStart() + val.version + "r" + $pathEnd();
            opt.selected = val.name.match("[0-9.]*")[0] === displayed_version;
            opt.text = val.name;
            sel.append(opt);
		  });

          $("span.version").replaceWith(sel);
        });
    });

  };

  document.head.appendChild(script);
})();
<commit_msg>ARROW-15895: [R] R docs version switcher disappears & reappears with back button on Chrome<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

function check_page_exists_and_redirect(event) {

    const path_to_try = event.target.value;

    const base_path = path_to_try.match("(.*\/r\/)?")[0];
    let tryUrl = path_to_try;
    $.ajax({
        type: 'HEAD',
        url: tryUrl,
        success: function() {
            location.href = tryUrl;
        }
    }).fail(function() {
        location.href = base_path;
    });
    return false;
}

/**
 * We need to do this so that the version dropdown doesn't used cached HTML
 * on Chrome on MacOS (see ARROW-15895)
 */
$(window).bind("pageshow", function(event) {
  if (event.originalEvent.persisted) {
    window.location.reload()
  }
});

(function () {
  // Load the rmarkdown tabset script
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.async = true;
  script.src =
    "https://cdn.jsdelivr.net/gh/rstudio/rmarkdown@47d837d3d9cd5e8e212b05767454f058db7d2789/inst/rmd/h/navigation-1.1/tabsets.js";
  script.integrity = "sha256-Rs54TE1FCN1uLM4f7VQEMiRTl1Ia7TiQLkMruItwV+Q=";
  script.crossOrigin = "anonymous";

  // Run the processing as the onload callback
  script.onload = () => {
    // Monkey patch the .html method to use the .text method
    $(document).ready(function () {
      (function ($) {
        $.fn.html = function (content) {
          return this.text();
        };
      })(jQuery);

      window.buildTabsets("toc");
    });

    $(document).ready(function () {
      $(".tabset-dropdown > .nav-tabs > li").click(function () {
        $(this).parent().toggleClass("nav-tabs-open");
      });
    });

    $(document).ready(function () {
      /**
       * The tabset creation above sometimes relies on empty headers to stop the
       * tabbing. Though they shouldn't be included in the TOC in the first place,
       * this will remove empty headers from the TOC after it's created.
       */

      // find all the empty  elements and remove them (and their parents)
      var empty_a = $("#toc").find("a").filter(":empty");
      empty_a.parent().remove();

      // now find any empty
s and remove them too
      var empty_ul = $("#toc").find("ul").filter(":empty");
      empty_ul.remove();
    });

    $(document).ready(function () {

      /**
       * This replaces the package version number in the docs with a
       * dropdown where you can select the version of the docs to view.
       */

        $pathStart = function(){
    	  return window.location.origin + "/docs/";
        }

        $pathEnd  = function(){
      	  var current_path = window.location.pathname;
      	  return current_path.match("(?<=\/r).*");
        }

        $.getJSON("https://arrow.apache.org/docs/r/versions.json", function( data ) {
          // get the current page's version number:
		  var displayed_version = $('.version').text();
          const sel = document.createElement("select");
          sel.name = "version-selector";
          sel.id = "version-selector";
          sel.classList.add("navbar-default");
          sel.onchange = check_page_exists_and_redirect;

		  $.each( data, function( key, val ) {
            const opt = document.createElement("option");
            opt.value = $pathStart() + val.version + "r" + $pathEnd();
            opt.selected = val.name.match("[0-9.]*")[0] === displayed_version;
            opt.text = val.name;
            sel.append(opt);
		  });

          $("span.version").replaceWith(sel);
        });
    });

  };

  document.head.appendChild(script);
})();
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'

if (process.env.BROWSER) {
    require("./FeaturesItem.css");
}

const IMG_RATIO = 0.667;

export default class FeaturesItem extends Component {
    constructor(props, context) {
        super(props, context)

        // scrollController and scrollScene are used for ScrollMagic
        this.scrollController = null
        this.scrollScene = null
    }

    _resizeImage() {
        let img = ReactDOM.findDOMNode(this.refs.listImg);
        // browser width and height
        let bHeight = window.innerHeight
        let bWidth =  window.innerWidth
        let bRatio = bHeight / bWidth
        let height
        let width
        let marginTop
        let marginLeft

        // height of browser is longer than image height in ratio.
        // use browser height as criterion
        if (bRatio > IMG_RATIO) {
            height = bHeight
            width = height / IMG_RATIO
            marginLeft = bWidth - width
        } else {
            width = bWidth
            height = width * IMG_RATIO
            marginTop = bHeight - height
        }
        img.style.marginTop = marginTop ? marginTop + 'px' : ''
        img.style.marginLeft = marginLeft ? marginLeft + 'px' : ''
        img.style.height = height + 'px'
        img.style.width = width + 'px'
    }

    _handleResize() {
        // resize image
         this._resizeImage()

        // only for desktop, we have the parallax animation
        if (window.innerWidth  > 800 ) {

            if (!this.scrollController) {
                // init controller
                this.scrollController = new ScrollMagic.Controller()
            }

            if (this.scrollScene) {
                // remove scene from controller
                this.scrollScene.remove()
            }

            if (!this.scrollScene) {
                // create a scene
                this.scrollScene = new ScrollMagic.Scene({
                    triggerElement: '#parallax-trigger'+this.props.article.id,
                    triggerHook: 0, // don't trigger until #parallax-trigger hits the top of the viewport,
                })
            }

            this.scrollScene
            .duration(window.innerHeight)
            .setPin('#parallax-trigger'+this.props.article.id, {pushFollowers: false}) // pins the element for the the scene's duration
            .addIndicators()
            .addTo(this.scrollController)

        } else {
            if (this.scrollScene) {
                // remove the pin from the scene and reset the pin element to its initial position (spacer is removed)
                this.scrollScene.removePin(true)
                // remove scene from controller it belonged to
                this.scrollScene.remove();
            }
        }
    }

    componentDidMount() {
        // only resize image and attach parallax for desktop
        if (window.innerWidth > 800) {
            this._handleResize()
            window.addEventListener('resize', this._handleResize.bind(this));
        }
    }

    render() {
        const { article } = this.props
        let firstImage = "https://www.twreporter.org/data/files/organization/60826/image/derivative/scale~24050x0~" + article.firstImage
        let url = (article.story_link) ? article.story_link : "https://www.twreporter.org/a/" + article.slug
        let d = new Date()
        d.setTime(article.lastPublish*1000)
        let d_str = d.toISOString().substring(0,10);
        let tags = article.tags
        let cat_display = "專題"
        for (let i = 0; i < tags.length; i++) {
            if (tags[i].substring(0,4) == 'cat:') {
                cat_display = tags[i].substring(4)
                break
            }
        }

        return (

{cat_display.substring(0,1)}

{cat_display.substring(2,1)}

{d_str}

{article.title}

{article.excerpt}

{article.author_display}

        )
    }
}
<commit_msg>show different img style for desktop and mobile<commit_after>import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'

if (process.env.BROWSER) {
    require("./FeaturesItem.css");
}

const IMG_RATIO = 0.667;

export default class FeaturesItem extends Component {
    constructor(props, context) {
        super(props, context)

        // scrollController and scrollScene are used for ScrollMagic
        this.scrollController = null
        this.scrollScene = null
    }

    _resizeImage() {
        let img = ReactDOM.findDOMNode(this.refs.listImg);
        // browser width and height
        let bHeight = window.innerHeight
        let bWidth =  window.innerWidth
        let bRatio = bHeight / bWidth
        let height
        let width
        let marginTop
        let marginLeft

        // height of browser is longer than image height in ratio.
        // use browser height as criterion
        if (bRatio > IMG_RATIO) {
            height = bHeight
            width = height / IMG_RATIO
            marginLeft = bWidth - width
        } else {
            width = bWidth
            height = width * IMG_RATIO
            marginTop = bHeight - height
        }
        img.style.marginTop = marginTop ? marginTop + 'px' : ''
        img.style.marginLeft = marginLeft ? marginLeft + 'px' : ''
        img.style.height = height + 'px'
        img.style.width = width + 'px'
    }

    _recoveryImage() {
        let img = ReactDOM.findDOMNode(this.refs.listImg);
        img.style.marginLeft = img.style.marginTop = img.style.height = img.style.width = ''
    }

    _handleResize() {

        // only for desktop, we have the parallax animation
        if (window.innerWidth  > 800 ) {

            // resize image
            this._resizeImage()

            if (!this.scrollController) {
                // init controller
                this.scrollController = new ScrollMagic.Controller()
            }

            if (this.scrollScene) {
                // remove scene from controller
                this.scrollScene.remove()
            }

            if (!this.scrollScene) {
                // create a scene
                this.scrollScene = new ScrollMagic.Scene({
                    triggerElement: '#parallax-trigger'+this.props.article.id,
                    triggerHook: 0, // don't trigger until #parallax-trigger hits the top of the viewport,
                })
            }

            this.scrollScene
            .duration(window.innerHeight)
            .setPin('#parallax-trigger'+this.props.article.id, {pushFollowers: false}) // pins the element for the the scene's duration
            .addIndicators()
            .addTo(this.scrollController)

        } else {
            // remove style added by _resizeImage function
            this._recoveryImage()

            if (this.scrollScene) {
                // remove the pin from the scene and reset the pin element to its initial position (spacer is removed)
                this.scrollScene.removePin(true)
                // remove scene from controller it belonged to
                this.scrollScene.remove();
            }
        }
    }

    componentDidMount() {
        this._handleResize()
        window.addEventListener('resize', this._handleResize.bind(this));
    }

    render() {
        const { article } = this.props
        let firstImage = "https://www.twreporter.org/data/files/organization/60826/image/derivative/scale~24050x0~" + article.firstImage
        let url = (article.story_link) ? article.story_link : "https://www.twreporter.org/a/" + article.slug
        let d = new Date()
        d.setTime(article.lastPublish*1000)
        let d_str = d.toISOString().substring(0,10);
        let tags = article.tags
        let cat_display = "專題"
        for (let i = 0; i < tags.length; i++) {
            if (tags[i].substring(0,4) == 'cat:') {
                cat_display = tags[i].substring(4)
                break
            }
        }

        return (

{cat_display.substring(0,1)}

{cat_display.substring(2,1)}

{d_str}

{article.title}

{article.excerpt}

{article.author_display}

        )
    }
}
<|endoftext|>


<commit_before>'use strict';

var React = require('react');
var t = require('tcomb-validation');
var Str = t.Str;
var Bool = t.Bool;
var Func = t.Func;
var Obj = t.Obj;
var maybe = t.maybe;
var list = t.list;
var struct = t.struct;
var union = t.union;

var ReactElement = t.irriducible('ReactElement', React.isValidElement);

var Value = union([t.Nil, Str, Bool], 'Value');

var Label = union([Str, ReactElement], 'Label');

var Option = t.struct({
  disabled: maybe(Bool),
  text: Str,
  value: Str
}, 'Option');

var OptGroup = t.struct({
  disabled: maybe(Bool),
  label: Str,
  options: list(Option)
}, 'OptGroup');

var SelectOption = union([Option, OptGroup], 'SelectOption');

SelectOption.dispatch = function (x) {
  if (x.hasOwnProperty('label')) { return OptGroup; }
  return Option;
};

var TypeAttr = t.enums.of('textarea hidden text password color date datetime datetime-local email month number range search tel time url week', 'TypeAttr');

var Textbox = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),    // should be disabled
  error: maybe(Label),      // should show an error
  hasError: maybe(Bool),    // if true should show an error state
  help: maybe(Label),       // should show an help message
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: maybe(Label),      // should show a label
  name: Str,                // should use this as name attribute
  onChange: Func,           // should call this function with the changed value
  placeholder: maybe(Str),  // should show a placeholder
  type: TypeAttr,           // should use this as type attribute
  value: maybe(Str)                // should use this as value attribute
}, 'Textbox');

var Checkbox = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: Label,             // checkboxes must always have a label
  name: Str,
  onChange: Func,
  value: Bool
}, 'Checkbox');

// handle multiple attribute
var SelectValue = union([Str, list(Str)], 'SelectValue');

var Select = struct({
  config: maybe(Obj),
  error: maybe(Label),
  disabled: maybe(Bool),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: maybe(Label),
  multiple: maybe(Bool),
  name: Str,
  onChange: Func,
  options: list(SelectOption),
  value: maybe(SelectValue)
}, 'Select');

var Radio = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,
  label: maybe(Label),
  name: Str,
  onChange: Func,
  options: list(Option),
  value: maybe(Str)
}, 'Radio');

var StructValue = t.dict(Str, Value, 'StructValue');

var Struct = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  help: maybe(Label),
  hasError: maybe(Bool),
  inputs: t.dict(Str, ReactElement),
  label: maybe(Label),
  order: list(Label),
  value: maybe(StructValue)
}, 'Struct');

var Button = struct({
  click: Func,
  label: Str
}, 'Button');

var ListItem = struct({
  buttons: list(Button),
  input: ReactElement,
  key: Str
}, 'ListItem');

var List = struct({
  add: maybe(Button),
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  items: list(ListItem),
  label: maybe(Label),
  value: maybe(list(Value))
}, 'List');

module.exports = {
  Label: Label,
  Textbox: Textbox,
  Checkbox: Checkbox,
  Option: Option,
  OptGroup: OptGroup,
  Select: Select,
  Radio: Radio,
  Struct: Struct,
  List: List
};<commit_msg>too strict...<commit_after>'use strict';

var React = require('react');
var t = require('tcomb-validation');
var Str = t.Str;
var Bool = t.Bool;
var Func = t.Func;
var Obj = t.Obj;
var maybe = t.maybe;
var list = t.list;
var struct = t.struct;
var union = t.union;

var ReactElement = t.irriducible('ReactElement', React.isValidElement);

var Value = union([t.Nil, Str, Bool], 'Value');

var Label = union([Str, ReactElement], 'Label');

var Option = t.struct({
  disabled: maybe(Bool),
  text: Str,
  value: Str
}, 'Option');

var OptGroup = t.struct({
  disabled: maybe(Bool),
  label: Str,
  options: list(Option)
}, 'OptGroup');

var SelectOption = union([Option, OptGroup], 'SelectOption');

SelectOption.dispatch = function (x) {
  if (x.hasOwnProperty('label')) { return OptGroup; }
  return Option;
};

var TypeAttr = t.enums.of('textarea hidden text password color date datetime datetime-local email month number range search tel time url week', 'TypeAttr');

var Textbox = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),    // should be disabled
  error: maybe(Label),      // should show an error
  hasError: maybe(Bool),    // if true should show an error state
  help: maybe(Label),       // should show an help message
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: maybe(Label),      // should show a label
  name: Str,                // should use this as name attribute
  onChange: Func,           // should call this function with the changed value
  placeholder: maybe(Str),  // should show a placeholder
  type: TypeAttr,           // should use this as type attribute
  value: maybe(Str)                // should use this as value attribute
}, 'Textbox');

var Checkbox = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: Label,             // checkboxes must always have a label
  name: Str,
  onChange: Func,
  value: Bool
}, 'Checkbox');

// handle multiple attribute
var SelectValue = union([Str, list(Str)], 'SelectValue');

var Select = struct({
  config: maybe(Obj),
  error: maybe(Label),
  disabled: maybe(Bool),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,                  // should use this as id attribute and as htmlFor label attribute
  label: maybe(Label),
  multiple: maybe(Bool),
  name: Str,
  onChange: Func,
  options: list(SelectOption),
  value: maybe(SelectValue)
}, 'Select');

var Radio = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  id: Str,
  label: maybe(Label),
  name: Str,
  onChange: Func,
  options: list(Option),
  value: maybe(Str)
}, 'Radio');

var StructValue = t.dict(Str, t.Any, 'StructValue');

var Struct = struct({
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  help: maybe(Label),
  hasError: maybe(Bool),
  inputs: t.dict(Str, ReactElement),
  label: maybe(Label),
  order: list(Label),
  value: maybe(StructValue)
}, 'Struct');

var Button = struct({
  click: Func,
  label: Str
}, 'Button');

var ListItem = struct({
  buttons: list(Button),
  input: ReactElement,
  key: Str
}, 'ListItem');

var List = struct({
  add: maybe(Button),
  config: maybe(Obj),
  disabled: maybe(Bool),
  error: maybe(Label),
  hasError: maybe(Bool),
  help: maybe(Label),
  items: list(ListItem),
  label: maybe(Label),
  value: maybe(list(t.Any))
}, 'List');

module.exports = {
  Label: Label,
  Textbox: Textbox,
  Checkbox: Checkbox,
  Option: Option,
  OptGroup: OptGroup,
  Select: Select,
  Radio: Radio,
  Struct: Struct,
  List: List
};<|endoftext|>


<commit_before>/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * 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.
 */

/**
 * @fileoverview Gulp task for closure-compiler. Sends multiple input files
 * into the compile method of Closure Compiler. This will yield a single
 * vinyl file as output. Every input file includes contents, path and optional
 * sourcemap.
 */

'use strict';

/**
 * Convert keys in the form "--foo_bar" or "zing_foo" to "fooBar" or "zingFoo", respectively.
 *
 * @param {string} key to convert
 * @return {string}
 */
function cleanupOptionKey(key) {
  // replace "_foo" with "Foo"
  key = key.replace(/_(\w)/g, match => match[1].toUpperCase());

  // remove leading dashes
  key = key.replace(/^--/, '');

  return key;
}

/**
 * @return {function(Object<string>=, Object<string>=):Object}
 */
module.exports = function() {
  const compile = require('../compile');
  const logger = require('../logger');
  const gutil = require('gulp-util');
  const PluginError = gutil.PluginError;
  const Transform = require('stream').Transform;
  const PLUGIN_NAME = 'gulp-google-closure-compiler-js';
  const DEFAULT_OUTPUT_PATH = 'compiled.js';
  const path = require('path');

  class CompilationStream extends Transform {
    constructor(compilationOptions, pluginOptions) {
      super({objectMode: true});

      this.compilationOptions_ = compilationOptions;
      this.logger_ = pluginOptions.logger || gutil.log;
      this.pluginName_ = pluginOptions.pluginName || PLUGIN_NAME;

      this.fileList_ = [];
    }

    _transform(file, enc, cb) {
      if (file.isNull()) {
        // Ignore empty files.
      } else if (file.isStream()) {
        this.emit('error', new PluginError(this.pluginName_, 'Streaming not supported'));
      } else {
        this.fileList_.push(file);
      }
      cb();
    }

    _flush(cb) {
      const options = {};
      for (const k in this.compilationOptions_) {
        options[cleanupOptionKey(k)] = this.compilationOptions_[k];
      }
      options.jsCode = (options.jsCode || []).concat(this.fileList_.map(file => {
        return {
          // TODO(samthor): It's not clear we always want to have modules rooted 'here'
          path: path.relative(process.cwd(), file.path),
          src: file.contents.toString(),
          sourceMap: file.sourceMap ? JSON.stringify(file.sourceMap) : undefined,
        };
      }));

      const outputFile = options.jsOutputFile;
      delete options.jsOutputFile;

      const output = compile(options);
      if (logger(options, output, this.logger_.warn ? this.logger_.warn : this.logger_)) {
        const message = `Compilation error, ${output.errors.length} errors`;
        this.emit('error', new PluginError(this.pluginName_, message));
      }

      const file = new gutil.File({
        path: outputFile || DEFAULT_OUTPUT_PATH,
        contents: new Buffer(output.compiledCode),
      });
      if (output.sourceMap) {
        file.sourceMap = JSON.parse(output.sourceMap);
      }
      this.push(file);

      cb();
    }
  };

  return function(compilationOptions={}, pluginOptions={}) {
    return new CompilationStream(compilationOptions, pluginOptions);
  };
};
<commit_msg>depend on vinyl directly<commit_after>/*
 * Copyright 2016 The Closure Compiler Authors.
 *
 * 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.
 */

/**
 * @fileoverview Gulp task for closure-compiler. Sends multiple input files
 * into the compile method of Closure Compiler. This will yield a single
 * vinyl file as output. Every input file includes contents, path and optional
 * sourcemap.
 */

'use strict';

/**
 * Convert keys in the form "--foo_bar" or "zing_foo" to "fooBar" or "zingFoo", respectively.
 *
 * @param {string} key to convert
 * @return {string}
 */
function cleanupOptionKey(key) {
  // replace "_foo" with "Foo"
  key = key.replace(/_(\w)/g, match => match[1].toUpperCase());

  // remove leading dashes
  key = key.replace(/^--/, '');

  return key;
}

/**
 * @return {function(Object<string>=, Object<string>=):Object}
 */
module.exports = function() {
  const compile = require('../compile');
  const logger = require('../logger');
  const gutil = require('gulp-util');
  const path = require('path');
  const File = require('vinyl');
  const PluginError = gutil.PluginError;
  const Transform = require('stream').Transform;
  const PLUGIN_NAME = 'gulp-google-closure-compiler-js';
  const DEFAULT_OUTPUT_PATH = 'compiled.js';

  class CompilationStream extends Transform {
    constructor(compilationOptions, pluginOptions) {
      super({objectMode: true});

      this.compilationOptions_ = compilationOptions;
      this.logger_ = pluginOptions.logger || gutil.log;
      this.pluginName_ = pluginOptions.pluginName || PLUGIN_NAME;

      this.fileList_ = [];
    }

    _transform(file, enc, cb) {
      if (file.isNull()) {
        // Ignore empty files.
      } else if (file.isStream()) {
        this.emit('error', new PluginError(this.pluginName_, 'Streaming not supported'));
      } else {
        this.fileList_.push(file);
      }
      cb();
    }

    _flush(cb) {
      const options = {};
      for (const k in this.compilationOptions_) {
        options[cleanupOptionKey(k)] = this.compilationOptions_[k];
      }
      options.jsCode = (options.jsCode || []).concat(this.fileList_.map(file => {
        return {
          // TODO(samthor): It's not clear we always want to have modules rooted 'here'
          path: path.relative(process.cwd(), file.path),
          src: file.contents.toString(),
          sourceMap: file.sourceMap ? JSON.stringify(file.sourceMap) : undefined,
        };
      }));

      const outputFile = options.jsOutputFile;
      delete options.jsOutputFile;

      const output = compile(options);
      if (logger(options, output, this.logger_.warn ? this.logger_.warn : this.logger_)) {
        const message = `Compilation error, ${output.errors.length} errors`;
        this.emit('error', new PluginError(this.pluginName_, message));
      }

      const file = new File({
        path: outputFile || DEFAULT_OUTPUT_PATH,
        contents: new Buffer(output.compiledCode),
      });
      if (output.sourceMap) {
        file.sourceMap = JSON.parse(output.sourceMap);
      }
      this.push(file);

      cb();
    }
  };

  return function(compilationOptions={}, pluginOptions={}) {
    return new CompilationStream(compilationOptions, pluginOptions);
  };
};
<|endoftext|>


<commit_before>/*
 * Copyright 2015 IBM Corp.
 *
 * 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.
 */

var RDD = require('../rdd/RDD.js');
var Utils = require('../utils.js');

var DataFrame = require('./DataFrame.js');
var DataFrameReader = require('./DataFrameReader.js');

/**
 * @constructor
 * @memberof module:eclairjs/sql
 * @classdesc  The entry point for working with structured data (rows and columns) in Spark.
 * Allows the creation of DataFrame objects as well as the execution of SQL queries.
 * @param {module:eclairjs.SparkContext}
 * @since EclairJS 0.1 Spark  1.0.0
 */
function SQLContext(SparkContext) {
  this.context = SparkContext;

  this.kernelP = this.context.kernelP;

  var self = this;

  var args = {
    target: SQLContext,
    args: [{value: SparkContext}],
    kernelP: this.kernelP
  };

  this.refIdP = Utils.generateConstructor(args);
}

/**
 * Creates a DataFrame from RDD of Rows using the schema
 * @param {module:eclairjs/rdd.RDD[]} rowRDD -
 * @param {module:eclairjs/sql/types.StructType} schema -
 * @returns {module:eclairjs/sql.DataFrame}
 */
SQLContext.prototype.createDataFrame = function(rowRDD, schema) {
  var args = {
    target: this,
    method: 'createDataFrame',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame

  };

  return Utils.generate(args);
};

/**
 * Creates a {@link DataFrame} from RDD of JSON
 * @param {{module:eclairjs.RDD<object>}    RDD of JSON
 * @param {object} schema - object with keys corresponding to JSON field names (or getter functions), and values indicating Datatype
 * @returns {module:eclairjs/sql.DataFrame}
 * @example
 * var df = sqlContext.createDataFrame([{id:1,"name":"jim"},{id:2,"name":"tom"}], {"id":"Integer","name","String"});
 *
 */
SQLContext.prototype.createDataFrameFromJson = function(rowRDD, schema) {
  var args = {
    target: this,
    method: 'createDataFrameFromJson',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame

  };

  return Utils.generate(args);
};

/**
 * Returns DataFrameReader
 * @returns {module:eclairjs/sql.DataFrameReader}
 */
SQLContext.prototype.read = function() {
  var args = {
    target: this,
    method: 'read',
    returnType: DataFrameReader
  };

  return Utils.generate(args);
};

/**
 * Returns DataFrame
 * @param {string} sqlString
 * @returns {module:eclairjs/sql.DataFrame}
 */
SQLContext.prototype.sql = function(sqlString) {
  var args = {
    target: this,
    method: 'sql',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame
  };

  return Utils.generate(args);
};

SQLContext.moduleLocation = '/sql/SQLContext';

module.exports = SQLContext;
<commit_msg>implement SQLContext.table<commit_after>/*
 * Copyright 2015 IBM Corp.
 *
 * 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.
 */

var RDD = require('../rdd/RDD.js');
var Utils = require('../utils.js');

var DataFrame = require('./DataFrame.js');
var DataFrameReader = require('./DataFrameReader.js');

/**
 * @constructor
 * @memberof module:eclairjs/sql
 * @classdesc  The entry point for working with structured data (rows and columns) in Spark.
 * Allows the creation of DataFrame objects as well as the execution of SQL queries.
 * @param {module:eclairjs.SparkContext}
 * @since EclairJS 0.1 Spark  1.0.0
 */
function SQLContext(SparkContext) {
  this.context = SparkContext;

  this.kernelP = this.context.kernelP;

  var self = this;

  var args = {
    target: SQLContext,
    args: [{value: SparkContext}],
    kernelP: this.kernelP
  };

  this.refIdP = Utils.generateConstructor(args);
}

/**
 * Returns the specified table as a DataFrame.
 * @param {string} tableName
 * @returns {module:eclairjs/sql.DataFrame}
 */
SQLContext.prototype.table = function(name) {
  var args = {
    target: this,
    method: 'table',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame

  };

  return Utils.generate(args);
};

/**
 * Creates a DataFrame from RDD of Rows using the schema
 * @param {module:eclairjs/rdd.RDD[]} rowRDD -
 * @param {module:eclairjs/sql/types.StructType} schema -
 * @returns {module:eclairjs/sql.DataFrame}
 */
SQLContext.prototype.createDataFrame = function(rowRDD, schema) {
  var args = {
    target: this,
    method: 'createDataFrame',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame

  };

  return Utils.generate(args);
};

/**
 * Creates a {@link DataFrame} from RDD of JSON
 * @param {{module:eclairjs.RDD<object>}    RDD of JSON
 * @param {object} schema - object with keys corresponding to JSON field names (or getter functions), and values indicating Datatype
 * @returns {module:eclairjs/sql.DataFrame}
 * @example
 * var df = sqlContext.createDataFrame([{id:1,"name":"jim"},{id:2,"name":"tom"}], {"id":"Integer","name","String"});
 *
 */
SQLContext.prototype.createDataFrameFromJson = function(rowRDD, schema) {
  var args = {
    target: this,
    method: 'createDataFrameFromJson',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame

  };

  return Utils.generate(args);
};

/**
 * Returns DataFrameReader
 * @returns {module:eclairjs/sql.DataFrameReader}
 */
SQLContext.prototype.read = function() {
  var args = {
    target: this,
    method: 'read',
    returnType: DataFrameReader
  };

  return Utils.generate(args);
};

/**
 * Returns DataFrame
 * @param {string} sqlString
 * @returns {module:eclairjs/sql.DataFrame}
 */
SQLContext.prototype.sql = function(sqlString) {
  var args = {
    target: this,
    method: 'sql',
    args: Utils.wrapArguments(arguments),
    returnType: DataFrame
  };

  return Utils.generate(args);
};

SQLContext.moduleLocation = '/sql/SQLContext';

module.exports = SQLContext;
<|endoftext|>


<commit_before>var http = require('http');
var connect = require('connect');

var config = require('./config.js').provision;
var dataSrv = require('./DataSrv');
var dataSrvBl = require('./DataSrvBlocking');
var validate = require('./validate');

var app = connect();

app.use(connect.favicon());

app.use(connect.query());

app.use(connect.bodyParser());

app.use('/block', function (req, res) {
    "use strict";
    insert(req, res, dataSrvBl.blocking_push, validate.errors_trans);
});

app.use('/', function (req, res) {
    "use strict";
    insert(req, res, dataSrv.push_transaction, validate.errors_trans);
});

app.listen(config.port);

function insert(req, res, push, validate) {
    "use strict";
    console.log(req.body);

    var errors = validate(req.body);

    if (errors.length === 0) {
        push(req.body, function (err, trans_id) {
            if (err) {
                res.writeHead(500, {'content-type':'application/json'});
                res.write(JSON.stringify({error:err}));
                res.end();
            }
            else {
                res.writeHead(200, {'content-type':'application/json'});
                res.write(JSON.stringify({id:trans_id}));
                res.end();
            }
        });
    }
    else {
        res.writeHead(400, {'content-type':'application/json'});
        res.write(JSON.stringify({error:errors}));
        res.end();
    }
}<commit_msg>express<commit_after>var express = require('express');

var config = require('./config.js').provision;
var dataSrv = require('./DataSrv');
var dataSrvBl = require('./DataSrvBlocking');
var validate = require('./validate');

var app = express.createServer();

app.use(express.favicon());

app.use(express.query());

app.use(express.bodyParser());

app.post('/block', function (req, res) {
    "use strict";
    insert(req, res, dataSrvBl.blocking_push, validate.errors_trans);
});

app.post('/', function (req, res) {
    "use strict";
    insert(req, res, dataSrv.push_transaction, validate.errors_trans);
});

app.listen(config.port);

function insert(req, res, push, validate) {
    "use strict";
    console.log(req.body);

    var errors = validate(req.body);

    if (errors.length === 0) {
        push(req.body, function (err, trans_id) {
            if (err) {
                res.send({error:[err]}, 500);
            }
            else {
                res.send({id:trans_id});
            }
        });
    }
    else {
        res.send({error:errors}, 400);
    }
}<|endoftext|>


<commit_before>const React = require('react');
const { Tabs, Tab } = require('material-ui/Tabs');
const Styles = require('./styles.scss');

class Footer extends React.Component {

    static propTypes = {
        navigate: React.PropTypes.func.isRequired
    }

    constructor(props, context) {

        super(props, context);

        // this.renderRatings = this._renderRatings.bind(this);
        // this.toggleRateBeerDialog = this._toggleRateBeerDialog.bind(this);
        // this.selectRating = this._selectRating.bind(this);
        this.handleActive = this._handleActive.bind(this);
    }

    _handleActive(tab) {

        const route = tab.props['data-route'];
        console.log(route);
        console.log(this);
        console.log(this.props);
        this.props.navigate(route);
    }

    render() {

        return (
            <Tabs className={Styles.footer}>
                <Tab label='ON TAP' data-route='/' onActive={this.handleActive} />
                <Tab label='Camera' data-route='/camera' onActive={this.handleActive} />
            </Tabs>
        );
    }
}

module.exports = Footer;
<commit_msg>cleanup<commit_after>const React = require('react');
const { Tabs, Tab } = require('material-ui/Tabs');
const Styles = require('./styles.scss');

class Footer extends React.Component {

    static propTypes = {
        navigate: React.PropTypes.func.isRequired
    }

    constructor(props, context) {

        super(props, context);

        this.handleActive = this._handleActive.bind(this);
    }

    _handleActive(tab) {

        const route = tab.props['data-route'];
        console.log(route);
        console.log(this);
        console.log(this.props);
        this.props.navigate(route);
    }

    render() {

        return (
            <Tabs className={Styles.footer}>
                <Tab label='ON TAP' data-route='/' onActive={this.handleActive} />
                <Tab label='Camera' data-route='/camera' onActive={this.handleActive} />
            </Tabs>
        );
    }
}

module.exports = Footer;
<|endoftext|>


<commit_before>const assert = require('assert');
const request = require('./_shared.js').request;
const testTranslator = require('./_shared.js').testTranslator;
const testTranslator2 = require('./_shared.js').testTranslator2;

describe('Get common data API', () => {

  it('should work', (done) => {
    request.get('/api/common').end(
      (err, res) => {
        res.should.have.status(200);
        done();
      }
    )
  });

  it('should take common translators and languages', (done) => {
    request.get('/api/common').end(
      (err, res) => {
        assert.equal(res.body.success, true);
        const translators = res.body.translators;
        const languages = res.body.languages;
        assert.notEqual(undefined, translators.find(elem => elem.id === testTranslator.id))
        assert.notEqual(undefined, translators.find(elem => elem.id === testTranslator2.id))
        assert.notEqual(undefined, languages.find(elem => elem.id === 'rus'))
        assert.notEqual(undefined, languages.find(elem => elem.id === 'eng'))
        done();
      }
    )
  });
});
<commit_msg>Corrected test<commit_after>const assert = require('assert');
const request = require('./_shared.js').request;
const testTranslator = require('./_shared.js').testTranslator;
const testTranslator2 = require('./_shared.js').testTranslator2;

describe('Get common data API', () => {

  it('should work', (done) => {
    request.get('/api/common').end(
      (err, res) => {
        res.should.have.status(200);
        done();
      }
    )
  });

  it('should take common translators and languages', (done) => {
    request.get('/api/common').end(
      (err, res) => {
        assert.equal(res.body.success, true)
        const translators = res.body.translators
        const languages = res.body.languages
        assert.equal(!!translators, true)
        assert.equal(!!languages, true)
        assert.equal(languages.length === 2, true)
        assert.equal(translators.length >= 2, true)
        assert.equal(true, !!translators.find(user => user.id === testTranslator.id))
        assert.equal(true, !!translators.find(user => user.id === testTranslator2.id))
        assert.equal(true, !!languages.find(lang => lang.id === 'rus'))
        assert.equal(true, !!languages.find(lang => lang.id === 'eng'))
        done();
      }
    )
  });
});
<|endoftext|>


<commit_before>
        // lib code
var   server     = require('./completion/server')
    , query      = require('./completion/query')
    , build      = require('./build/build')
    , lint       = require('./linting/lint')
    , decl       = require('./reflect/declaration')
    , state      = require('./haxe-state')
        // lib debugging
    , comp_debug = require('./completion/debug')
    , log        = require('./utils/log')

module.exports = {

    config: require('./haxe-config'),

    failed: false,
    disposables : [],

//Lifecycle

        //This is automatic, don't add anything heavy in here
    activate: function(serialized_state) {

        this.check_dependency().then(function(){

            this._init_internal();
            log.init();
            comp_debug.init();
            server.init();
            query.init();
            lint.init();
            decl.init();
            state.init(serialized_state);

        }.bind(this)).catch(function(e) {

            if(e && e.missing_deps) {
                this.fail(e);
            } else {
                throw e;
            }

        }.bind(this));

    }, //activate

    deactivate:function() {

        if(!this.failed) {
            this._dispose_internal();
            state.dispose();
            query.dispose();
            server.dispose();
            comp_debug.dispose();
            log.dispose();
            decl.dispose();
            lint.dispose();
        }

    }, //deactivate

    serialize: function() {

        if(!this.failed) return state.serialize();

    }, //serialize

    check_dependency: function() {

        var required = ['linter', 'autocomplete-plus', 'language-haxe'];
        return new Promise(function(resolve, reject) {

            var missing = [];
            for(var i = 0; i < required.length; ++i) {
                var req = required[i];
                if(!atom.packages.isPackageLoaded(req)) {
                    missing.push(req);
                }
            }

            if(missing.length) {
                console.log('haxe / missing dependencies', missing);
                reject({ missing_deps:missing });
            } else {
                resolve();
            }

        }); //promise

    }, //check_dependency

    fail: function(e) {

        this.failed = true;
        var message = 'Haxe package is missing dependencies!
';
            message += 'Please install/activate these via Preferences:

';
            message += e.missing_deps.map(function(d){ return '- '+d+' package'; }).join('
');

        atom.notifications.addWarning(message, {dismissable:true});

    }, //fail

//Commands

    set_hxml_file_from_treeview: function(opt) {

        var treeview = atom.packages.getLoadedPackage('tree-view');
        if(!treeview) return;

        treeview = require(treeview.mainModulePath);

        var package_obj = treeview.serialize();
        var file_path = package_obj.selectedPath;

            //we are the consumer now
        state.set_hxml_file( file_path );
        state.set_consumer(null);

    }, //set_hxml_file_from_treeview

    build: function(e) {

            //continue propogation if
            //not set up properly
        if(this.failed) {
            return e.abortKeyBinding();
        }

            //check selectors
        var selectors = atom.config.get('haxe.build_selectors');
            //:todo: resilience
        var list = selectors.split(',');
            list = list.map(function(l) { return l.trim(); });

            //get the consumer selectors
        if(state.consumer && state.consumer.onBuildSelectorQuery) {
            var consumer_list = state.consumer.onBuildSelectorQuery();
            if(consumer_list) {
                list = list.concat(consumer_list);
            }
        }

            //find current scope of file
        var editor = atom.workspace.getActiveTextEditor();
        var scope = editor.getRootScopeDescriptor();
        if(editor && scope && scope.scopes.length) {

                //filter non scoped ones
            var allowed = list.filter(function(item){
                if(scope.scopes.indexOf(item) != -1) {
                    return true;
                }
            });

                //any left?
            if(allowed.length) {
                build.run_build();
            } else {
                var info = ' - scope: ' + scope.scopes.join(', ');
                    info += ' - allowed: ' + list;
                log.msg('build / scope not in allowed selectors (see settings).' + info);
            }

        } //editor + scope

    },

//Providers

        //provides this plugin to the consumers,
        //allowing them to call set_completion_state
        //with options, to config the haxe query completion state
    completion_service:function() {
        return this;
    },

    set_completion_consumer:function( options ) {

        var _str = JSON.stringify(options);

        var handle_err = function(err) {
            log.error('Failed to set completion consumer. ' + _str);
            log.error(err);
            return false;
        }

        if(!options.name || !options.onConsumerLost) {
            return handle_err('required: name and onConsumerLost(callback) properties');
        }

        if(options.hxml_content && options.hxml_file) {
            return handle_err('error: hxml_content or hxml_file, not both.');
        }

        if(options.hxml_content && !options.hxml_cwd) {
            return handle_err('required: hxml_cwd is needed when giving hxml_content');
        }

        log.msg('set consumer: ' + _str);

        state.set_consumer(options);

        return true;

    }, //set_completion_consumer

        //handles the completion provider
        //for autocomplete-plus
    provide: function() {
        return require('./completion/provider');
    },

//Internal conveniences

    _init_commands:function() {

        this._command('build',
            this.build.bind(this) );

        this._command('toggle-log-view',
            log.toggle.bind(log) );

        this._command('reset-server',
            server.reset.bind(server) );

        this._command('stop-server',
            server.stop.bind(server) );

        this._command('toggle-completion-debug',
            comp_debug.toggle.bind(comp_debug) );

        this._command('set-hxml-file',
            this.set_hxml_file_from_treeview.bind(this) );

        this._command('clear-project',
            state.unset.bind(state) );

        this._command('go-to-declaration',
            decl.jump.bind(decl), 'symbols-view' );

    }, //_init_commands

    _init_internal:function() {

        this._init_commands();

    }, //

    _dispose_internal:function() {

        for(var i = 0; i < this.disposables.length; ++i) {
            this.disposables[i].dispose();
        }

        this.disposables = [];

    }, //

    _command:function(name, func, module) {

        if (module == null) {
            module = 'haxe';
        }

        var cmd = atom.commands.add('atom-workspace', module+':'+name, func);
        this.disposables.push(cmd);

        return cmd;
    } //

} //module.exports
<commit_msg>Fix uncaught error when pressing CTRL + B with no editor (ie. settings view)<commit_after>
        // lib code
var   server     = require('./completion/server')
    , query      = require('./completion/query')
    , build      = require('./build/build')
    , lint       = require('./linting/lint')
    , decl       = require('./reflect/declaration')
    , state      = require('./haxe-state')
        // lib debugging
    , comp_debug = require('./completion/debug')
    , log        = require('./utils/log')

module.exports = {

    config: require('./haxe-config'),

    failed: false,
    disposables : [],

//Lifecycle

        //This is automatic, don't add anything heavy in here
    activate: function(serialized_state) {

        this.check_dependency().then(function(){

            this._init_internal();
            log.init();
            comp_debug.init();
            server.init();
            query.init();
            lint.init();
            decl.init();
            state.init(serialized_state);

        }.bind(this)).catch(function(e) {

            if(e && e.missing_deps) {
                this.fail(e);
            } else {
                throw e;
            }

        }.bind(this));

    }, //activate

    deactivate:function() {

        if(!this.failed) {
            this._dispose_internal();
            state.dispose();
            query.dispose();
            server.dispose();
            comp_debug.dispose();
            log.dispose();
            decl.dispose();
            lint.dispose();
        }

    }, //deactivate

    serialize: function() {

        if(!this.failed) return state.serialize();

    }, //serialize

    check_dependency: function() {

        var required = ['linter', 'autocomplete-plus', 'language-haxe'];
        return new Promise(function(resolve, reject) {

            var missing = [];
            for(var i = 0; i < required.length; ++i) {
                var req = required[i];
                if(!atom.packages.isPackageLoaded(req)) {
                    missing.push(req);
                }
            }

            if(missing.length) {
                console.log('haxe / missing dependencies', missing);
                reject({ missing_deps:missing });
            } else {
                resolve();
            }

        }); //promise

    }, //check_dependency

    fail: function(e) {

        this.failed = true;
        var message = 'Haxe package is missing dependencies!
';
            message += 'Please install/activate these via Preferences:

';
            message += e.missing_deps.map(function(d){ return '- '+d+' package'; }).join('
');

        atom.notifications.addWarning(message, {dismissable:true});

    }, //fail

//Commands

    set_hxml_file_from_treeview: function(opt) {

        var treeview = atom.packages.getLoadedPackage('tree-view');
        if(!treeview) return;

        treeview = require(treeview.mainModulePath);

        var package_obj = treeview.serialize();
        var file_path = package_obj.selectedPath;

            //we are the consumer now
        state.set_hxml_file( file_path );
        state.set_consumer(null);

    }, //set_hxml_file_from_treeview

    build: function(e) {

            //continue propogation if
            //not set up properly
        if(this.failed) {
            return e.abortKeyBinding();
        }

            //check selectors
        var selectors = atom.config.get('haxe.build_selectors');
            //:todo: resilience
        var list = selectors.split(',');
            list = list.map(function(l) { return l.trim(); });

            //get the consumer selectors
        if(state.consumer && state.consumer.onBuildSelectorQuery) {
            var consumer_list = state.consumer.onBuildSelectorQuery();
            if(consumer_list) {
                list = list.concat(consumer_list);
            }
        }

            //find current scope of file
        var editor = atom.workspace.getActiveTextEditor();
        var scope = editor ? editor.getRootScopeDescriptor() : null;
        if(editor && scope && scope.scopes.length) {

                //filter non scoped ones
            var allowed = list.filter(function(item){
                if(scope.scopes.indexOf(item) != -1) {
                    return true;
                }
            });

                //any left?
            if(allowed.length) {
                build.run_build();
            } else {
                var info = ' - scope: ' + scope.scopes.join(', ');
                    info += ' - allowed: ' + list;
                log.msg('build / scope not in allowed selectors (see settings).' + info);
            }

        } //editor + scope

    },

//Providers

        //provides this plugin to the consumers,
        //allowing them to call set_completion_state
        //with options, to config the haxe query completion state
    completion_service:function() {
        return this;
    },

    set_completion_consumer:function( options ) {

        var _str = JSON.stringify(options);

        var handle_err = function(err) {
            log.error('Failed to set completion consumer. ' + _str);
            log.error(err);
            return false;
        }

        if(!options.name || !options.onConsumerLost) {
            return handle_err('required: name and onConsumerLost(callback) properties');
        }

        if(options.hxml_content && options.hxml_file) {
            return handle_err('error: hxml_content or hxml_file, not both.');
        }

        if(options.hxml_content && !options.hxml_cwd) {
            return handle_err('required: hxml_cwd is needed when giving hxml_content');
        }

        log.msg('set consumer: ' + _str);

        state.set_consumer(options);

        return true;

    }, //set_completion_consumer

        //handles the completion provider
        //for autocomplete-plus
    provide: function() {
        return require('./completion/provider');
    },

//Internal conveniences

    _init_commands:function() {

        this._command('build',
            this.build.bind(this) );

        this._command('toggle-log-view',
            log.toggle.bind(log) );

        this._command('reset-server',
            server.reset.bind(server) );

        this._command('stop-server',
            server.stop.bind(server) );

        this._command('toggle-completion-debug',
            comp_debug.toggle.bind(comp_debug) );

        this._command('set-hxml-file',
            this.set_hxml_file_from_treeview.bind(this) );

        this._command('clear-project',
            state.unset.bind(state) );

        this._command('go-to-declaration',
            decl.jump.bind(decl), 'symbols-view' );

    }, //_init_commands

    _init_internal:function() {

        this._init_commands();

    }, //

    _dispose_internal:function() {

        for(var i = 0; i < this.disposables.length; ++i) {
            this.disposables[i].dispose();
        }

        this.disposables = [];

    }, //

    _command:function(name, func, module) {

        if (module == null) {
            module = 'haxe';
        }

        var cmd = atom.commands.add('atom-workspace', module+':'+name, func);
        this.disposables.push(cmd);

        return cmd;
    } //

} //module.exports
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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.

/**
 * Builds the Shopping Results Page UI by integrating product results from
 * Google Shopping into the webpage.
 */
async function buildShoppingResultsUI() {
  // Make a GET request to '/photo-shopping-request' to scrape the Google Shopping
  // search query results. The request returns a JSON with data about each product
  // from the Google Shopping results page.

  // Build the URL to be fetched - add parameters to identify the uploaded photo.
  const fetchURL =
      `/photo-shopping-request`;

  const response = await fetch(fetchURL)
      .catch((error) => {
        console.warn(error);
        return new Response(JSON.stringify({
          code: error.response.status,
          message: `Failed to fetch ${fetchURL}`,
        }));
      });

  if (!response.ok) {
    return Promise.reject(response);
  }

  const products = await response.json();

  // Integrate the products into the webpage.
  products.forEach(product => {
    // Create an HTML node for the item container.
    let $productContainer = $('
', {class: 'col-md-4'});

    // Get the HTML content for the container.
    const productElementHTML = getProductElementHTML(product.title,
                                                     product.imageLink,
                                                     product.priceAndSeller,
                                                     product.link,
                                                     product.shippingPrice);

    // Load the content using jQuery's append.
    $productContainer.append(productElementHTML);

    // Add the container to the results page, into the corresponding product wrapper.
    $('#shopping-results-wrapper').append($productContainer);
  });
}

/**
 * Returns the HTML content for a product container, based on the arguments.
 */
function getProductElementHTML(productTitle,
                               productImageLink,
                               productPriceAndSeller,
                               productLink,
                               productShippingPrice) {
  return `

${productTitle}

${productPriceAndSeller}

                  <button type="button"
                          class="btn btn-sm btn-outline-secondary"
                          onclick="window.location.href='${productLink}'">
                    View
                  </button>

                ${productShippingPrice}

`;
}

buildShoppingResultsUI();
<commit_msg>Formatting changes<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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.

/**
 * Builds the Shopping Results Page UI by integrating product results from
 * Google Shopping into the webpage.
 */
async function buildShoppingResultsUI() {
  // Make a GET request to '/photo-shopping-request' to scrape the Google Shopping
  // search query results. The request returns a JSON with data about each product
  // from the Google Shopping results page.

  const fetchURL = `/photo-shopping-request`;

  const response = await fetch(fetchURL)
      .catch((error) => {
        console.warn(error);
        return new Response(JSON.stringify({
          code: error.response.status,
          message: `Failed to fetch ${fetchURL}`,
        }));
      });

  if (!response.ok) {
    return Promise.reject(response);
  }

  const products = await response.json();

  // Integrate the products into the webpage.
  products.forEach(product => {
    // Create an HTML node for the item container.
    let $productContainer = $('
', {class: 'col-md-4'});

    // Get the HTML content for the container.
    const productElementHTML = getProductElementHTML(product.title,
                                                     product.imageLink,
                                                     product.priceAndSeller,
                                                     product.link,
                                                     product.shippingPrice);

    // Load the content using jQuery's append.
    $productContainer.append(productElementHTML);

    // Add the container to the results page, into the corresponding product wrapper.
    $('#shopping-results-wrapper').append($productContainer);
  });
}

/**
 * Returns the HTML content for a product container, based on the arguments.
 */
function getProductElementHTML(productTitle,
                               productImageLink,
                               productPriceAndSeller,
                               productLink,
                               productShippingPrice) {
  return `

${productTitle}

${productPriceAndSeller}

                  <button type="button"
                          class="btn btn-sm btn-outline-secondary"
                          onclick="window.location.href='${productLink}'">
                    View
                  </button>

                ${productShippingPrice}

`;
}

buildShoppingResultsUI();
<|endoftext|>


<commit_before>"use strict";

var _ = require('lodash');
var fs = require('fs');
var cheerio = require('cheerio');
var request = require('request');

var queue = require('./queue.js');
var url = require('url');

var re = /\/web\/[\d]+\//;
var default_timestamp = "19950101";
var min_score = 0;
var max_year = 1998;

var pages = require('./pages.js');

var wordfilter = require('wordfilter');

/**
 * run without checking if a page has aleady been scraped
 */
var alwaysRun = function(val) {
    queue.alwaysRun(val);
};

/**
 * load a single URL from the wayback machine at the specified timestamp,
 *  make sure it was relatively valid, then pass to callbacka
 */
var scrapeUrl = function(url, timestamp, cb, onError) {
    var target = "http://web.archive.org/web/" + timestamp + "/" + url;
    console.log(target);
    request(target, function (error, response, body) {
        if ( error || response.statusCode !== 200 ) {
            console.log("ERR: " + error);
            console.log("response: " + response);

            if ( typeof(onError) !== "undefined" ) {
                onError(error, response);
            }
        }

        // make sure there was no error, that this was a 200 response, and that it's HTML-ish
        if (!error && response.statusCode == 200 && response.headers['content-type'].indexOf("text/html") !== -1 ) {
            console.log("got valid response, send it along");
            cb(body, response.request.href);
        }
    });
};

/**
 * remove the wayback header from the output so we don't include it in parsing
 */
var parseAndClean = function(contents) {
    var $ = cheerio.load(contents);
    $("#wm-ipp").remove();
    return $;
};

/**
 * parse out some page attributes for storing later
 */
var getPageAttrs = function(contents) {
    var $ = parseAndClean(contents);
    var attrs = {
        title: $("title").text(),
        generator: ""
    };

    var m = $('meta[name="generator"]').get(0);

    if ( typeof(m) !== "undefined" ) {
        attrs.generator = m.attribs.content;
    }

    return attrs;
};

/**
 * find a list of URLs on the page, remove the wayback prefixes, and return
 */
var urlsToScrape = function(contents, u) {
    var $ = parseAndClean(contents);
    if ( typeof(u) == "undefined" ) {
        u = "";
    }

    return _.uniq(
        _.select(
            $('body').find("a").map(function(i, a) {
                // grab the href from any links. the replace here should strip /web/timestamp/
                var href = undefined;
                if ( a.attribs && a.attribs.href ) {
                    href = a.attribs.href.replace(re, "");
                    try {
                        href = url.resolve(u, href);
                    }
                    catch(e) {
                        console.log("URL error: " + href);
                        console.log(e);
                        href = undefined;
                    }
                }
                return href;
            }),
            function(url) {
                // strip out some obviously junky URLs
                return typeof(url) !== "undefined" &&
                    url.indexOf('http') !== -1 &&
                    url.indexOf('_vti') === -1 &&
                    url.indexOf("yahoo.com/Regional/") === -1 &&
                    url.indexOf("yahoo.com/bin") === -1 &&
                    url.indexOf("yahoo.com/SpaceID") === -1 &&
                    url.length > 1;
            })
    );
};

/**
 * do a couple basic tests to make sure this is a page we might want to render/store. basically
 * make sure it's a 200 and doesn't have an old meta-refresh on it
 */
var invalidPage = function(c) {
    return c.indexOf('
Redirecting to...
') > -1 ||
        c.indexOf('
Wayback Machine doesn't have that page archived.
') > -1 ||
        c.indexOf('HTTP-EQUIV="REFRESH"') > -1 ||
        c.indexOf('frameset') > -1;
};

/**
 * look for a potential redirect url on this page
 */
var findRedirect = function(c) {
    var result = undefined;

    var $ = cheerio.load(c);

    var meta = $("meta[http-equiv]");
    if ( c.indexOf('
Redirecting to...
') > 0 ) {
        result = $(".impatient a").get(0).attribs.href;
        result = result.replace(re, "");
    }
    else if ( meta.length > 0 ) {
        console.log("**** " + meta.get(0).attribs.content);
        console.log("**** " + meta.get(0).attribs.content.split(/; *url=/i)[1]);
        result =  meta.get(0).attribs.content.split(/; *url=/i);
        if ( typeof(result) === 'object' && result.length > 1 ) {
            var dest = result[1].replace(re, "");
            return dest;
        }
        result = undefined; // tmp hack
    }

    return result;
};

/**
 * generate a fairly arbitrary 'score' for the page. Not really used right now
 */
var score = function(url, body) {
    // Scraper scoring
    // Number of buzzwords
    // Number of images
    // Number of tags
    var $ = cheerio.load(body);
    var tags = $("*").length;
    var images = $("img").length;
    var tildes = (url.indexOf("~") !== -1) ? 100 : 0;

    console.log("tags: " + tags + " images: " + images + " tildes: " + tildes);

    return tags + images + tildes;
};

/**
 * scrape the specified URL
 */
var scrape = function(u) {
    console.log("lets scrape", u);

    if ( typeof(u) === "undefined" ) {
        console.log("nothing to scrape!");
        return;
    }

    queue.runOnce(u, function() {
        scrapeUrl(u, default_timestamp, function(body, _url) {
            console.log("actual url: " + _url);
            var tstamp = _url.split('/')[4];
            var year = parseInt(tstamp.substr(0, 4), 10);
            console.log("YEAR: " + year);
            if ( year > max_year ) {
                console.log("oops, this page is from " + year);
                return;
            }

            if ( invalidPage(body) ) {
                console.log("looks like " + u + " didn't return a 200, bye");
                var r = findRedirect(body);
                if ( typeof(r) !== "undefined" ) {
                    console.log("let's scrape redirect " + r + " at some point");
                    queue.add([r]);
                }
                return;
            }

            var page_score = score(u, body);
            var attrs = getPageAttrs(body);

            if ( page_score > min_score ) {
                //console.log("score: " + page_score + " looks good, let's store it");
                var urls = urlsToScrape(body, u);

                if ( urls.length > 0 ) {
                    queue.add(urls);
                }

                //
                // we'll auto-approve pages that don't have bad words on them
                // and don't have long strings of numbers (phone numbers, etc)
                //

                var approved_at;

                var $ = cheerio.load(body.replace(/</g, ' <'));
                var test_text = $("body").first().text().replace(/ +/g, " ");

                if ( test_text.match(/[\(\+]?\b[ 0-9\-\(\)+^'^"^<^>]{10,14}\b/g) === null &&
                     ! wordfilter.blacklisted(test_text) ) {
                    approved_at = new Date();
                }

		            if ( u.indexOf("yahoo.com") === -1 ) {
                    var h = url.parse(u).host;
                    pages.add({
			                  url: u,
                        host: h,
			                  body: body,
			                  score: page_score,
			                  tstamp: tstamp,
			                  title: attrs.title,
			                  generator: attrs.generator,
                        content: body,
                        approved_at: approved_at
                    });
		            }
		            else {
		                console.log("we will scrape yahoo pages but not store them in mysql");
		            }
            }
            else {
                console.log("this page wasn't cool enough, sorry :(");
            }
        });
    });
};

/**
 * grab a url from the queue and scrape it
 */
var run = function() {
    var q = require('./queue.js');
    q.get(function(url) {
        try {
            scrape(url);
        }
        catch(e) {
            console.log(";(", e);
        }
    });
};

/**
 * main loop. run forever!
 */
var loop = function() {
    console.log("ok, running forever!");
    var q = require('./queue.js');
    setInterval(function() {
        run();
    }, 10000);
};

exports.alwaysRun = alwaysRun;
exports.scrapeUrl = scrapeUrl;
exports.urlsToScrape = urlsToScrape;
exports.scrape = scrape;
exports.run = run;
exports.loop = loop;
<commit_msg>add a couple extra words to wordfilter<commit_after>"use strict";

var _ = require('lodash');
var fs = require('fs');
var cheerio = require('cheerio');
var request = require('request');

var queue = require('./queue.js');
var url = require('url');

var re = /\/web\/[\d]+\//;
var default_timestamp = "19950101";
var min_score = 0;
var max_year = 1998;

var pages = require('./pages.js');

var wordfilter = require('wordfilter');
wordfilter.addWords(['nude', 'naked', 'xxx', 'porn']);

/**
 * run without checking if a page has aleady been scraped
 */
var alwaysRun = function(val) {
    queue.alwaysRun(val);
};

/**
 * load a single URL from the wayback machine at the specified timestamp,
 *  make sure it was relatively valid, then pass to callbacka
 */
var scrapeUrl = function(url, timestamp, cb, onError) {
    var target = "http://web.archive.org/web/" + timestamp + "/" + url;
    console.log(target);
    request(target, function (error, response, body) {
        if ( error || response.statusCode !== 200 ) {
            console.log("ERR: " + error);
            console.log("response: " + response);

            if ( typeof(onError) !== "undefined" ) {
                onError(error, response);
            }
        }

        // make sure there was no error, that this was a 200 response, and that it's HTML-ish
        if (!error && response.statusCode == 200 && response.headers['content-type'].indexOf("text/html") !== -1 ) {
            console.log("got valid response, send it along");
            cb(body, response.request.href);
        }
    });
};

/**
 * remove the wayback header from the output so we don't include it in parsing
 */
var parseAndClean = function(contents) {
    var $ = cheerio.load(contents);
    $("#wm-ipp").remove();
    return $;
};

/**
 * parse out some page attributes for storing later
 */
var getPageAttrs = function(contents) {
    var $ = parseAndClean(contents);
    var attrs = {
        title: $("title").text(),
        generator: ""
    };

    var m = $('meta[name="generator"]').get(0);

    if ( typeof(m) !== "undefined" ) {
        attrs.generator = m.attribs.content;
    }

    return attrs;
};

/**
 * find a list of URLs on the page, remove the wayback prefixes, and return
 */
var urlsToScrape = function(contents, u) {
    var $ = parseAndClean(contents);
    if ( typeof(u) == "undefined" ) {
        u = "";
    }

    return _.uniq(
        _.select(
            $('body').find("a").map(function(i, a) {
                // grab the href from any links. the replace here should strip /web/timestamp/
                var href = undefined;
                if ( a.attribs && a.attribs.href ) {
                    href = a.attribs.href.replace(re, "");
                    try {
                        href = url.resolve(u, href);
                    }
                    catch(e) {
                        console.log("URL error: " + href);
                        console.log(e);
                        href = undefined;
                    }
                }
                return href;
            }),
            function(url) {
                // strip out some obviously junky URLs
                return typeof(url) !== "undefined" &&
                    url.indexOf('http') !== -1 &&
                    url.indexOf('_vti') === -1 &&
                    url.indexOf("yahoo.com/Regional/") === -1 &&
                    url.indexOf("yahoo.com/bin") === -1 &&
                    url.indexOf("yahoo.com/SpaceID") === -1 &&
                    url.length > 1;
            })
    );
};

/**
 * do a couple basic tests to make sure this is a page we might want to render/store. basically
 * make sure it's a 200 and doesn't have an old meta-refresh on it
 */
var invalidPage = function(c) {
    return c.indexOf('
Redirecting to...
') > -1 ||
        c.indexOf('
Wayback Machine doesn't have that page archived.
') > -1 ||
        c.indexOf('HTTP-EQUIV="REFRESH"') > -1 ||
        c.indexOf('frameset') > -1;
};

/**
 * look for a potential redirect url on this page
 */
var findRedirect = function(c) {
    var result = undefined;

    var $ = cheerio.load(c);

    var meta = $("meta[http-equiv]");
    if ( c.indexOf('
Redirecting to...
') > 0 ) {
        result = $(".impatient a").get(0).attribs.href;
        result = result.replace(re, "");
    }
    else if ( meta.length > 0 ) {
        console.log("**** " + meta.get(0).attribs.content);
        console.log("**** " + meta.get(0).attribs.content.split(/; *url=/i)[1]);
        result =  meta.get(0).attribs.content.split(/; *url=/i);
        if ( typeof(result) === 'object' && result.length > 1 ) {
            var dest = result[1].replace(re, "");
            return dest;
        }
        result = undefined; // tmp hack
    }

    return result;
};

/**
 * generate a fairly arbitrary 'score' for the page. Not really used right now
 */
var score = function(url, body) {
    // Scraper scoring
    // Number of buzzwords
    // Number of images
    // Number of tags
    var $ = cheerio.load(body);
    var tags = $("*").length;
    var images = $("img").length;
    var tildes = (url.indexOf("~") !== -1) ? 100 : 0;

    console.log("tags: " + tags + " images: " + images + " tildes: " + tildes);

    return tags + images + tildes;
};

/**
 * scrape the specified URL
 */
var scrape = function(u) {
    console.log("lets scrape", u);

    if ( typeof(u) === "undefined" ) {
        console.log("nothing to scrape!");
        return;
    }

    queue.runOnce(u, function() {
        scrapeUrl(u, default_timestamp, function(body, _url) {
            console.log("actual url: " + _url);
            var tstamp = _url.split('/')[4];
            var year = parseInt(tstamp.substr(0, 4), 10);
            console.log("YEAR: " + year);
            if ( year > max_year ) {
                console.log("oops, this page is from " + year);
                return;
            }

            if ( invalidPage(body) ) {
                console.log("looks like " + u + " didn't return a 200, bye");
                var r = findRedirect(body);
                if ( typeof(r) !== "undefined" ) {
                    console.log("let's scrape redirect " + r + " at some point");
                    queue.add([r]);
                }
                return;
            }

            var page_score = score(u, body);
            var attrs = getPageAttrs(body);

            if ( page_score > min_score ) {
                //console.log("score: " + page_score + " looks good, let's store it");
                var urls = urlsToScrape(body, u);

                if ( urls.length > 0 ) {
                    queue.add(urls);
                }

                //
                // we'll auto-approve pages that don't have bad words on them
                // and don't have long strings of numbers (phone numbers, etc)
                //

                var approved_at;

                var $ = cheerio.load(body.replace(/</g, ' <'));
                var test_text = $("body").first().text().replace(/ +/g, " ");

                if ( test_text.match(/[\(\+]?\b[ 0-9\-\(\)+^'^"^<^>]{10,14}\b/g) === null &&
                     ! wordfilter.blacklisted(test_text) ) {
                    approved_at = new Date();
                }

		            if ( u.indexOf("yahoo.com") === -1 ) {
                    var h = url.parse(u).host;
                    pages.add({
			                  url: u,
                        host: h,
			                  body: body,
			                  score: page_score,
			                  tstamp: tstamp,
			                  title: attrs.title,
			                  generator: attrs.generator,
                        content: body,
                        approved_at: approved_at
                    });
		            }
		            else {
		                console.log("we will scrape yahoo pages but not store them in mysql");
		            }
            }
            else {
                console.log("this page wasn't cool enough, sorry :(");
            }
        });
    });
};

/**
 * grab a url from the queue and scrape it
 */
var run = function() {
    var q = require('./queue.js');
    q.get(function(url) {
        try {
            scrape(url);
        }
        catch(e) {
            console.log(";(", e);
        }
    });
};

/**
 * main loop. run forever!
 */
var loop = function() {
    console.log("ok, running forever!");
    var q = require('./queue.js');
    setInterval(function() {
        run();
    }, 10000);
};

exports.alwaysRun = alwaysRun;
exports.scrapeUrl = scrapeUrl;
exports.urlsToScrape = urlsToScrape;
exports.scrape = scrape;
exports.run = run;
exports.loop = loop;
<|endoftext|>


<commit_before>var expect = require('chai').expect;

var compressor = require('../lib/compressor')
  , Compressor = compressor.Compressor
  , Decompressor = compressor.Decompressor;

var test_integers = [{
  N: 5,
  I: 10,
  buffer: new Buffer([10])
}, {
  N: 0,
  I: 10,
  buffer: new Buffer([10])
}, {
  N: 5,
  I: 1337,
  buffer: new Buffer([31, 128 + 26, 10])
}, {
  N: 0,
  I: 1337,
  buffer: new Buffer([128 + 57, 10])
}];

var test_strings = [{
  string: new Buffer('abcdefghij', 'utf-8'),
  buffer: new Buffer('0A6162636465666768696A', 'hex')
}, {
  string: new Buffer('éáűőúöüó€', 'utf-8'),
  buffer: new Buffer('13C3A9C3A1C5B1C591C3BAC3B6C3BCC3B3E282AC', 'hex')
}];

var test_headers = [{
  header: {
    name: 3,
    value: new Buffer('/my-example/index.html', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('44' + '162F6D792D6578616D706C652F696E6465782E68746D6C', 'hex')
}, {
  header: {
    name: 12,
    value: new Buffer('my-user-agent', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('4D' + '0D6D792D757365722D6167656E74', 'hex')
}, {
  header: {
    name: new Buffer('x-my-header', 'utf-8'),
    value: new Buffer('first', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('40' + '0B782D6D792D686561646572' + '056669727374', 'hex')
}, {
  header: {
    name: 38,
    value: 38,
    indexing: false
  },
  buffer: new Buffer('A6', 'hex')
}, {
  header: {
    name: 40,
    value: 40,
    indexing: false
  },
  buffer: new Buffer('A8', 'hex')
}, {
  header: {
    name: 3,
    value: new Buffer('/my-example/resources/script.js', 'utf-8'),
    indexing: true,
    substitution: 38
  },
  buffer: new Buffer('0426' + '1F2F6D792D6578616D706C652F7265736F75726365732F7363726970742E6A73', 'hex')
}, {
  header: {
    name: 40,
    value: new Buffer('second', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('5F0A' + '067365636F6E64', 'hex')
}];

// Concatenate buffers into a new buffer
function concat(buffers) {
  var size = 0;
  for (var i = 0; i < buffers.length; i++) {
    size += buffers[i].length;
  }

  var concatenated = new Buffer(size);
  for (var cursor = 0, j = 0; j < buffers.length; cursor += buffers[j].length, j++) {
    buffers[j].copy(concatenated, cursor);
  }

  return concatenated;
}

describe('compressor.js', function() {
  describe('Compressor', function() {
    describe('static method .integer(I, N)', function() {
      it('should return an array of buffers that represent the N-prefix coded I value', function() {
        for (var i = 0; i < test_integers.length; i++) {
          var test = test_integers[i];
          expect(concat(Compressor.integer(test.I, test.N))).to.deep.equal(test.buffer);
        }
      });
    });
    describe('static method .string(stringbuffer)', function() {
      it('should return an array of buffers that represent the encoded form of the string buffer', function() {
        for (var i = 0; i < test_strings.length; i++) {
          var test = test_strings[i];
          expect(concat(Compressor.string(test.string))).to.deep.equal(test.buffer);
        }
      });
    });
    describe('static method .header({ name, value, indexing, substitution })', function() {
      it('should return an array of buffers that represent the encoded form of the header', function() {
        for (var i = 0; i < test_headers.length; i++) {
          var test = test_headers[i];
          expect(concat(Compressor.header(test.header))).to.deep.equal(test.buffer);
        }
      });
    });
  });

  describe('Decompressor', function() {
    describe('static method .integer(buffer, N)', function() {
      it('should return the parsed N-prefix coded number and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_integers.length; i++) {
          var test = test_integers[i];
          test.buffer.cursor = 0;
          expect(Decompressor.integer(test.buffer, test.N)).to.equal(test.I);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
    describe('static method .string(buffer)', function() {
      it('should return the parsed string buffer and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_strings.length; i++) {
          var test = test_strings[i];
          test.buffer.cursor = 0;
          expect(Decompressor.string(test.buffer)).to.deep.equal(test.string);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
    describe('static method .header(buffer)', function() {
      it('should return the parsed header and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_headers.length; i++) {
          var test = test_headers[i];
          test.buffer.cursor = 0;
          expect(Decompressor.header(test.buffer)).to.deep.equal(test.header);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
  });
});
<commit_msg>Adding tests for CompressionContext.equal()<commit_after>var expect = require('chai').expect;

var compressor = require('../lib/compressor')
  , CompressionContext = compressor.CompressionContext
  , Compressor = compressor.Compressor
  , Decompressor = compressor.Decompressor;

var test_integers = [{
  N: 5,
  I: 10,
  buffer: new Buffer([10])
}, {
  N: 0,
  I: 10,
  buffer: new Buffer([10])
}, {
  N: 5,
  I: 1337,
  buffer: new Buffer([31, 128 + 26, 10])
}, {
  N: 0,
  I: 1337,
  buffer: new Buffer([128 + 57, 10])
}];

var test_strings = [{
  string: new Buffer('abcdefghij', 'utf-8'),
  buffer: new Buffer('0A6162636465666768696A', 'hex')
}, {
  string: new Buffer('éáűőúöüó€', 'utf-8'),
  buffer: new Buffer('13C3A9C3A1C5B1C591C3BAC3B6C3BCC3B3E282AC', 'hex')
}];

var test_headers = [{
  header: {
    name: 3,
    value: new Buffer('/my-example/index.html', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('44' + '162F6D792D6578616D706C652F696E6465782E68746D6C', 'hex')
}, {
  header: {
    name: 12,
    value: new Buffer('my-user-agent', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('4D' + '0D6D792D757365722D6167656E74', 'hex')
}, {
  header: {
    name: new Buffer('x-my-header', 'utf-8'),
    value: new Buffer('first', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('40' + '0B782D6D792D686561646572' + '056669727374', 'hex')
}, {
  header: {
    name: 38,
    value: 38,
    indexing: false
  },
  buffer: new Buffer('A6', 'hex')
}, {
  header: {
    name: 40,
    value: 40,
    indexing: false
  },
  buffer: new Buffer('A8', 'hex')
}, {
  header: {
    name: 3,
    value: new Buffer('/my-example/resources/script.js', 'utf-8'),
    indexing: true,
    substitution: 38
  },
  buffer: new Buffer('0426' + '1F2F6D792D6578616D706C652F7265736F75726365732F7363726970742E6A73', 'hex')
}, {
  header: {
    name: 40,
    value: new Buffer('second', 'utf-8'),
    indexing: true
  },
  buffer: new Buffer('5F0A' + '067365636F6E64', 'hex')
}];

// Concatenate buffers into a new buffer
function concat(buffers) {
  var size = 0;
  for (var i = 0; i < buffers.length; i++) {
    size += buffers[i].length;
  }

  var concatenated = new Buffer(size);
  for (var cursor = 0, j = 0; j < buffers.length; cursor += buffers[j].length, j++) {
    buffers[j].copy(concatenated, cursor);
  }

  return concatenated;
}

describe('compressor.js', function() {
  describe('CompressionContext', function() {
    describe('static method .equal([name1, value1], [name2, value2])', function() {
      var equal = CompressionContext.equal;
      it('decides if the two headers are considered equal', function() {
        expect(equal(['name', 'value'], ['name', 'value'])).to.be.equal(true);
        expect(equal(['name', 'value'], ['nAmE', 'value'])).to.be.equal(true);
        expect(equal(['NaMe', 'value'], ['nAmE', 'value'])).to.be.equal(true);
        expect(equal(['name', 'VaLuE'], ['name', 'value'])).to.be.equal(false);
        expect(equal(['NaMe', 'VaLuE'], ['name', 'value'])).to.be.equal(false);
      });
    });
  });

  describe('Compressor', function() {
    describe('static method .integer(I, N)', function() {
      it('should return an array of buffers that represent the N-prefix coded I value', function() {
        for (var i = 0; i < test_integers.length; i++) {
          var test = test_integers[i];
          expect(concat(Compressor.integer(test.I, test.N))).to.deep.equal(test.buffer);
        }
      });
    });
    describe('static method .string(stringbuffer)', function() {
      it('should return an array of buffers that represent the encoded form of the string buffer', function() {
        for (var i = 0; i < test_strings.length; i++) {
          var test = test_strings[i];
          expect(concat(Compressor.string(test.string))).to.deep.equal(test.buffer);
        }
      });
    });
    describe('static method .header({ name, value, indexing, substitution })', function() {
      it('should return an array of buffers that represent the encoded form of the header', function() {
        for (var i = 0; i < test_headers.length; i++) {
          var test = test_headers[i];
          expect(concat(Compressor.header(test.header))).to.deep.equal(test.buffer);
        }
      });
    });
  });

  describe('Decompressor', function() {
    describe('static method .integer(buffer, N)', function() {
      it('should return the parsed N-prefix coded number and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_integers.length; i++) {
          var test = test_integers[i];
          test.buffer.cursor = 0;
          expect(Decompressor.integer(test.buffer, test.N)).to.equal(test.I);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
    describe('static method .string(buffer)', function() {
      it('should return the parsed string buffer and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_strings.length; i++) {
          var test = test_strings[i];
          test.buffer.cursor = 0;
          expect(Decompressor.string(test.buffer)).to.deep.equal(test.string);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
    describe('static method .header(buffer)', function() {
      it('should return the parsed header and increase the cursor property of buffer', function() {
        for (var i = 0; i < test_headers.length; i++) {
          var test = test_headers[i];
          test.buffer.cursor = 0;
          expect(Decompressor.header(test.buffer)).to.deep.equal(test.header);
          expect(test.buffer.cursor).to.equal(test.buffer.length);
        }
      });
    });
  });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import PostsItem from './PostsItem';

class PostsListing extends Component {
  componentDidMount() {
    this.props.fetchPosts();
  }

  render() {
    return (

        {this.props.posts.map(post =>
<PostsItem key={post.id} {...post} />
)}

    );
  }
}

PostsListing.propTypes = {
  fetchPosts: PropTypes.func.isRequired,
  posts: PropTypes.arrayOf(PropTypes.object).isRequired
};

export default PostsListing;
<commit_msg>Update post listing<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import PostsItem from './PostsItem';

class PostsListing extends Component {
  componentDidMount() {
    this.props.fetchPosts();
  }

  render() {
    return (

        {this.props.posts.map(post => (

            <PostsItem {...post} />

)
        )}

    );
  }
}

PostsListing.propTypes = {
  fetchPosts: PropTypes.func.isRequired,
  posts: PropTypes.arrayOf(PropTypes.object).isRequired
};

export default PostsListing;
<|endoftext|>