<commit_before>import * as path from 'path';

import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import HtmlWebpackRemarkPlugin from 'html-webpack-remark-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import SystemBellPlugin from 'system-bell-webpack-plugin';
import CleanPlugin from 'clean-webpack-plugin';
import merge from 'webpack-merge';
import React from 'react';
import ReactDOM from 'react-dom/server';

import App from './demo/App.jsx';
import pkg from './package.json';

import js from 'highlight.js/lib/languages/javascript';

const RENDER_UNIVERSAL = true;
const TARGET = process.env.npm_lifecycle_event;
const ROOT_PATH = __dirname;
const config = {
  paths: {
    readme: path.join(ROOT_PATH, 'README.md'),
    dist: path.join(ROOT_PATH, 'dist'),
    src: path.join(ROOT_PATH, 'src'),
    demo: path.join(ROOT_PATH, 'demo'),
    tests: path.join(ROOT_PATH, 'tests')
  },
  filename: 'boilerplate',
  library: 'Boilerplate'
};
const CSS_PATHS = [
  config.paths.demo,
  path.join(ROOT_PATH, 'style.css'),
  path.join(ROOT_PATH, 'node_modules', 'purecss'),
  path.join(ROOT_PATH, 'node_modules', 'highlight.js', 'styles', 'github.css'),
  path.join(ROOT_PATH, 'node_modules', 'react-ghfork', 'gh-fork-ribbon.ie.css'),
  path.join(ROOT_PATH, 'node_modules', 'react-ghfork', 'gh-fork-ribbon.css')
];
const STYLE_ENTRIES = [
  'purecss',
  'highlight.js/styles/github.css',
  'react-ghfork/gh-fork-ribbon.ie.css',
  'react-ghfork/gh-fork-ribbon.css',
  './demo/main.css',
  './style.css'
];

process.env.BABEL_ENV = TARGET;

const demoCommon = {
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.png', '.jpg']
  },
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: ['eslint'],
        include: [
          config.paths.demo,
          config.paths.src
        ]
      }
    ],
    loaders: [
      {
        test: /\.png$/,
        loader: 'url?limit=100000&mimetype=image/png',
        include: config.paths.demo
      },
      {
        test: /\.jpg$/,
        loader: 'file',
        include: config.paths.demo
      },
      {
        test: /\.json$/,
        loader: 'json',
        include: path.join(ROOT_PATH, 'package.json')
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'start') {
  module.exports = merge(demoCommon, {
    devtool: 'eval-source-map',
    entry: {
      demo: [config.paths.demo].concat(STYLE_ENTRIES)
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"development"'
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        template: 'lib/index_template.ejs',
        inject: false,

        // Context for the template
        name: pkg.name,
        description: pkg.description,
        demonstration: ''
      }),
      new HtmlWebpackRemarkPlugin({
        key: 'documentation',
        file: config.paths.readme,
        languages: {
          js
        }
      }),
      new webpack.HotModuleReplacementPlugin()
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loaders: ['style', 'css'],
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel?cacheDirectory'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    },
    devServer: {
      historyApiFallback: true,
      hot: true,
      inline: true,
      progress: true,
      host: process.env.HOST,
      port: process.env.PORT,
      stats: 'errors-only'
    }
  });
}

function NamedModulesPlugin(options) {
  this.options = options || {};
}
NamedModulesPlugin.prototype.apply = function(compiler) {
  compiler.plugin('compilation', function(compilation) {
    compilation.plugin('before-module-ids', function(modules) {
      modules.forEach(function(module) {
        if(module.id === null && module.libIdent) {
          var id = module.libIdent({
            context: this.options.context || compiler.options.context
          });

          // Skip CSS files since those go through ExtractTextPlugin
          if(!id.endsWith('.css')) {
            module.id = id;
          }
        }
      }, this);
    }.bind(this));
  }.bind(this));
};

if (TARGET === 'gh-pages' || TARGET === 'gh-pages:stats') {
  module.exports = merge(demoCommon, {
    entry: {
      app: config.paths.demo,
      vendors: [
        'react'
      ],
      style: STYLE_ENTRIES
    },
    output: {
      path: './gh-pages',
      filename: '[name].[chunkhash].js',
      chunkFilename: '[chunkhash].js'
    },
    plugins: [
      new CleanPlugin(['gh-pages'], {
        verbose: false
      }),
      new ExtractTextPlugin('[name].[chunkhash].css'),
      new webpack.DefinePlugin({
          // This affects the react lib size
        'process.env.NODE_ENV': '"production"'
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        template: 'lib/index_template.ejs',
        inject: false,

        // Context for the template
        name: pkg.name,
        description: pkg.description,
        demonstration: RENDER_UNIVERSAL ? ReactDOM.renderToString(<App />) : ''
      }),
      new HtmlWebpackRemarkPlugin({
        key: 'documentation',
        file: config.paths.readme,
        languages: {
          js
        }
      }),
      new NamedModulesPlugin(),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      }),
      new webpack.optimize.CommonsChunkPlugin({
        names: ['vendors', 'manifest']
      })
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract('style', 'css'),
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    }
  });
}

// !TARGET === prepush hook for test
if (TARGET === 'test' || TARGET === 'test:tdd' || !TARGET) {
  module.exports = merge(demoCommon, {
    module: {
      preLoaders: [
        {
          test: /\.jsx?$/,
          loaders: ['eslint'],
          include: [
            config.paths.tests
          ]
        }
      ],
      loaders: [
        {
          test: /\.jsx?$/,
          loaders: ['babel?cacheDirectory'],
          include: [
            config.paths.src,
            config.paths.tests
          ]
        }
      ]
    }
  })
}

const distCommon = {
  devtool: 'source-map',
  output: {
    path: config.paths.dist,
    libraryTarget: 'umd',
    library: config.library
  },
  entry: config.paths.src,
  externals: {
    'react': {
      commonjs: 'react',
      commonjs2: 'react',
      amd: 'React',
      root: 'React'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loaders: ['babel'],
        include: config.paths.src
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'dist') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.js'
    }
  });
}

if (TARGET === 'dist:min') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.min.js'
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]
  });
}
<commit_msg>Drop `inject: false` from html-webpack-plugin<commit_after>import * as path from 'path';

import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import HtmlWebpackRemarkPlugin from 'html-webpack-remark-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import SystemBellPlugin from 'system-bell-webpack-plugin';
import CleanPlugin from 'clean-webpack-plugin';
import merge from 'webpack-merge';
import React from 'react';
import ReactDOM from 'react-dom/server';

import App from './demo/App.jsx';
import pkg from './package.json';

import js from 'highlight.js/lib/languages/javascript';

const RENDER_UNIVERSAL = true;
const TARGET = process.env.npm_lifecycle_event;
const ROOT_PATH = __dirname;
const config = {
  paths: {
    readme: path.join(ROOT_PATH, 'README.md'),
    dist: path.join(ROOT_PATH, 'dist'),
    src: path.join(ROOT_PATH, 'src'),
    demo: path.join(ROOT_PATH, 'demo'),
    tests: path.join(ROOT_PATH, 'tests')
  },
  filename: 'boilerplate',
  library: 'Boilerplate'
};
const CSS_PATHS = [
  config.paths.demo,
  path.join(ROOT_PATH, 'style.css'),
  path.join(ROOT_PATH, 'node_modules', 'purecss'),
  path.join(ROOT_PATH, 'node_modules', 'highlight.js', 'styles', 'github.css'),
  path.join(ROOT_PATH, 'node_modules', 'react-ghfork', 'gh-fork-ribbon.ie.css'),
  path.join(ROOT_PATH, 'node_modules', 'react-ghfork', 'gh-fork-ribbon.css')
];
const STYLE_ENTRIES = [
  'purecss',
  'highlight.js/styles/github.css',
  'react-ghfork/gh-fork-ribbon.ie.css',
  'react-ghfork/gh-fork-ribbon.css',
  './demo/main.css',
  './style.css'
];

process.env.BABEL_ENV = TARGET;

const demoCommon = {
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.png', '.jpg']
  },
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: ['eslint'],
        include: [
          config.paths.demo,
          config.paths.src
        ]
      }
    ],
    loaders: [
      {
        test: /\.png$/,
        loader: 'url?limit=100000&mimetype=image/png',
        include: config.paths.demo
      },
      {
        test: /\.jpg$/,
        loader: 'file',
        include: config.paths.demo
      },
      {
        test: /\.json$/,
        loader: 'json',
        include: path.join(ROOT_PATH, 'package.json')
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'start') {
  module.exports = merge(demoCommon, {
    devtool: 'eval-source-map',
    entry: {
      demo: [config.paths.demo].concat(STYLE_ENTRIES)
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"development"'
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        template: 'lib/index_template.ejs',

        // Context for the template
        name: pkg.name,
        description: pkg.description,
        demonstration: ''
      }),
      new HtmlWebpackRemarkPlugin({
        key: 'documentation',
        file: config.paths.readme,
        languages: {
          js
        }
      }),
      new webpack.HotModuleReplacementPlugin()
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loaders: ['style', 'css'],
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel?cacheDirectory'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    },
    devServer: {
      historyApiFallback: true,
      hot: true,
      inline: true,
      progress: true,
      host: process.env.HOST,
      port: process.env.PORT,
      stats: 'errors-only'
    }
  });
}

function NamedModulesPlugin(options) {
  this.options = options || {};
}
NamedModulesPlugin.prototype.apply = function(compiler) {
  compiler.plugin('compilation', function(compilation) {
    compilation.plugin('before-module-ids', function(modules) {
      modules.forEach(function(module) {
        if(module.id === null && module.libIdent) {
          var id = module.libIdent({
            context: this.options.context || compiler.options.context
          });

          // Skip CSS files since those go through ExtractTextPlugin
          if(!id.endsWith('.css')) {
            module.id = id;
          }
        }
      }, this);
    }.bind(this));
  }.bind(this));
};

if (TARGET === 'gh-pages' || TARGET === 'gh-pages:stats') {
  module.exports = merge(demoCommon, {
    entry: {
      app: config.paths.demo,
      vendors: [
        'react'
      ],
      style: STYLE_ENTRIES
    },
    output: {
      path: './gh-pages',
      filename: '[name].[chunkhash].js',
      chunkFilename: '[chunkhash].js'
    },
    plugins: [
      new CleanPlugin(['gh-pages'], {
        verbose: false
      }),
      new ExtractTextPlugin('[name].[chunkhash].css'),
      new webpack.DefinePlugin({
          // This affects the react lib size
        'process.env.NODE_ENV': '"production"'
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        template: 'lib/index_template.ejs',

        // Context for the template
        name: pkg.name,
        description: pkg.description,
        demonstration: RENDER_UNIVERSAL ? ReactDOM.renderToString(<App />) : ''
      }),
      new HtmlWebpackRemarkPlugin({
        key: 'documentation',
        file: config.paths.readme,
        languages: {
          js
        }
      }),
      new NamedModulesPlugin(),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      }),
      new webpack.optimize.CommonsChunkPlugin({
        names: ['vendors', 'manifest']
      })
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract('style', 'css'),
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    }
  });
}

// !TARGET === prepush hook for test
if (TARGET === 'test' || TARGET === 'test:tdd' || !TARGET) {
  module.exports = merge(demoCommon, {
    module: {
      preLoaders: [
        {
          test: /\.jsx?$/,
          loaders: ['eslint'],
          include: [
            config.paths.tests
          ]
        }
      ],
      loaders: [
        {
          test: /\.jsx?$/,
          loaders: ['babel?cacheDirectory'],
          include: [
            config.paths.src,
            config.paths.tests
          ]
        }
      ]
    }
  })
}

const distCommon = {
  devtool: 'source-map',
  output: {
    path: config.paths.dist,
    libraryTarget: 'umd',
    library: config.library
  },
  entry: config.paths.src,
  externals: {
    'react': {
      commonjs: 'react',
      commonjs2: 'react',
      amd: 'React',
      root: 'React'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loaders: ['babel'],
        include: config.paths.src
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'dist') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.js'
    }
  });
}

if (TARGET === 'dist:min') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.min.js'
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]
  });
}
<|endoftext|>


<commit_before>var webpack = require("webpack");

/**
 * This is the Webpack configuration file for local development. It contains
 * local-specific configuration such as the React Hot Loader, as well as:
 *
 * - The entry point of the application
 * - Where the output file should be
 * - Which loaders to use on what files to properly transpile the source
 *
 * For more information, see: http://webpack.github.io/docs/configuration.html
 */
module.exports = {

  // Efficiently evaluate modules with source maps
  devtool: "eval",

  // Set entry point to ./src/main and include necessary files for hot load
  entry:  [
    "webpack-dev-server/client?http://localhost:9090",
    "webpack/hot/only-dev-server",
    "./src/main"
  ],

  // This will not actually create a bundle.js file in ./build. It is used
  // by the dev server for dynamic hot loading.
  output: {
    path: __dirname + "/build/",
    filename: "app.js",
    publicPath: "http://localhost:9090/build/"
  },

  // Necessary plugins for hot load
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],

  // Transform source code using Babel and React Hot Loader
  module: {
    loaders: [
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["react-hot", "babel-loader"]},
      { test: /\.png$/, loader: "url-loader?limit=10000&minetype=image/png" },
      { test: /\.jpg$/, loader: "url-loader?limit=10000&minetype=image/jpg" },
      { test: /\.less$/, loader: "style!css!less" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
      { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" },
    ]
  },

  // Automatically transform files with these extensions
  resolve: {
    extensions: ["", ".js", ".jsx"]
  }
}
<commit_msg>Add autoprefixer-loader to local webpack configuration. #32<commit_after>var webpack = require("webpack");

/**
 * This is the Webpack configuration file for local development. It contains
 * local-specific configuration such as the React Hot Loader, as well as:
 *
 * - The entry point of the application
 * - Where the output file should be
 * - Which loaders to use on what files to properly transpile the source
 *
 * For more information, see: http://webpack.github.io/docs/configuration.html
 */
module.exports = {

  // Efficiently evaluate modules with source maps
  devtool: "eval",

  // Set entry point to ./src/main and include necessary files for hot load
  entry:  [
    "webpack-dev-server/client?http://localhost:9090",
    "webpack/hot/only-dev-server",
    "./src/main"
  ],

  // This will not actually create a bundle.js file in ./build. It is used
  // by the dev server for dynamic hot loading.
  output: {
    path: __dirname + "/build/",
    filename: "app.js",
    publicPath: "http://localhost:9090/build/"
  },

  // Necessary plugins for hot load
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],

  // Transform source code using Babel and React Hot Loader
  module: {
    loaders: [
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ["react-hot", "babel-loader"]},
      { test: /\.png$/, loader: "url-loader?limit=10000&minetype=image/png" },
      { test: /\.jpg$/, loader: "url-loader?limit=10000&minetype=image/jpg" },
      { test: /\.less$/, loader: "style!css!autoprefixer-loader!less!" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff" },
      { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" },
    ]
  },

  // Automatically transform files with these extensions
  resolve: {
    extensions: ["", ".js", ".jsx"]
  }
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var webpack = require("webpack");
var webpackNodeExternals = require('webpack-node-externals');
var config = require("./config");
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
var webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('../isomorphic.config'));
var wds = {
  hostname: process.env.HOSTNAME || "localhost",
  port: process.env.PORT || 8080
};

config.entry.unshift(
  "webpack-dev-server/client?http://" + wds.hostname + ":" + wds.port,
  "webpack/hot/only-dev-server"
);

config.devServer = {
  publicPath: "http://" + wds.hostname + ":" + wds.port + "/",
  hot: true,
  inline: false,
  lazy: false,
  quiet: true,
  noInfo: true,
  headers: {
    "Access-Control-Allow-Origin": "*"
  },
  proxy: {
    '*': 'http://localhost:8000/'
  },
  stats: {
    colors: true
  },
  host: wds.hostname
};

module.exports = _.mergeWith(config, {
  cache: true,
  debug: true,
  devtool: 'cheap-module-eval-source-map',
  output: {
    publicPath: config.devServer.publicPath,
    hotUpdateMainFilename: "update/[hash]/update.json",
    hotUpdateChunkFilename: "update/[hash]/[id].update.js"
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  externals: [
    webpackNodeExternals({
      whitelist: ['webpack/hot/only-dev-server']
    })
  ]
}, function(objValue, srcValue) {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
});
<commit_msg>Fix client webpack config<commit_after>var _ = require('lodash');
var webpack = require("webpack");
var webpackNodeExternals = require('webpack-node-externals');
var config = require("./config");
var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');
var webpackIsomorphicToolsPlugin = new WebpackIsomorphicToolsPlugin(require('../isomorphic.config'));
var wds = {
  hostname: process.env.HOSTNAME || "localhost",
  port: process.env.PORT || 8080
};

config.entry.unshift(
  "webpack-dev-server/client?http://" + wds.hostname + ":" + wds.port,
  "webpack/hot/only-dev-server"
);

config.devServer = {
  publicPath: "http://" + wds.hostname + ":" + wds.port + "/",
  hot: true,
  inline: false,
  lazy: false,
  quiet: true,
  noInfo: true,
  headers: {
    "Access-Control-Allow-Origin": "*"
  },
  proxy: {
    '*': 'http://localhost:8000/'
  },
  stats: {
    colors: true
  },
  host: wds.hostname
};

module.exports = _.mergeWith(config, {
  cache: true,
  debug: true,
  devtool: 'cheap-module-eval-source-map',
  output: {
    publicPath: config.devServer.publicPath,
    hotUpdateMainFilename: "update/[hash]/update.json",
    hotUpdateChunkFilename: "update/[hash]/[id].update.js"
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ]
}, function(objValue, srcValue) {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
});
<|endoftext|>


<commit_before>var URL = require('url'),
    request = require('request'),
    _ = require('underscore'),
    async = require('async'),
    cheerio = require('cheerio'),
    moment = require('moment'),
    columnMap = {
        // 'Name of the Candidate': 'candidate',
        'Filing Date': 'filing_date',
        // 'Name of Committee': 'committee',
        'Party Affiliation': 'party',
        'Office Sought': 'office'
    },
    columns = 'year committee candidate office party organization_date url'.split(' '),
    baseUrl = 'http://ocf.dc.gov/registration_statements/pcc/pcc_searchresult.asp?ftype=PCC',
    grandTotal = 0,
    queue = async.queue(processPage);

function processPage(task, callback) {
    var year = task.year,
        page = task.page,
        url = baseUrl + '&ele_year=' + year + '&whichpage=' + page,
        recordsFound = 0,
        numPages, totalRecords;
    console.log(url);
    request(url, function (err, response, body) {
        var m, $;
        if (err) {
            throw err;
        }
        if (m = body.match(/Page (\d+) of (\d+)(?: )+Total Records : (\d+)/)) {
            if (numPages) {
                if (+m[1] !== page || +m[2] !== numPages || +m[3] !== totalRecords) {
                    throw 'Unexpected numbers (' + m[1] + ', ' + m[2] + ', ' + m[3] + ') for ' + url;
                }
            }
            else {
                numPages = m[2];
                totalRecords = m[3];
                console.log('%d pages, %d records', numPages, totalRecords);
            }
        }
        else if (body.match(/Your\s+search returned no results\./)) {
            console.log("  no records\n");
            numPages = totalRecords = 0;
            callback();
            return;
        }
        else {
            throw 'Unexpected first page for ' + url + '\n' + body;
        }
        $ = cheerio.load(body);
        $('form[name=pcc_searchresult] table').children().each(function () {
            var $row = $(this),
                r = {year: year},
                cells;
            if (!$row.attr('bgcolor')) {
                return;
            }
            cells = $row.children();
            r.candidate = trim(cells.eq(0).text());
            r.committee = trim(cells.eq(1).text());
            r.url = URL.resolve(baseUrl, cells.eq(0).find('a').attr('href'));
            recordsFound++;
            if (r.committee == 'N/A') {
                return;
            }
            request(r.url, function (err, response, body) {
                var $ = cheerio.load(body);
                if (err) {
                    throw err;
                }
                $('tr').each(function () {
                    var subcells = $(this).find('td'),
                        label, value, column;
                    if (subcells.length != 2 ||
                        subcells.eq(0).attr('width') != '25%' ||
                        subcells.eq(1).attr('width') != '75%') {
                        return;
                    }
                    label = trim(subcells.eq(0).text());
                    value = trim(subcells.eq(1).text());
                    column = columnMap[label];
                    if (!column) {
                        return;
                    }
                    if (/_date$/.test(column)) {
                        value = moment(value).format('YYYY-MM-DD');
                    }
                    r[column] = value;
                });
                console.log('r', r);
            });
        });
        if (page < numPages) {
            page++;
        }
        else {
            page = 1;
            year++;
        }
        if (year < 2015) {
            queue.push({year: year, page: page});
        }
        callback();
    });
}

queue.push({year: 2014, page: 1});

/*
for my $year (2000 .. 2012) {
    print "$year \n";
    my $page = 1;
    my($num_pages, $total_records);
    my $records_found = 0;
    while (1) {
        my $url = "$base_url&ele_year=$year&whichpage=$page";
        $bot->get($url);
        if ($bot->content =~
            /Page (\d+) of (\d+)(?: )+Total Records : (\d+)/) {
            if ($num_pages) {
                if ($1 != $page or $2 != $num_pages or $3 != $total_records) {
                    die "Unexpected numbers ($1, $2, $3) for $url\n";
                }
            }
            else {
                $num_pages = $2;
                $total_records = $3;
                print "  $num_pages pages, $total_records records\n";
            }
        }
        elsif ($bot->content =~ /Your\s+search returned no results\./) {
            print "  no records\n";
            $num_pages = $total_records = 0;
            last;
        }
        else {
            die "Unexpected first page for $url\n", $bot->content;
        }
        my $form = $bot->tree->look_down(_tag => 'form',
            name => 'pcc_searchresult')->clone();
        my @rows = $form->look_down(_tag => 'table')->content_list();
        for my $row (@rows) {
            next unless defined $row->attr('bgcolor');
            my @cells = $row->content_list();
            my %r = (year => $year);
            $r{candidate} = $cells[0]->as_trimmed_text();
            $r{committee} = $cells[1]->as_trimmed_text();
            $r{url} = $cells[0]->look_down(_tag => 'a')->attr('href');
            $records_found++;
            next if $r{committee} eq 'N/A';
            $bot->get($r{url});
            my @subrows = $bot->tree
                ->look_down(_tag => 'form', name => 'CANCOM_summ')
                ->look_down(_tag => 'tr');
            for my $subrow (@subrows) {
                my @subcells = $subrow->content_list();
                next unless @subcells == 2 and
                    $subcells[0]->attr('width') eq '25%' and
                    $subcells[1]->attr('width') eq '75%';
                my $label = $subcells[0]->as_trimmed_text();
                my $value = $subcells[1]->as_trimmed_text();
                my $column = $column_map{$label} or next;
                if ($column =~ /_date$/) {
                    $value =~ s{^(\d\d?)/(\d\d?)/(\d{4})}
                    { sprintf '%d-%02d-%02d', $3, $1, $2 }ge;
                }
                $r{$column} = $value;
            }
            print OUT join("\t", @r{@columns}), "\n";
            #use Data::Dumper; print Dumper \%r; exit();
        }
        last if ++$page > $num_pages;
    }
    if ($records_found != $total_records) {
        die "$records_found records found -- should be $total_records\n";
    }
    $grand_total += $total_records;
}
print "TOTAL $grand_total records\n";
*/

function trim(s) {
    if (s == null) {
        return null;
    }
    return s.replace(/\s+/g, ' ')
        .replace(/^ | $/g, '');
}
<commit_msg>insert committee records into database (not finishing right)<commit_after>var URL = require('url'),
    request = require('request'),
    _ = require('underscore'),
    async = require('async'),
    cheerio = require('cheerio'),
    moment = require('moment'),
    mysql = require('mysql'),
    config = require('./config'),
    db = mysql.createConnection(config.database),
    columnMap = {
        // 'Name of the Candidate': 'candidate',
        'Filing Date': 'filing_date',
        // 'Name of Committee': 'committee',
        'Party Affiliation': 'party',
        'Office Sought': 'office'
    },
    columns = 'year committee candidate office party organization_date url'.split(' '),
    baseUrl = 'http://ocf.dc.gov/registration_statements/pcc/pcc_searchresult.asp?ftype=PCC',
    queue = async.queue(process),
    maxYear = +moment().format('YYYY') + 2,
    recordsFound = 0;

db.connect(function (err) {
    if (err) {
        throw err;
    }
});

queue.push({year: 2014, page: 1});

function process(task, callback) {
    if (task.page) {
        processPage(task, callback);
    }
    else {
        insertRecord(task, callback);
    }
}

function processPage(task, callback) {
    var year = task.year,
        page = task.page,
        url = baseUrl + '&ele_year=' + year + '&whichpage=' + page,
        numPages, totalRecords;
    console.log('getting', url);
    request(url, function (err, response, body) {
        var m, $;
        if (err) {
            throw err;
        }
        if (body.match(/Your\s+search returned no results\./)) {
            console.log("  no records\n");
            numPages = totalRecords = 0;
        }
        else if (m = body.match(/Page (\d+) of (\d+)(?: )+Total Records : (\d+)/)) {
            if (numPages) {
                if (+m[1] !== page || +m[2] !== numPages || +m[3] !== totalRecords) {
                    throw 'Unexpected numbers (' + m[1] + ', ' + m[2] + ', ' + m[3] + ') for ' + url;
                }
            }
            else {
                numPages = m[2];
                totalRecords = m[3];
                console.log('%d pages, %d records', numPages, totalRecords);
            }
            $ = cheerio.load(body);
            $('form[name=pcc_searchresult] table').children('[bgcolor]').each(function () {
                var $row = $(this),
                    r = {year: year},
                    $cells = $row.children();
                r.candidate = trim($cells.eq(0).text());
                r.committee = trim($cells.eq(1).text());
                r.url = URL.resolve(baseUrl, $cells.eq(0).find('a').attr('href'));
                recordsFound++;
                if (r.committee == 'N/A') {
                    r.committee = '[' + r.candidate.replace(/^([^,]+), ([^,]+)/, '$2 $1') + ' ' + year + ']';
                }
                console.log('getting', r.url);
                request(r.url, function (err, response, body) {
                    var $ = cheerio.load(body);
                    if (err) {
                        throw err;
                    }
                    $('tr').each(function () {
                        var subcells = $(this).find('td'),
                            label, value, column;
                        if (subcells.length != 2 ||
                            subcells.eq(0).attr('width') != '25%' ||
                            subcells.eq(1).attr('width') != '75%') {
                            return;
                        }
                        label = trim(subcells.eq(0).text());
                        value = trim(subcells.eq(1).text());
                        column = columnMap[label];
                        if (!column) {
                            return;
                        }
                        if (/_date$/.test(column)) {
                            value = moment(value).format('YYYY-MM-DD');
                        }
                        r[column] = value;
                    });
                    console.log('queuing', r);
                    queue.push(r, function (err) {
                        if (err) {
                            throw err;
                        }
                    });
                });
            });
        }
        else {
            throw 'Unexpected first page for ' + url + '\n' + body;
        }
        if (page < numPages) {
            page++;
        }
        else {
            if (recordsFound != totalRecords) {
                throw recordsFound + ' of total ' + totalRecords + ' records found';
            }
            recordsFound = 0;
            page = 1;
            year++;
        }
        if (year <= maxYear) {
            queue.push({year: year, page: page});
        }
        callback();
    });
}

function finish() {
    console.log('all records inserted');
    db.end(function (err) {
        if (err) {
            throw err;
        }
        console.log('db connection closed');
    });
}

/*
for my $year (2000 .. 2012) {
    print "$year \n";
    my $page = 1;
    my($num_pages, $total_records);
    my $records_found = 0;
    while (1) {
        my $url = "$base_url&ele_year=$year&whichpage=$page";
        $bot->get($url);
        if ($bot->content =~
            /Page (\d+) of (\d+)(?: )+Total Records : (\d+)/) {
            if ($num_pages) {
                if ($1 != $page or $2 != $num_pages or $3 != $total_records) {
                    die "Unexpected numbers ($1, $2, $3) for $url\n";
                }
            }
            else {
                $num_pages = $2;
                $total_records = $3;
                print "  $num_pages pages, $total_records records\n";
            }
        }
        elsif ($bot->content =~ /Your\s+search returned no results\./) {
            print "  no records\n";
            $num_pages = $total_records = 0;
            last;
        }
        else {
            die "Unexpected first page for $url\n", $bot->content;
        }
        my $form = $bot->tree->look_down(_tag => 'form',
            name => 'pcc_searchresult')->clone();
        my @rows = $form->look_down(_tag => 'table')->content_list();
        for my $row (@rows) {
            next unless defined $row->attr('bgcolor');
            my @cells = $row->content_list();
            my %r = (year => $year);
            $r{candidate} = $cells[0]->as_trimmed_text();
            $r{committee} = $cells[1]->as_trimmed_text();
            $r{url} = $cells[0]->look_down(_tag => 'a')->attr('href');
            $records_found++;
            next if $r{committee} eq 'N/A';
            $bot->get($r{url});
            my @subrows = $bot->tree
                ->look_down(_tag => 'form', name => 'CANCOM_summ')
                ->look_down(_tag => 'tr');
            for my $subrow (@subrows) {
                my @subcells = $subrow->content_list();
                next unless @subcells == 2 and
                    $subcells[0]->attr('width') eq '25%' and
                    $subcells[1]->attr('width') eq '75%';
                my $label = $subcells[0]->as_trimmed_text();
                my $value = $subcells[1]->as_trimmed_text();
                my $column = $column_map{$label} or next;
                if ($column =~ /_date$/) {
                    $value =~ s{^(\d\d?)/(\d\d?)/(\d{4})}
                    { sprintf '%d-%02d-%02d', $3, $1, $2 }ge;
                }
                $r{$column} = $value;
            }
            print OUT join("\t", @r{@columns}), "\n";
            #use Data::Dumper; print Dumper \%r; exit();
        }
        last if ++$page > $num_pages;
    }
    if ($records_found != $total_records) {
        die "$records_found records found -- should be $total_records\n";
    }
    $grand_total += $total_records;
}
print "TOTAL $grand_total records\n";
*/

function trim(s) {
    if (s == null) {
        return null;
    }
    return s.replace(/\s+/g, ' ')
        .replace(/^ | $/g, '');
}

function insertRecord(row, callback) {
    console.log('inserting', row);
    db.query('INSERT INTO committees SET ?', [row], callback);
}
<|endoftext|>


<commit_before>/* eslint-env mocha */
const DoublyLinkedList = require('../../src').DataStructures.DoublyLinkedList;
const assert = require('assert');

describe('DoublyLinkedList', () => {
  it('should be empty when initialized', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());
    assert.equal(inst.length, 0);
  });

  it('should push node to the front', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    assert.equal(inst.length, 1);

    inst.push(2);
    assert.equal(inst.length, 2);

    assert.equal(inst.toString(), '2 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(2), inst.tail);
  });

  it('should get node at given index', () => {
    const inst = new DoublyLinkedList();

    inst.push(1);
    inst.push(2);

    const node = inst.getNode(2);
    assert.equal(node.value, 1);

    assert.equal(inst.toString(), '2 -> 1 -> null');
  });

  it('should insert node after a given node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertAfter(inst.getNode(1), 3);

    assert.equal(inst.toString(), '2 -> 3 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node after last node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertAfter(inst.getNode(2), 3);

    assert.equal(inst.toString(), '2 -> 1 -> 3 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node before a given node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertBefore(inst.getNode(2), 3);

    assert.equal(inst.toString(), '2 -> 3 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node before first node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertBefore(inst.getNode(1), 3);

    assert.equal(inst.toString(), '3 -> 2 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should throw error on insert after in list with no node or null', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.insertAfter(inst.getNode(1)), Error);
    assert.throws(() => inst.insertAfter(null), Error);
  });

  it('should throw error on insert before in list with no node or null', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.insertBefore(inst.getNode(1)), Error);
    assert.throws(() => inst.insertBefore(null), Error);
  });

  it('should throw error on popping from empty list', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.pop(), Error);
  });

  it('should pop node from head', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);

    assert.equal(inst.toString(), '3 -> 2 -> 1 -> null');
    inst.pop();
    assert.equal(inst.toString(), '2 -> 1 -> null');
    assert.equal(inst.length, 2);
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(2), inst.tail);
  });

  it('should delete nodes', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);
    inst.push(4);
    inst.push(5);
    inst.push(6);
    inst.push(7);
    inst.push(8);

    inst.deleteNode(inst.getNode(6));
    assert.equal(
      inst.toString(),
      '8 -> 7 -> 6 -> 5 -> 4 -> 2 -> 1 -> null'
    );

    inst.deleteNode(inst.getNode(1));
    assert.equal(
      inst.toString(),
      '7 -> 6 -> 5 -> 4 -> 2 -> 1 -> null'
    );

    inst.deleteNode(inst.getNode(3));
    assert.equal(
      inst.toString(),
      '7 -> 6 -> 4 -> 2 -> 1 -> null'
    );

    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(5), inst.tail);
    assert.equal(inst.length, 5);
  });
});
<commit_msg>DoublyLinkedList: 100% test coverage<commit_after>/* eslint-env mocha */
const DoublyLinkedList = require('../../src').DataStructures.DoublyLinkedList;
const assert = require('assert');

describe('DoublyLinkedList', () => {
  it('should be empty when initialized', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());
    assert.equal(inst.length, 0);
  });

  it('should push node to the front', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    assert.equal(inst.length, 1);

    inst.push(2);
    assert.equal(inst.length, 2);

    assert.equal(inst.toString(), '2 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(2), inst.tail);
  });

  it('should get node at given index', () => {
    const inst = new DoublyLinkedList();

    inst.push(1);
    inst.push(2);

    const node = inst.getNode(2);
    assert.equal(node.value, 1);

    assert.equal(inst.toString(), '2 -> 1 -> null');
  });

  it('should insert node after a given node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertAfter(inst.getNode(1), 3);

    assert.equal(inst.toString(), '2 -> 3 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node after last node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertAfter(inst.getNode(2), 3);

    assert.equal(inst.toString(), '2 -> 1 -> 3 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node before a given node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertBefore(inst.getNode(2), 3);

    assert.equal(inst.toString(), '2 -> 3 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should insert node before first node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.insertBefore(inst.getNode(1), 3);

    assert.equal(inst.toString(), '3 -> 2 -> 1 -> null');
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(3), inst.tail);
  });

  it('should throw error on insert after in list with no node or null', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.insertAfter(inst.getNode(1)), Error);
    assert.throws(() => inst.insertAfter(null), Error);
  });

  it('should throw error on insert before in list with no node or null', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.insertBefore(inst.getNode(1)), Error);
    assert.throws(() => inst.insertBefore(null), Error);
  });

  it('should throw error on popping from empty list', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    assert.throws(() => inst.pop(), Error);
  });

  it('should pop node from head', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);

    assert.equal(inst.toString(), '3 -> 2 -> 1 -> null');
    inst.pop();
    assert.equal(inst.toString(), '2 -> 1 -> null');
    assert.equal(inst.length, 2);
    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(2), inst.tail);
  });

  it('should delete nodes', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);
    inst.push(4);
    inst.push(5);
    inst.push(6);
    inst.push(7);
    inst.push(8);

    inst.deleteNode(inst.getNode(6));
    assert.equal(
      inst.toString(),
      '8 -> 7 -> 6 -> 5 -> 4 -> 2 -> 1 -> null'
    );

    inst.deleteNode(inst.getNode(1));
    assert.equal(
      inst.toString(),
      '7 -> 6 -> 5 -> 4 -> 2 -> 1 -> null'
    );

    inst.deleteNode(inst.getNode(3));
    assert.equal(
      inst.toString(),
      '7 -> 6 -> 4 -> 2 -> 1 -> null'
    );

    assert.deepStrictEqual(inst.getNode(1), inst.head);
    assert.deepStrictEqual(inst.getNode(5), inst.tail);
    assert.equal(inst.length, 5);
  });

  it('should delete tail node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);

    assert.equal(inst.toString(), '3 -> 2 -> 1 -> null');
    inst.deleteNode(inst.getNode(3));
    assert.equal(inst.tail.value, 2);
    assert.equal(inst.length, 2);
  });

  it('should throw error on deletion of undefined node', () => {
    const inst = new DoublyLinkedList();
    assert(inst.isEmpty());

    inst.push(1);
    inst.push(2);
    inst.push(3);

    assert.throws(() => inst.deleteNode(), Error);
  });
});
<|endoftext|>


<commit_before>/**
 * A simple script that, when a point on the canvas is clicked,
 * it will draw concentric circles around the point.
 *
 * There are better, cleaner, and more efficient ways to write
 * this code. But this way is fairly straightforward.
 */

(function(){

  var canvasElement = document.getElementById('canvasNumberOne');
  canvasElement.addEventListener('click', drawManyCircles, false);

  function drawManyCircles(event){
    var x = event.pageX - canvasElement.offsetLeft;
    var y = event.pageY - canvasElement.offsetTop;
  };

})();

/**
  * A separate function for drawing a circle
  */
function drawCircle(canvas){
    var context = canvas.getContext("2d");
    context.beginPath();
    context.arc(200, 200, 93, Math.PI / 2, Math.PI, true);
    mainContext.lineWidth = 1;
    mainContext.strokeStyle = 'black';
    mainContext.stroke();
}
<commit_msg>Animated concentric rings working<commit_after>/**
 * A simple script that, when a point on the canvas is clicked,
 * it will draw concentric circles around the point.
 *
 * There are better, cleaner, and more efficient ways to write
 * this code. But this way is fairly straightforward.
 */

(function(){

  var canvasElement = document.getElementById('canvasNumberOne');
  canvasElement.addEventListener('mousedown', drawManyCircles, false);

  function drawManyCircles(event){
    var x = event.pageX - canvasElement.offsetLeft;
    var y = event.pageY - canvasElement.offsetTop;
	for (var r = 1; r <= 100; r += 5) {
		var delay = r * 2;
		drawCircle(canvasElement, x, y, r, delay);
	}
  };

})();

/**
  * A separate function for drawing a circle
  */
function drawCircle(canvas, x, y, radius, delayInMilliseconds){
    setTimeout(function(){
		var context = canvas.getContext("2d");
		context.beginPath();
		context.arc(x, y, radius, 0, 2 * Math.PI, true);
		context.lineWidth = 1;
		context.strokeStyle = 'black';
		context.stroke();
	}, delayInMilliseconds);
}
<|endoftext|>


<commit_before>// ---------------------------------------------------------------

var timerUI = 0;

$(document).ready(function() {
    fixLegend();
    applyFilter();
});

// ---------------------------------------------------------------

function queueUIRefresh() {
    if (timerUI != 0) {
	clearTimeout(timerUI);
    }
    timerUI = setTimeout(function() {
	    applyUI();
    }, 10000);

}

function applyFilter() {
    logsFilterRefresh();
    applyData();
}

function applyData() {
    logsRefresh();
    applyUI();
}

function applyUI() {
    queueUIRefresh();
    logsRefreshTimestamps();
    drawMap();
}

// ---------------------------------------------------------------

function mapSystemClicked(name) {
    if ($.inArray(name, logsFilterSystems) != -1) {
	logsFilterSystemRemove(name);
	applyFilter();
	return;
    }

    switch (settingsGet('s-map-action-select-filter')) {
	case '0':
	    logsFilterSystemAdd(name);
	    break;
	case '1':
	    logsFilterSystemReplace(name);
	    break;
    }

    switch (settingsGet('s-map-action-select-unknown')) {
	case '0':
	    break;
	case '1':
	    logsFilterUnknownsSet(false);
	    break;
	case '2':
	    logsFilterUnknownsSet(true);
	    break;
    }

    applyFilter();
}

function logsSystemsClicked(names) {
    switch (settingsGet('s-logs-action-select-filter')) {
	case '0':
	    logsFilterSystemsAdd(names);
	    break;
	case '1':
	    logsFilterSystemsReplace(names);
	    break;
    }

    switch (settingsGet('s-logs-action-select-unknown')) {
	case '0':
	    break;
	case '1':
	    logsFilterUnknownsSet(false);
	    break;
	case '2':
	    logsFilterUnknownsSet(true);
	    break;
    }

    applyFilter();
}

// ---------------------------------------------------------------

function timestampToAgo(timestamp) {
    var diff = (new Date().getTime() - timestamp) / 1000 / 60;
    if (diff < 0.5) {
	return 'new';
    }
    return Math.ceil(diff) + 'm';
}

// ---------------------------------------------------------------

function timestampToColor(timestamp) {
    var diff = Math.ceil((new Date().getTime() - timestamp) / 1000 / 60);
    if (diff < 2) {
	return "#ff0000";
    }
    if (diff < 5) {
	return "#ff6d00";
    }
    if (diff < 10) {
	return "#efef00";
    }
    if (diff < 15) {
	return "#b8a62e";
    }
    if (diff < 20) {
	return "#615718";
    }
    return false;
}

function connectionToColor(gate) {
    if (gate == "j") {
	return "#4c4c4c";
    }
    if (gate == "jc") {
	return "#7c0000";
    }
    if (gate == "jr") {
	return "#7c047b";
    }
    if (gate == "jb") {
	return "#000000";
    }
    if (gate == "jbf") {
	return "#070766";
    }
    if (gate == "jbh") {
	return "#47270a";
    }

}

function systemToColor() {
    return "#6d6d6d";
}

function nameToColor() {
    return "#aaaaaa";
}

function fixLegend() {
    $("#legend-less2").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 1)));
    $("#legend-less5").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 4)));
    $("#legend-less10").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 9)));
    $("#legend-less15").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 14)));
    $("#legend-less20").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 19)));

    $("#legend-j").css('color', connectionToColor('j'));
    $("#legend-jc").css('color', connectionToColor('jc'));
    $("#legend-jr").css('color', connectionToColor('jr'));
    $("#legend-jbf").css('color', connectionToColor('jbf'));
    $("#legend-jbh").css('color', connectionToColor('jbh'));

    $("#legend-system").css('color', systemToColor());
    $("#legend-system-station").css('color', systemToColor());
}

// ---------------------------------------------------------------

function blink(id) {
    h = 400;
    l = 600;
    $('#' + id)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0}, 600);
}

// ---------------------------------------------------------------

function findSystem(sid) {
    for (i in drawData['map']['systems']) {
	if (drawData['map']['systems'][i]['id'] == sid) {
	    return drawData['map']['systems'][i];
	}
    }
    return false;
}

function findBridge(jid) {
    for (i in jbData['bridges']) {
	if (jbData['bridges'][i]['idA'] == jid || jbData['bridges'][i]['idB'] == jid) {
	    return jbData['bridges'][i];
	}
    }
    return false;
}

// ---------------------------------------------------------------

function showSystemDetails(obj, sid) {
    hideSystemDetails(sid);

    sys = findSystem(sid);
    if (sys === false) {
	return;
    }

    $('#popsys-name').html('' + sys['name'] + '');

    cnt = "";
    cnt+= '
';

    bridge = findBridge(sid);
    if (bridge !== false) {
	cnt += 'Jumpbridge ';
	if (bridge['friendly'] == true) {
	    cnt += ' (friendly)';
	} else {
	    cnt += ' (hostile)';
	}
	cnt+= '
';
	cnt += bridge['nameA'] + " " + bridge['planetA'] + "-" + bridge['moonA'];
	cnt += ' <-> ';
	cnt += bridge['nameB'] + " " + bridge['planetB'] + "-" + bridge['moonB'] + "
";
    }

    jumps = 0;
    if (eveData['jumps'][sid] !== undefined) {
	jumps = eveData['jumps'][sid];
    }
    cnt += 'Stats (1h)
';
    cnt += "Jumps: " +  jumps + "
";

    kShips = 0;
    kPods = 0;
    kRats = 0;
    if (eveData['kills'][sid] !== undefined) {
	kShips = eveData['kills'][sid]['ships'];
	kPods = eveData['kills'][sid]['pods'];
	kRats = eveData['kills'][sid]['rats'];
    }
    cnt += 'Kills (1h)
';
    cnt += "Ships: " + kShips + "
";
    cnt += "Pods: " + kPods + "
";
    cnt += "Rats: " + kRats + "
";

    cnt += '';

    $('#popsys-content').html(cnt);
    popShow(obj, "#popsys");
}

function hideSystemDetails(obj, sid) {
    popHide(obj, "#popsys");
}

// ---------------------------------------------------------------

function popHide(obj, overlay) {
  $("#popsys").addClass('hide');
}

function popShow(obj, overlay) {
  $(overlay).css({left: 0, top: 0, position:'absolute'});
  $(overlay).removeClass('hide');

  var ox = 25;
  var oy = 0;

  var x = $(obj).offset().left;
  var y = $(obj).offset().top;

  if (x + ox + $(overlay).width() > $(document).width()) {
    x = (x - ox - $(overlay).width());
  } else {
    x = (x + ox);
  }

  if (y + oy + $(overlay).height() > $(document).height()) {
    y = (y - oy - $(overlay).height());
  } else {
    y = (y + oy);
  }

 $(overlay).css({left: x, top: y, position:'absolute'});
}

// ---------------------------------------------------------------
<commit_msg>Nicer formatting in overlay<commit_after>// ---------------------------------------------------------------

var timerUI = 0;

$(document).ready(function() {
    fixLegend();
    applyFilter();
});

// ---------------------------------------------------------------

function queueUIRefresh() {
    if (timerUI != 0) {
	clearTimeout(timerUI);
    }
    timerUI = setTimeout(function() {
	    applyUI();
    }, 10000);

}

function applyFilter() {
    logsFilterRefresh();
    applyData();
}

function applyData() {
    logsRefresh();
    applyUI();
}

function applyUI() {
    queueUIRefresh();
    logsRefreshTimestamps();
    drawMap();
}

// ---------------------------------------------------------------

function mapSystemClicked(name) {
    if ($.inArray(name, logsFilterSystems) != -1) {
	logsFilterSystemRemove(name);
	applyFilter();
	return;
    }

    switch (settingsGet('s-map-action-select-filter')) {
	case '0':
	    logsFilterSystemAdd(name);
	    break;
	case '1':
	    logsFilterSystemReplace(name);
	    break;
    }

    switch (settingsGet('s-map-action-select-unknown')) {
	case '0':
	    break;
	case '1':
	    logsFilterUnknownsSet(false);
	    break;
	case '2':
	    logsFilterUnknownsSet(true);
	    break;
    }

    applyFilter();
}

function logsSystemsClicked(names) {
    switch (settingsGet('s-logs-action-select-filter')) {
	case '0':
	    logsFilterSystemsAdd(names);
	    break;
	case '1':
	    logsFilterSystemsReplace(names);
	    break;
    }

    switch (settingsGet('s-logs-action-select-unknown')) {
	case '0':
	    break;
	case '1':
	    logsFilterUnknownsSet(false);
	    break;
	case '2':
	    logsFilterUnknownsSet(true);
	    break;
    }

    applyFilter();
}

// ---------------------------------------------------------------

function timestampToAgo(timestamp) {
    var diff = (new Date().getTime() - timestamp) / 1000 / 60;
    if (diff < 0.5) {
	return 'new';
    }
    return Math.ceil(diff) + 'm';
}

// ---------------------------------------------------------------

function timestampToColor(timestamp) {
    var diff = Math.ceil((new Date().getTime() - timestamp) / 1000 / 60);
    if (diff < 2) {
	return "#ff0000";
    }
    if (diff < 5) {
	return "#ff6d00";
    }
    if (diff < 10) {
	return "#efef00";
    }
    if (diff < 15) {
	return "#b8a62e";
    }
    if (diff < 20) {
	return "#615718";
    }
    return false;
}

function connectionToColor(gate) {
    if (gate == "j") {
	return "#4c4c4c";
    }
    if (gate == "jc") {
	return "#7c0000";
    }
    if (gate == "jr") {
	return "#7c047b";
    }
    if (gate == "jb") {
	return "#000000";
    }
    if (gate == "jbf") {
	return "#070766";
    }
    if (gate == "jbh") {
	return "#47270a";
    }

}

function systemToColor() {
    return "#6d6d6d";
}

function nameToColor() {
    return "#aaaaaa";
}

function fixLegend() {
    $("#legend-less2").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 1)));
    $("#legend-less5").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 4)));
    $("#legend-less10").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 9)));
    $("#legend-less15").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 14)));
    $("#legend-less20").css('color', timestampToColor(new Date().getTime() - (1000 * 60 * 19)));

    $("#legend-j").css('color', connectionToColor('j'));
    $("#legend-jc").css('color', connectionToColor('jc'));
    $("#legend-jr").css('color', connectionToColor('jr'));
    $("#legend-jbf").css('color', connectionToColor('jbf'));
    $("#legend-jbh").css('color', connectionToColor('jbh'));

    $("#legend-system").css('color', systemToColor());
    $("#legend-system-station").css('color', systemToColor());
}

// ---------------------------------------------------------------

function blink(id) {
    h = 400;
    l = 600;
    $('#' + id)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0.2}, 600)
	.animate({opacity: 1}, 400)
	.animate({opacity: 0}, 600);
}

// ---------------------------------------------------------------

function findSystem(sid) {
    for (i in drawData['map']['systems']) {
	if (drawData['map']['systems'][i]['id'] == sid) {
	    return drawData['map']['systems'][i];
	}
    }
    return false;
}

function findBridge(jid) {
    for (i in jbData['bridges']) {
	if (jbData['bridges'][i]['idA'] == jid || jbData['bridges'][i]['idB'] == jid) {
	    return jbData['bridges'][i];
	}
    }
    return false;
}

// ---------------------------------------------------------------

function showSystemDetails(obj, sid) {
    hideSystemDetails(sid);

    sys = findSystem(sid);
    if (sys === false) {
	return;
    }

    $('#popsys-name').html('' + sys['name'] + '');

    cnt = "";
    cnt+= '
';

    bridge = findBridge(sid);
    if (bridge !== false) {
	cnt += 'Jumpbridge ';
	if (bridge['friendly'] == true) {
	    cnt += ' (friendly)';
	} else {
	    cnt += ' (hostile)';
	}
	cnt+= '
';
	cnt += "  ";
	cnt += bridge['nameA'] + " " + bridge['planetA'] + "-" + bridge['moonA'];
	cnt += ' <-> ';
	cnt += bridge['nameB'] + " " + bridge['planetB'] + "-" + bridge['moonB'] + "
";
    }

    jumps = 0;
    if (eveData['jumps'][sid] !== undefined) {
	jumps = eveData['jumps'][sid];
    }
    cnt += 'Stats (1h)
';
    cnt += "  " + jumps + " jumps
";

    kShips = 0;
    kPods = 0;
    kRats = 0;
    if (eveData['kills'][sid] !== undefined) {
	kShips = eveData['kills'][sid]['ships'];
	kPods = eveData['kills'][sid]['pods'];
	kRats = eveData['kills'][sid]['rats'];
    }
    cnt += 'Kills (1h)
';
    cnt += "  " + kShips + " ships
";
    cnt += "  " + kPods + " pods
";
    cnt += "  " + kRats + " rats
";

    cnt += '';

    $('#popsys-content').html(cnt);
    popShow(obj, "#popsys");
}

function hideSystemDetails(obj, sid) {
    popHide(obj, "#popsys");
}

// ---------------------------------------------------------------

function popHide(obj, overlay) {
  $("#popsys").addClass('hide');
}

function popShow(obj, overlay) {
  $(overlay).css({left: 0, top: 0, position:'absolute'});
  $(overlay).removeClass('hide');

  var ox = 25;
  var oy = 0;

  var x = $(obj).offset().left;
  var y = $(obj).offset().top;

  if (x + ox + $(overlay).width() > $(document).width()) {
    x = (x - ox - $(overlay).width());
  } else {
    x = (x + ox);
  }

  if (y + oy + $(overlay).height() > $(document).height()) {
    y = (y - oy - $(overlay).height());
  } else {
    y = (y + oy);
  }

 $(overlay).css({left: x, top: y, position:'absolute'});
}

// ---------------------------------------------------------------
<|endoftext|>


<commit_before>'use strict';

// mocha defines to avoid JSHint breakage
/* global describe, it, before, beforeEach, after, afterEach */

var assert = require('../../../utils/assert.js');
var server = require('../../../utils/server.js');
var preq   = require('preq');
var fs     = require('fs');

// read the contents of a spec file as JSON or raw HTML
function readFile(filename) {
    var contents = fs.readFileSync(filename, { encoding: 'utf8' });

    // readFileSync seems to append a line feed
    contents = contents.replace(/\n$/, "");

    if (/\.json$/.test(filename)) {
        return JSON.parse(contents);
    } else {
        return contents;
    }
}

// find dirs matching the pattern "{foo}2{bar}"
function findSpecDirs() {
    var specDirs = [];
    var specDirPattern = /^(.+)2(.+)$/;
    function isDir(x) {
        return fs.statSync(x).isDirectory();
    }
    function isSpecDir(x) {
        return isDir(__dirname + '/' + x) && specDirPattern.test(x);
    }
    var dirs = fs.readdirSync(__dirname);
    dirs.forEach(function(dir) {
        if (isSpecDir(dir)) {
            var match = specDirPattern.exec(dir);
            var fromFormat = match[1];
            var toFormat = match[2];
            specDirs.push({
                name: fromFormat + '2' + toFormat,
                fromFormat: fromFormat,
                toFormat: toFormat,
                src: __dirname + '/' + dir
            });
        }
    });
    return specDirs;
}

// for each dir that looks like it contains req/res specs, find the specs
function findSpecs() {
    var specs = [];
    findSpecDirs().forEach(function (specDir) {
        var files = fs.readdirSync(specDir.src);
        var request = null;
        var response = null;
        files.forEach(function(file2) {
            if (/^request\./.test(file2)) {
                request = specDir.src + '/' + file2;
            } else if (/^response\./.test(file2)) {
                response = specDir.src + '/' + file2;
            }
        });
        if (request !== null && response !== null) {
            specs.push({
                name: specDir.name,
                from: { format: specDir.fromFormat, src: request },
                to: { format: specDir.toFormat, src: response }
            });
        }

    });
    return specs;
}

function x2y(spec) {
    function test() {
        return preq.post({
            uri: server.config.baseURL + '/transform/' + spec.from.format + '/to/' + spec.to.format,
			headers: {
				'content-type': /\.html$/.test(spec.from.src) ?
					'text/html' : 'application/json'
			},
            body: {
				// FIXME: use format name
				content: readFile(spec.from.src)
			}
        })
        .then(function(res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, readFile(spec.to.src));
        });
    }
    describe('transform api: ' + spec.name, function() {
        this.timeout(20000);
        before(function () { return server.start(); });
        it('should directly convert ' + spec.from.format + ' to ' + spec.to.format, test);
    });
}

describe('transform api', function() {
    this.timeout(20000);

    before(function () { return server.start(); });

    it('wt2html', function () {
        return preq.post({
			uri: server.config.baseURL
				+ '/transform/wikitext/to/html/User:GWicke%2F_restbase_test',
            body: {
				wikitext: '== Heading =='
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
			var pattern = /
 Heading <\/h2>/;
			if (!pattern.test(res.body)) {
				throw new Error('Expected pattern in response: ' + pattern);
			}
			assert.deepEqual(res.headers['content-type'],
					'text/html;profile=mediawiki.org/specs/html/1.0.0');
        });
    });

    it('html2wt, no-selser', function () {
        return preq.post({
			uri: server.config.baseURL
				+ '/transform/html/to/wikitext/User:GWicke%2F_restbase_test',
            body: {
				html: 'The modified HTML'
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, 'The modified HTML');
			assert.deepEqual(res.headers['content-type'],
					'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0');
        });
    });

//    it('html2wt, selser', function () {
//        return preq.post({
//			uri: server.config.baseURL
//				+ '/transform/html/to/wikitext/User:GWicke%2F_restbase_test/646859921',
//            body: {
//				html: "<!DOCTYPE html>\n<meta property=\"mw:articleNamespace\" content=\"2\"/><link rel=\"dc:replaces\" resource=\"mwr:revision/0\"/><meta property=\"dc:modified\" content=\"2015-02-12T22:30:30.000Z\"/><meta about=\"mwr:user/11429869\" property=\"dc:title\" content=\"GWicke\"/><link rel=\"dc:contributor\" resource=\"mwr:user/11429869\"/><meta property=\"mw:revisionSHA1\" content=\"6417e5e59b2975e65eebb5104ea572913a61db7e\"/><meta property=\"dc:description\" content=\"selser test page\"/><meta property=\"mw:parsoidVersion\" content=\"0\"/><link rel=\"dc:isVersionOf\" href=\"//en.wikipedia.org/wiki/User%3AGWicke/_restbase_test\"/><title>User:GWicke/_restbase_test</title><base href=\"//en.wikipedia.org/wiki/\"/><link rel=\"stylesheet\" href=\"//en.wikipedia.org/w/load.php?modules=mediawiki.legacy.commonPrint,shared|mediawiki.skinning.elements|mediawiki.skinning.content|mediawiki.skinning.interface|skins.vector.styles|site|mediawiki.skinning.content.parsoid&only=styles&skin=vector\"/>
Selser test
"
//            }
//        })
//        .then(function (res) {
//            assert.deepEqual(res.status, 200);
//            assert.deepEqual(res.body, '
Selser test');
//			assert.deepEqual(res.headers['content-type'],
//					'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0');
//        });
//    });

});

/* TODO: actually implement wikitext fetching
describe('storage-backed transform api', function() {
    this.timeout(20000);

    before(function () { return server.start(); });

    it('should load a specific title/revision from storage to send as the "original"', function () {
        return preq.post({
            uri: server.config.baseURL + '/transform/html/to/wikitext/Main_Page/1',
            headers: { 'content-type': 'application/json' },
            body: {
                headers: {
                  'content-type': 'text/html;profile=mediawiki.org/specs/html/1.0.0'
                },
                body: 'The modified HTML'
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, {
                wikitext: {
                    headers: {
                        'content-type': 'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0'
                    },
                    body: 'The modified HTML'
                }
            });
        });
    });

});
*/
<commit_msg>Add test for html2html & some clean-up<commit_after>'use strict';

// mocha defines to avoid JSHint breakage
/* global describe, it, before, beforeEach, after, afterEach */

var assert = require('../../../utils/assert.js');
var server = require('../../../utils/server.js');
var preq   = require('preq');
var fs     = require('fs');

// read the contents of a spec file as JSON or raw HTML
function readFile(filename) {
    var contents = fs.readFileSync(filename, { encoding: 'utf8' });

    // readFileSync seems to append a line feed
    contents = contents.replace(/\n$/, "");

    if (/\.json$/.test(filename)) {
        return JSON.parse(contents);
    } else {
        return contents;
    }
}

// find dirs matching the pattern "{foo}2{bar}"
function findSpecDirs() {
    var specDirs = [];
    var specDirPattern = /^(.+)2(.+)$/;
    function isDir(x) {
        return fs.statSync(x).isDirectory();
    }
    function isSpecDir(x) {
        return isDir(__dirname + '/' + x) && specDirPattern.test(x);
    }
    var dirs = fs.readdirSync(__dirname);
    dirs.forEach(function(dir) {
        if (isSpecDir(dir)) {
            var match = specDirPattern.exec(dir);
            var fromFormat = match[1];
            var toFormat = match[2];
            specDirs.push({
                name: fromFormat + '2' + toFormat,
                fromFormat: fromFormat,
                toFormat: toFormat,
                src: __dirname + '/' + dir
            });
        }
    });
    return specDirs;
}

// for each dir that looks like it contains req/res specs, find the specs
function findSpecs() {
    var specs = [];
    findSpecDirs().forEach(function (specDir) {
        var files = fs.readdirSync(specDir.src);
        var request = null;
        var response = null;
        files.forEach(function(file2) {
            if (/^request\./.test(file2)) {
                request = specDir.src + '/' + file2;
            } else if (/^response\./.test(file2)) {
                response = specDir.src + '/' + file2;
            }
        });
        if (request !== null && response !== null) {
            specs.push({
                name: specDir.name,
                from: { format: specDir.fromFormat, src: request },
                to: { format: specDir.toFormat, src: response }
            });
        }

    });
    return specs;
}

function x2y(spec) {
    function test() {
        return preq.post({
            uri: server.config.baseURL + '/transform/' + spec.from.format + '/to/' + spec.to.format,
			headers: {
				'content-type': /\.html$/.test(spec.from.src) ?
					'text/html' : 'application/json'
			},
            body: {
				// FIXME: use format name
				content: readFile(spec.from.src)
			}
        })
        .then(function(res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, readFile(spec.to.src));
        });
    }
    describe('transform api: ' + spec.name, function() {
        this.timeout(20000);
        before(function () { return server.start(); });
        it('should directly convert ' + spec.from.format + ' to ' + spec.to.format, test);
    });
}

var testPage = {
	title: 'User:GWicke%2F_restbase_test',
	revision: '646859921',
	html: "<!DOCTYPE html>\n<meta property=\"mw:articleNamespace\" content=\"2\"/><link rel=\"dc:replaces\" resource=\"mwr:revision/0\"/><meta property=\"dc:modified\" content=\"2015-02-12T22:30:30.000Z\"/><meta about=\"mwr:user/11429869\" property=\"dc:title\" content=\"GWicke\"/><link rel=\"dc:contributor\" resource=\"mwr:user/11429869\"/><meta property=\"mw:revisionSHA1\" content=\"6417e5e59b2975e65eebb5104ea572913a61db7e\"/><meta property=\"dc:description\" content=\"selser test page\"/><meta property=\"mw:parsoidVersion\" content=\"0\"/><link rel=\"dc:isVersionOf\" href=\"//en.wikipedia.org/wiki/User%3AGWicke/_restbase_test\"/><title>User:GWicke/_restbase_test</title><base href=\"//en.wikipedia.org/wiki/\"/><link rel=\"stylesheet\" href=\"//en.wikipedia.org/w/load.php?modules=mediawiki.legacy.commonPrint,shared|mediawiki.skinning.elements|mediawiki.skinning.content|mediawiki.skinning.interface|skins.vector.styles|site|mediawiki.skinning.content.parsoid&only=styles&skin=vector\"/>
Selser test
",
	wikitext: '
Selser test'
};

describe('transform api', function() {
    this.timeout(20000);

    before(function () { return server.start(); });

    it('html2html', function () {
        return preq.post({
			uri: server.config.baseURL
				+ '/transform/html/to/html/' + testPage.title
				+ '/' + testPage.revision,
            body: {
				html: testPage.html
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
			var pattern = /
Selser test<\/div>/;
			if (!pattern.test(res.body)) {
				throw new Error('Expected pattern in response: ' + pattern
						+ '\nSaw: ' + JSON.stringify(res, null, 2));
			}
			assert.deepEqual(res.headers['content-type'],
					'text/html;profile=mediawiki.org/specs/html/1.0.0');
        });
    });

    it('wt2html', function () {
        return preq.post({
			uri: server.config.baseURL
				+ '/transform/wikitext/to/html/User:GWicke%2F_restbase_test',
            body: {
				wikitext: '== Heading =='
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
			var pattern = /
 Heading <\/h2>/;
			if (!pattern.test(res.body)) {
				throw new Error('Expected pattern in response: ' + pattern);
			}
			assert.deepEqual(res.headers['content-type'],
					'text/html;profile=mediawiki.org/specs/html/1.0.0');
        });
    });

    it('html2wt, no-selser', function () {
        return preq.post({
			uri: server.config.baseURL
				+ '/transform/html/to/wikitext/User:GWicke%2F_restbase_test',
            body: {
				html: 'The modified HTML'
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, 'The modified HTML');
			assert.deepEqual(res.headers['content-type'],
					'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0');
        });
    });

// Temporarily disabled until https://phabricator.wikimedia.org/T89411 is
// resolved
//    it('html2wt, selser', function () {
//        return preq.post({
//			uri: server.config.baseURL
//				+ '/transform/html/to/wikitext/' + testPage.title
//				+ '/' + testPage.revision,
//            body: {
//				html: testPage.html
//            }
//        })
//        .then(function (res) {
//            assert.deepEqual(res.status, 200);
//            assert.deepEqual(res.body, testPage.wikitext);
//			assert.deepEqual(res.headers['content-type'],
//					'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0');
//        });
//    });

});

/* TODO: actually implement wikitext fetching
describe('storage-backed transform api', function() {
    this.timeout(20000);

    before(function () { return server.start(); });

    it('should load a specific title/revision from storage to send as the "original"', function () {
        return preq.post({
            uri: server.config.baseURL + '/transform/html/to/wikitext/Main_Page/1',
            headers: { 'content-type': 'application/json' },
            body: {
                headers: {
                  'content-type': 'text/html;profile=mediawiki.org/specs/html/1.0.0'
                },
                body: 'The modified HTML'
            }
        })
        .then(function (res) {
            assert.deepEqual(res.status, 200);
            assert.deepEqual(res.body, {
                wikitext: {
                    headers: {
                        'content-type': 'text/plain;profile=mediawiki.org/specs/wikitext/1.0.0'
                    },
                    body: 'The modified HTML'
                }
            });
        });
    });

});
*/
<|endoftext|>


<commit_before>const {
  setupComponent,
  checkWrap,
  checkWrapActions,
  initialState,
  defaultLang,
  terms,
  translators,
  users,
  admin,
  roles,
  languages,
  _appPath
} = require('../../_shared.js');

const Term = require(_appPath + 'components/search/Term').default;

describe('Testing Term Component.', () => {

  const checkShowTerm = (selectedTerm, user, lang) => {
    const _initialState = { ...initialState,
      selected: { ...initialState.selected,
        term: selectedTerm
      },
      common: { ...initialState.common,
        userLanguage: lang,
        translators
      },
      auth: { ...initialState.auth,
        userInfo: { ...initialState.auth.userInfo,
          data: { ...initialState.auth.userInfo.data,
            role: user.role,
            id: user.id
          }
        }
      }
    };
    const {wrapper} = setupComponent(Term, _initialState);
    const i18n = require(_appPath + 'i18n/' + lang);

    checkWrap(wrapper.find('[data-test-id="Term"]'), {
      className: 'term'
    });

    checkWrap(wrapper.find('[data-test-id="term-header"]'), {
      className: 'term-header'
    });

    checkWrap(wrapper.find('[data-test-id="wylie-header"]'), {
      className: 'wylie',
      text: selectedTerm.wylie
    });

    checkWrap(wrapper.find('[data-test-id="sanskrit"]'), {
      className: 'sanskrit',
      text: i18n['Term.sanskrit_term'].replace(`{sanskrit_${lang}}`, selectedTerm[`sanskrit_${lang}`])
    });

    checkWrap(wrapper.find('[data-test-id="translation-list"]'), {
      className: 'translation-list'
    });

    checkWrap(wrapper.find('[data-test-id="translation"]'), {
      length: selectedTerm.translations.length
    });

    let _versionIndex = -1;
    selectedTerm.translations.forEach((translation, translationIndex) => {

      checkWrap(wrapper.find('[data-test-id="translation"]').at(translationIndex), {
        className: 'translation'
      });

      checkWrap(wrapper.find('[data-test-id="wrap-translator-ref"]').at(translationIndex), {
        className: 'wrap-translator-ref'
      });

      checkWrap(wrapper.find('a[data-test-id="link-translator"]').at(translationIndex), {
        text: translators.find(e => e.id === translation.translatorId).name,
        className: 'translator=ref'
      });

      if (user.role === 'admin') {
        checkWrap(wrapper.find('a[data-test-id="link-to-edit"]'), {
          length: selectedTerm.translations.length
        });
        checkWrap(wrapper.find('[data-test-id="edit-icon"].edit-icon'), {
          length: selectedTerm.translations.length
        });
      } else if (translation.translatorId === user.id) {
        checkWrap(wrapper.find('[data-test-id="link-to-edit"]').first());
        checkWrap(wrapper.find('[data-test-id="edit-icon"].edit-icon'));
      } else if (!selectedTerm.translations.find(t => t.translatorId === user.id)) {
        checkWrap(wrapper.find('[data-test-id="link-to-edit"]'), {
          length: 0
        });
        checkWrap(wrapper.find('[data-test-id="edit-icon"].edit-icon'), {
          length: 0
        });
      }

      checkWrap(wrapper.find('[data-test-id="list-meanings"]').at(translationIndex), {
        length: 1,
        className: 'meanings' + (translation.meanings.length === 1 ? ' single-item' : '')
      });

      let meaningsLength = 0;
      selectedTerm.translations.forEach(e => meaningsLength += e.meanings.length);
      checkWrap(wrapper.find('[data-test-id="meaning"]'), {
        length: meaningsLength
      });

      translation.meanings.forEach((meaning, meaningIndex) => {

        checkWrap(wrapper.find('[data-test-id="meaning"]').at(meaningIndex));

        checkWrap(wrapper.find('[data-test-id="meaning"]').at(meaningIndex), {
          className: 'meaning'
        });

        let versionLength = 0;
        selectedTerm.translations.forEach(elem =>
          elem.meanings.forEach(e =>
            versionLength += e.versions.length
          )
        );
        checkWrap(wrapper.find('[data-test-id="version"]'), {
          length: versionLength
        });

        let amountComments = 0;
        meaning.versions.forEach(e => e.comment ? amountComments++ : null);
        if (amountComments) {
          checkWrap(wrapper.find('[data-test-id="commentLink"]'), {
            length: amountComments,
            className: 'commentLink',
            text: '>>>'
          })
        }

        let amountOpenComments = 0;
        meaning.versions.forEach(e => e.openComment ? amountComments++ : null);
        if (amountOpenComments) {
          checkWrap(wrapper.find('[data-test-id="translation-comment"]'), {
            length: amountOpenComments,
            className: 'translation-comment',
            text: ':'
          })
        }

        meaning.versions.forEach((version, versionIndex) => {
          _versionIndex++;
          checkWrap(wrapper.find('[data-test-id="version"]').at(_versionIndex), {
            text: version + (versionIndex < meaning.versions.length - 1 ? '; ' : '')
          });
        });
      });
    });

    if (!selectedTerm.translations.find(t => t.translatorId === user.id)
      && user.role === 'translator') {
      checkWrap(wrapper.find('[data-test-id="add-translation"].add-translation'));
      checkWrap(wrapper.find('[data-test-id="link-add-translation"]').first());
      checkWrap(wrapper.find('[data-test-id="link-add-translation"]').first(), {
        text: i18n['Term.add-translation']
      });
    } else {
      checkWrap(wrapper.find('[data-test-id="add-translation"]'), { length: 0 });
      checkWrap(wrapper.find('[data-test-id="link-add-translation"]'), { length: 0 });
    }

    wrapper.unmount();
  };

  // tests starts here
  terms.forEach(term => {

    users.forEach(user =>
      it(`should correctly show component for ${user.id} with role ${user.role}`,
        () => checkShowTerm(term, user, user.language)
      )
    );

    translators.forEach(translator =>
      it(`should correctly show component for ${translator.id} with role ${translator.role}`,
        () => checkShowTerm(term, translator, translator.language)
      )
    );
  });

  it('should correctly handle actions on component', () => {
    const selectedTerm = terms[0];
    const _initialState = { ...initialState,
      selected: { ...initialState.selected,
        term: selectedTerm
      },
      common: { ...initialState.common,
        userLanguage: defaultLang,
        translators
      },
      auth: { ...initialState.auth,
        userInfo: { ...initialState.auth.userInfo,
          data: { ...initialState.auth.userInfo.data,
            role: 'user',
            id: 'id'
          }
        }
      }
    };
    const _props = {
      dispatch: jest.fn()
    };
    const {wrapper, store} = setupComponent(Term, _initialState, _props);
    let actionsCount = 0;
    checkWrapActions(store, actionsCount);

    const _wrap = wrapper.find('[data-test-id="commentLink"]');
    for (let i = 0; i < _wrap.length; i++) {
      _wrap.at(i).props().onClick();
      checkWrapActions(store, ++actionsCount);
    }
  });
});
<commit_msg>Delete old Term.spec.js...<commit_after><|endoftext|>


<commit_before>'use strict';

const pathToRegExp = require('path-to-regexp');

const { assignObject } = require('../../../utilities');

class RoutesManager {

  constructor({ routes = [] }) {
    this._routes = [];
    for (const route of routes) {
      this.add(route);
    }
  }

  add({ path, name, goal }) {
    const regexp = pathToRegExp(path);
    const variables = regexp.keys.map(({ name }) => name);
    const goals = goal && !(goal instanceof Array) ? [goal] : goal;

    this._routes.push({ path, name, regexp, variables, goals });
  }

  // Retrieves correct route, according to path
  find({ path, goal }) {
    // Check path and goals
    return this._routes.find(({ regexp, goals }) => {
      return regexp.test(path) && (!goals || goals.includes(goal));
    });
  }

  // Retrieves path variables, e.g. /path/:id
  getPathVars({ path, route: { regexp, variables } }) {
    return regexp
      .exec(path)
      // Removes first value, which is the full path
      .slice(1)
      // Adds the name of the variable to the value
      // Will be an incrementing index e.g. for /path/* or /path/(maybe)?/
      .map((value, index) => {
        const key = variables[index];
        return { [key]: value };
      })
      .reduce(assignObject, {});
  }

}

module.exports = {
  RoutesManager,
};
<commit_msg>Transtype URL variables<commit_after>'use strict';

const pathToRegExp = require('path-to-regexp');

const { transtype, assignObject } = require('../../../utilities');

class RoutesManager {

  constructor({ routes = [] }) {
    this._routes = [];
    for (const route of routes) {
      this.add(route);
    }
  }

  add({ path, name, goal }) {
    const regexp = pathToRegExp(path);
    const variables = regexp.keys.map(({ name }) => name);
    const goals = goal && !(goal instanceof Array) ? [goal] : goal;

    this._routes.push({ path, name, regexp, variables, goals });
  }

  // Retrieves correct route, according to path
  find({ path, goal }) {
    // Check path and goals
    return this._routes.find(({ regexp, goals }) => {
      return regexp.test(path) && (!goals || goals.includes(goal));
    });
  }

  // Retrieves path variables, e.g. /path/:id
  getPathVars({ path, route: { regexp, variables } }) {
    return regexp
      .exec(path)
      // Removes first value, which is the full path
      .slice(1)
      // Adds the name of the variable to the value
      // Will be an incrementing index e.g. for /path/* or /path/(maybe)?/
      .map((value, index) => {
        const key = variables[index];
        const transtypedValue = transtype(value);
        return { [key]: transtypedValue };
      })
      .reduce(assignObject, {});
  }

}

module.exports = {
  RoutesManager,
};
<|endoftext|>


<commit_before>(function (nativeDefineProperty) {

	var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__');
	var ERR_ACCESSORS_NOT_SUPPORTED = 'Getters & setters cannot be defined on this javascript engine';
	var ERR_VALUE_ACCESSORS = 'A property cannot both have accessors and be writable or have a value';

	Object.defineProperty = function defineProperty(object, property, descriptor) {

		var propertyString = String(property);
		var hasValueOrWritable = 'value' in descriptor || 'writable' in descriptor;
		var getterType = 'get' in descriptor && typeof descriptor.get;
		var setterType = 'set' in descriptor && typeof descriptor.set;

		if (object === null || !(object instanceof Object || typeof object === 'object')) {
			throw new TypeError('Object must be an object (Object.defineProperty polyfill)');
		}

		if (!(descriptor instanceof Object)) {
			throw new TypeError('Descriptor must be an object (Object.defineProperty polyfill)');
		}

		// Where native support exists, assume it
		if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) {
			return nativeDefineProperty(object, propertyString, descriptor);
		}

		// handle descriptor.get
		if (getterType) {
			if (getterType !== 'function') {
				throw new TypeError('Getter expected a function (Object.defineProperty polyfill)');
			}
			if (!supportsAccessors) {
				throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
			}
			if (hasValueOrWritable) {
				throw new TypeError(ERR_VALUE_ACCESSORS);
			}
			object.__defineGetter__(propertyString, descriptor.get);
		} else {
			object[propertyString] = descriptor.value;
		}

		// handle descriptor.set
		if (setterType) {
			if (setterType !== 'function') {
				throw new TypeError('Setter expected a function (Object.defineProperty polyfill)');
			}
			if (!supportsAccessors) {
				throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
			}
			if (hasValueOrWritable) {
				throw new TypeError(ERR_VALUE_ACCESSORS);
			}
			object.__defineSetter__(propertyString, descriptor.set);
		}

		// OK to define value unconditionally - if a getter has been specified as well, an error would be thrown above
		if ('value' in descriptor) {
			object[propertyString] = descriptor.value;
		}

		return object;
	};
}(Object.defineProperty));
<commit_msg>Return before trying to cast property to string<commit_after>(function (nativeDefineProperty) {

	var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__');
	var ERR_ACCESSORS_NOT_SUPPORTED = 'Getters & setters cannot be defined on this javascript engine';
	var ERR_VALUE_ACCESSORS = 'A property cannot both have accessors and be writable or have a value';

	Object.defineProperty = function defineProperty(object, property, descriptor) {

		// Where native support exists, assume it
		if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) {
			return nativeDefineProperty(object, property, descriptor);
		}

		var propertyString = String(property);
		var hasValueOrWritable = 'value' in descriptor || 'writable' in descriptor;
		var getterType = 'get' in descriptor && typeof descriptor.get;
		var setterType = 'set' in descriptor && typeof descriptor.set;

		if (object === null || !(object instanceof Object || typeof object === 'object')) {
			throw new TypeError('Object must be an object (Object.defineProperty polyfill)');
		}

		if (!(descriptor instanceof Object)) {
			throw new TypeError('Descriptor must be an object (Object.defineProperty polyfill)');
		}

		// handle descriptor.get
		if (getterType) {
			if (getterType !== 'function') {
				throw new TypeError('Getter expected a function (Object.defineProperty polyfill)');
			}
			if (!supportsAccessors) {
				throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
			}
			if (hasValueOrWritable) {
				throw new TypeError(ERR_VALUE_ACCESSORS);
			}
			object.__defineGetter__(propertyString, descriptor.get);
		} else {
			object[propertyString] = descriptor.value;
		}

		// handle descriptor.set
		if (setterType) {
			if (setterType !== 'function') {
				throw new TypeError('Setter expected a function (Object.defineProperty polyfill)');
			}
			if (!supportsAccessors) {
				throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
			}
			if (hasValueOrWritable) {
				throw new TypeError(ERR_VALUE_ACCESSORS);
			}
			object.__defineSetter__(propertyString, descriptor.set);
		}

		// OK to define value unconditionally - if a getter has been specified as well, an error would be thrown above
		if ('value' in descriptor) {
			object[propertyString] = descriptor.value;
		}

		return object;
	};
}(Object.defineProperty));
<|endoftext|>