<commit_before>/* Purpose: Export development and production webpack configuration objects */

'use strict'

// Load modules
let env = require('../env')
let alert = require('../lib/alert')
let found = require('../lib/found')
let fs = require('fs-extra')
let path = require('path')
let abs = require('path').resolve
let webpack = require('webpack')

// Empty cache folder
fs.emptyDirSync(abs(env.cache, 'build'))

// Create configuration
let createConfiguration = function (mode) {
  // Define mode
  if (mode === '') {
    if (mode !== 'development' && mode !== 'production') {
      alert('Webpack configuration needs "production" or "development" as parameter.', 'issue')
    }
  }

  // Define string with all pages (to use in main.js)
  var pageStr = ''
  if (found(env.app, 'pages')) {
    var pageFiles = fs.readdirSync(abs(env.app, 'pages'))
    for (var p = 0; p < pageFiles.length; p++) {
      if (pageFiles[p].substr(pageFiles[p].length - 4, 4) === '.vue') {
        pageFiles[p] = pageFiles[p].replace(/\\/g, '/')
        if (p > 0) {
          pageStr += ','
        }
        pageStr += pageFiles[p].substr(0, pageFiles[p].length - 4)
      }
    }
  }

  // Define loaders
  let ExtractTextPlugin = require('extract-text-webpack-plugin')
  let loaders = [
    // JS files
    {
      test: /\.js$/,
      loader: 'babel',
      include: [
        abs(__dirname, '../lib'),
        abs(__dirname, '../scripts'),
        abs(env.app, 'app')
      ]
    },
    // Vue files
    {
      test: /\.vue$/,
      loader: 'vue'
    },
    // JSON files
    {
      test: /\.json$/,
      loader: 'json'
    },
    // CSS files
    {
      test: /\.css$/,
      loader: mode === 'development' ? 'vue-style-loader!css-loader' : ExtractTextPlugin.extract('css-loader' + (env.cfg.buildSourcemaps === true ? '?sourceMap' : ''))
    },
    // Image files
    {
      test: /\.(png|jpe?g|gif)(\?.*)?$/,
      loader: 'url',
      query: {
        limit: 1,
        name: 'img/[name].[hash:7].[ext]'
      }
    },
    // Favicon
    {
      test: /favicon\.ico$/,
      loader: 'url',
      query: {
        limit: 1,
        name: '[name].[ext]'
      }
    },
    // Font files
    {
      test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
      loader: 'url',
      query: {
        limit: 1,
        name: 'fonts/[name].[hash:7].[ext]'
      }
    }
  ]

  // Start configuration object
  let config = {
    entry: {
      app: [abs(__dirname, '../lib/main.js')]
    },
    output: {
      path: mode === 'development' ? abs(env.app) : abs(env.cache, 'build/www'),
      publicPath: mode === 'development' ? path.join('/') : path.join('/'),
      filename: '[name].[hash:7].js'
    },
    resolve: {
      extensions: ['', '.js', '.vue', '.json'],
      alias: {
        'vue$': 'vue/dist/vue.common.js'
      }
    },
    module: {
      loaders: loaders
    },
    plugins: []
  }

  // Add environment variables
  config.plugins.push(
    new webpack.DefinePlugin({
      'process.env': {
        THEME: '"' + env.cfg.theme + '"',
        APP_ROOT_FROM_SCRIPTS: '"' + (env.installed ? '../../../app/' : '../app/') + '"',
        CACHE_ROOT_FROM_SCRIPTS: '"' + (env.installed ? '../../../node_modules/.app-framework-cache/' : '../node_modules/.app-framework-cache/') + '"',
        FRAMEWORK_VERSION: '"' + env.pkg.version + '"',
        FONT_FRAMEWORK7: '"' + env.cfg.loadIconFonts.framework7 + '"',
        FONT_MATERIAL: '"' + env.cfg.loadIconFonts.material + '"',
        FONT_ION: '"' + env.cfg.loadIconFonts.ion + '"',
        FONT_AWESOME: '"' + env.cfg.loadIconFonts.fontawesome + '"',
        RESET_LOCAL_STORAGE: '"' + env.cfg.resetLocalStorageOnVersionChange + '"',
        PAGES: '"' + pageStr + '"',
        NODE_ENV: '"' + mode + '"',
        DEV_BUILD: '"' + (env.arg.dev === true) + '"'
      }
    })
  )

  // Optimize ordering, reduce size
  config.plugins.push(new webpack.optimize.OccurrenceOrderPlugin())

  // Avoid exit with error in CLI
  if (mode === 'development') {
    config.plugins.push(new webpack.NoErrorsPlugin())
  }

  // Add hot file reload in development mode
  if (mode === 'development') {
    config.entry['app'].unshift(abs(__dirname, '../lib/dev-client.js'))
    config.plugins.push(new webpack.HotModuleReplacementPlugin())
  }

  // Extract CSS code to extra file
  if (mode === 'production') {
    config.plugins.push(
      new ExtractTextPlugin('[name].[hash:7].css')
    )
    config.vue = {
      loaders: {
        css: ExtractTextPlugin.extract('vue-style-loader', 'css-loader' + (env.cfg.buildSourcemaps === true ? '?sourceMap' : ''))
      }
    }
  }

  // Define icon tags for production
  let iconTags = ''
  if (mode === 'production') {
    iconTags = '<meta name="theme-color" content="' + env.cfg.iconBackgroundColor + '" />' +
               '<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />' +
               '<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />' +
               '<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />' +
               '<link rel="manifest" href="manifest.json" />'
  } else {
    iconTags = ''
  }

  // Plugin: HTML index file generation
  let HtmlPlugin = require('html-webpack-plugin')
  config.plugins.push(
    new HtmlPlugin({
      // filename: mode === 'development' ? 'index.html' : abs(env.proj, 'build/index.html'),
      filename: 'index.html',
      template: abs(__dirname, '../index.ejs'),
      title: env.cfg.title,
      iconTags: mode === 'development' ? '' : iconTags, // favicon.ico will be loaded by browser default from root directory
      manifest: mode === 'production' ? ' manifest="manifest.appcache"' : '',
      inject: true,
      minify: mode === 'production' ? {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      } : undefined
    })
  )

  // Add source maps
  if (mode === 'development') {
    config.devtool = '#eval-source-map'
  } else if (mode === 'production' && env.cfg.buildSourcemaps === true) {
    config.devtool = '#source-map'
  } else {
    config.devtool = undefined
  }

  // Add JS compression
  if (mode === 'production') {
    config.plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    )
  }

  // Add cache manifest
  if (mode === 'production') {
    let AppCachePlugin = require('appcache-webpack-plugin')
    config.plugins.push(
      new AppCachePlugin({
        cache: null,
        network: ['*'],
        fallback: null,
        settings: null,
        exclude: [/\.(js|css)\.map$/],
        output: 'manifest.appcache'
      })
    )
  }

  // Return object
  return config
}

// Export configuration
module.exports = {
  development: createConfiguration('development'),
  production: createConfiguration('production')
}
<commit_msg>path fix<commit_after>/* Purpose: Export development and production webpack configuration objects */

'use strict'

// Load modules
let env = require('../env')
let alert = require('../lib/alert')
let found = require('../lib/found')
let fs = require('fs-extra')
let abs = require('path').resolve
let webpack = require('webpack')

// Empty cache folder
fs.emptyDirSync(abs(env.cache, 'build'))

// Create configuration
let createConfiguration = function (mode) {
  // Define mode
  if (mode === '') {
    if (mode !== 'development' && mode !== 'production') {
      alert('Webpack configuration needs "production" or "development" as parameter.', 'issue')
    }
  }

  // Define string with all pages (to use in main.js)
  var pageStr = ''
  if (found(env.app, 'pages')) {
    var pageFiles = fs.readdirSync(abs(env.app, 'pages'))
    for (var p = 0; p < pageFiles.length; p++) {
      if (pageFiles[p].substr(pageFiles[p].length - 4, 4) === '.vue') {
        pageFiles[p] = pageFiles[p].replace(/\\/g, '/')
        if (p > 0) {
          pageStr += ','
        }
        pageStr += pageFiles[p].substr(0, pageFiles[p].length - 4)
      }
    }
  }

  // Define loaders
  let ExtractTextPlugin = require('extract-text-webpack-plugin')
  let loaders = [
    // JS files
    {
      test: /\.js$/,
      loader: 'babel',
      include: [
        abs(__dirname, '../lib'),
        abs(__dirname, '../scripts'),
        abs(env.app, 'app')
      ]
    },
    // Vue files
    {
      test: /\.vue$/,
      loader: 'vue'
    },
    // JSON files
    {
      test: /\.json$/,
      loader: 'json'
    },
    // CSS files
    {
      test: /\.css$/,
      loader: mode === 'development' ? 'vue-style-loader!css-loader' : ExtractTextPlugin.extract('css-loader' + (env.cfg.buildSourcemaps === true ? '?sourceMap' : ''))
    },
    // Image files
    {
      test: /\.(png|jpe?g|gif)(\?.*)?$/,
      loader: 'url',
      query: {
        limit: 1,
        name: 'img/[name].[hash:7].[ext]'
      }
    },
    // Favicon
    {
      test: /favicon\.ico$/,
      loader: 'url',
      query: {
        limit: 1,
        name: '[name].[ext]'
      }
    },
    // Font files
    {
      test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
      loader: 'url',
      query: {
        limit: 1,
        name: 'fonts/[name].[hash:7].[ext]'
      }
    }
  ]

  // Start configuration object
  let config = {
    entry: {
      app: [abs(__dirname, '../lib/main.js')]
    },
    output: {
      path: mode === 'development' ? abs(env.app) : abs(env.cache, 'build/www'),
      publicPath: '',
      filename: '[name].[hash:7].js'
    },
    resolve: {
      extensions: ['', '.js', '.vue', '.json'],
      alias: {
        'vue$': 'vue/dist/vue.common.js'
      }
    },
    module: {
      loaders: loaders
    },
    plugins: []
  }

  // Add environment variables
  config.plugins.push(
    new webpack.DefinePlugin({
      'process.env': {
        THEME: '"' + env.cfg.theme + '"',
        APP_ROOT_FROM_SCRIPTS: '"' + (env.installed ? '../../../app/' : '../app/') + '"',
        CACHE_ROOT_FROM_SCRIPTS: '"' + (env.installed ? '../../../node_modules/.app-framework-cache/' : '../node_modules/.app-framework-cache/') + '"',
        FRAMEWORK_VERSION: '"' + env.pkg.version + '"',
        FONT_FRAMEWORK7: '"' + env.cfg.loadIconFonts.framework7 + '"',
        FONT_MATERIAL: '"' + env.cfg.loadIconFonts.material + '"',
        FONT_ION: '"' + env.cfg.loadIconFonts.ion + '"',
        FONT_AWESOME: '"' + env.cfg.loadIconFonts.fontawesome + '"',
        RESET_LOCAL_STORAGE: '"' + env.cfg.resetLocalStorageOnVersionChange + '"',
        PAGES: '"' + pageStr + '"',
        NODE_ENV: '"' + mode + '"',
        DEV_BUILD: '"' + (env.arg.dev === true) + '"'
      }
    })
  )

  // Optimize ordering, reduce size
  config.plugins.push(new webpack.optimize.OccurrenceOrderPlugin())

  // Avoid exit with error in CLI
  if (mode === 'development') {
    config.plugins.push(new webpack.NoErrorsPlugin())
  }

  // Add hot file reload in development mode
  if (mode === 'development') {
    config.entry['app'].unshift(abs(__dirname, '../lib/dev-client.js'))
    config.plugins.push(new webpack.HotModuleReplacementPlugin())
  }

  // Extract CSS code to extra file
  if (mode === 'production') {
    config.plugins.push(
      new ExtractTextPlugin('[name].[hash:7].css')
    )
    config.vue = {
      loaders: {
        css: ExtractTextPlugin.extract('vue-style-loader', 'css-loader' + (env.cfg.buildSourcemaps === true ? '?sourceMap' : ''))
      }
    }
  }

  // Define icon tags for production
  let iconTags = ''
  if (mode === 'production') {
    iconTags = '<meta name="theme-color" content="' + env.cfg.iconBackgroundColor + '" />' +
               '<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />' +
               '<link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />' +
               '<link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />' +
               '<link rel="manifest" href="manifest.json" />'
  } else {
    iconTags = ''
  }

  // Plugin: HTML index file generation
  let HtmlPlugin = require('html-webpack-plugin')
  config.plugins.push(
    new HtmlPlugin({
      // filename: mode === 'development' ? 'index.html' : abs(env.proj, 'build/index.html'),
      filename: 'index.html',
      template: abs(__dirname, '../index.ejs'),
      title: env.cfg.title,
      iconTags: mode === 'development' ? '' : iconTags, // favicon.ico will be loaded by browser default from root directory
      manifest: mode === 'production' ? ' manifest="manifest.appcache"' : '',
      inject: true,
      minify: mode === 'production' ? {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      } : undefined
    })
  )

  // Add source maps
  if (mode === 'development') {
    config.devtool = '#eval-source-map'
  } else if (mode === 'production' && env.cfg.buildSourcemaps === true) {
    config.devtool = '#source-map'
  } else {
    config.devtool = undefined
  }

  // Add JS compression
  if (mode === 'production') {
    config.plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    )
  }

  // Add cache manifest
  if (mode === 'production') {
    let AppCachePlugin = require('appcache-webpack-plugin')
    config.plugins.push(
      new AppCachePlugin({
        cache: null,
        network: ['*'],
        fallback: null,
        settings: null,
        exclude: [/\.(js|css)\.map$/],
        output: 'manifest.appcache'
      })
    )
  }

  // Return object
  return config
}

// Export configuration
module.exports = {
  development: createConfiguration('development'),
  production: createConfiguration('production')
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const assert = require('assert');

const globStream = require('glob-stream');
const mkdirp = require('mkdirp');

const TarStream = require('./streams/tar-stream');
const CopyStream = require('./streams/copy-stream');

/**
 * Adds to patterns includes and excludes.
 *
 * Note: the exclude patterns will be transformed to negative patterns.
 *
 * @param {string[]} patterns — the paths to files which need to be included or excluded.
 * @param {string[]} includes — the paths to files which need to be included.
 * @param {string[]} excludes — the paths to files which need to be excluded.
 *
 * @returns {string[]}
 */
function clarifyPatterns(patterns, includes, excludes) {
    const entireIncludes = Array.isArray(includes) ? includes : [].concat(includes || []);
    const entireExcludes = Array.isArray(excludes) ? excludes : [].concat(excludes || []);

    const entirePatterns = [].concat(
        Array.isArray(patterns) ? patterns : [].concat(patterns || []),
        entireIncludes,
        entireExcludes.map(pattern => isNegativePattern(pattern) ? pattern : `!${pattern}`)
    );

    if (entireIncludes.some(isNegativePattern)) {
        throw new Error('The includes parameter of artifact should not contains negative patterns.');
    }

    if (isNegativePattern(entirePatterns[0])) {
        throw new Error('The first pattern of artifact should not be is negative.');
    }

    return entirePatterns;
}

/**
 * Returns `true` if pattern is negative.
 *
 * @param {string} pattern — the pattern with to files which need to be included or excluded.
 *
 * @returns {Boolean}
 */
function isNegativePattern(pattern) {
    return pattern.charAt(0) === '!';
}

/**
 * Creates and writes artifact to fs.
 *
 * @param {object}   artifact             The artifact info.
 * @param {string}   artifact.dest        The path to destination file or directory.
 * @param {string[]} [artifact.patterns]  The paths to files which need to be included or excluded.
 * @param {string[]} [artifact.includes]  The paths to files which need to be included.
 * @param {string[]} [artifact.excludes]  The paths to files which need to be excluded.
 * @param {boolean}  [artifact.tar]       If `true`, destination directory will be packed to tarball file.
 *                                        Otherwise files of artifact will be copied to destination directory.
 *                                        If `true`, tarball file will be gzipped.
 * @param {boolean}  [artifact.gzip]      Gzip destination tarball file.
 * @param {object}   options              The options.
 * @param {string}   options.root         The path to root directory. By default is cwd.
 * @param {boolean}  options.dotFiles     Include dotfiles.
 * @param {boolean}  options.emptyFiles   Include empty files.
 * @param {function} callback             The callback.
 */
module.exports = function (artifact, options, callback) {
    if (arguments.length === 1) { callback = artifact; }
    if (arguments.length === 2) { callback = options;  }

    assert(artifact.dest, 'You should specify the dest for artifact.');
    assert(artifact.includes || artifact.patterns,
        'You should specify the includes or patterns parameters for artifact.');

    const patterns = clarifyPatterns(artifact.patterns, artifact.includes, artifact.excludes);
    const dest = path.join(options.root, artifact.dest);
    const dir = artifact.tar ? path.dirname(dest) : dest;

    mkdirp(dir, err => {
        if (err) { return callback(err); }

        const readStream = globStream.create(patterns, {
            cwd: options.root,
            base: options.root,
            dot: options.dotFiles,
            nosort: true
        });
        const writeStream = artifact.tar
            ? new TarStream(dest, { gzip: artifact.gzip, emptyFiles: options.emptyFiles })
            : new CopyStream(dest, { emptyFiles: options.emptyFiles });

        readStream.on('error', callback);

        writeStream
            .on('error', callback)
            .on(artifact.tar ? 'close' : 'finish', () => callback(null));

        readStream.pipe(writeStream);
    });
};
<commit_msg>fix(find): don't to lose `base` info<commit_after>'use strict';

const path = require('path');
const assert = require('assert');

const globStream = require('glob-stream');
const mkdirp = require('mkdirp');

const TarStream = require('./streams/tar-stream');
const CopyStream = require('./streams/copy-stream');

/**
 * Adds to patterns includes and excludes.
 *
 * Note: the exclude patterns will be transformed to negative patterns.
 *
 * @param {string[]} patterns — the paths to files which need to be included or excluded.
 * @param {string[]} includes — the paths to files which need to be included.
 * @param {string[]} excludes — the paths to files which need to be excluded.
 *
 * @returns {string[]}
 */
function clarifyPatterns(patterns, includes, excludes) {
    const entireIncludes = Array.isArray(includes) ? includes : [].concat(includes || []);
    const entireExcludes = Array.isArray(excludes) ? excludes : [].concat(excludes || []);

    const entirePatterns = [].concat(
        Array.isArray(patterns) ? patterns : [].concat(patterns || []),
        entireIncludes,
        entireExcludes.map(pattern => isNegativePattern(pattern) ? pattern : `!${pattern}`)
    );

    if (entireIncludes.some(isNegativePattern)) {
        throw new Error('The includes parameter of artifact should not contains negative patterns.');
    }

    if (isNegativePattern(entirePatterns[0])) {
        throw new Error('The first pattern of artifact should not be is negative.');
    }

    return entirePatterns;
}

/**
 * Returns `true` if pattern is negative.
 *
 * @param {string} pattern — the pattern with to files which need to be included or excluded.
 *
 * @returns {Boolean}
 */
function isNegativePattern(pattern) {
    return pattern.charAt(0) === '!';
}

/**
 * Creates and writes artifact to fs.
 *
 * @param {object}   artifact             The artifact info.
 * @param {string}   artifact.dest        The path to destination file or directory.
 * @param {string[]} [artifact.patterns]  The paths to files which need to be included or excluded.
 * @param {string[]} [artifact.includes]  The paths to files which need to be included.
 * @param {string[]} [artifact.excludes]  The paths to files which need to be excluded.
 * @param {boolean}  [artifact.tar]       If `true`, destination directory will be packed to tarball file.
 *                                        Otherwise files of artifact will be copied to destination directory.
 *                                        If `true`, tarball file will be gzipped.
 * @param {boolean}  [artifact.gzip]      Gzip destination tarball file.
 * @param {object}   options              The options.
 * @param {string}   options.root         The path to root directory. By default is cwd.
 * @param {boolean}  options.dotFiles     Include dotfiles.
 * @param {boolean}  options.emptyFiles   Include empty files.
 * @param {function} callback             The callback.
 */
module.exports = function (artifact, options, callback) {
    if (arguments.length === 1) { callback = artifact; }
    if (arguments.length === 2) { callback = options;  }

    assert(artifact.dest, 'You should specify the dest for artifact.');
    assert(artifact.includes || artifact.patterns,
        'You should specify the includes or patterns parameters for artifact.');

    const patterns = clarifyPatterns(artifact.patterns, artifact.includes, artifact.excludes);
    const dest = path.join(options.root, artifact.dest);
    const dir = artifact.tar ? path.dirname(dest) : dest;

    mkdirp(dir, err => {
        if (err) { return callback(err); }

        const readStream = globStream.create(patterns, {
            cwd: options.root,
            dot: options.dotFiles,
            nosort: true
        });
        const writeStream = artifact.tar
            ? new TarStream(dest, { gzip: artifact.gzip, emptyFiles: options.emptyFiles })
            : new CopyStream(dest, { emptyFiles: options.emptyFiles });

        readStream.on('error', callback);

        writeStream
            .on('error', callback)
            .on(artifact.tar ? 'close' : 'finish', () => callback(null));

        readStream.pipe(writeStream);
    });
};
<|endoftext|>


<commit_before>var xmlBuilder    = require('xmlbuilder')
  , dateFormatter = require('./date-formatter.js')

var xmlrpcBuilder = exports

/**
 * Creates the XML for an XML-RPC method call.
 *
 * @param {String} method - the method name
 * @param {Array} params - params to pass in the call
 * @param {Function} callback - function (error, xml)
 *   - {Object|null} error - any errors that occurred while building the XML,
 *     otherwise null
 *   - {String} the method call XML
 */
xmlrpcBuilder.buildMethodCall = function(method, params, callback) {

  // Creates the boiler plate for the XML-RPC call
  var xml = xmlBuilder.begin('methodCall', { version: '1.0' })
    .ele('methodName')
      .txt(method)
      .up()

  // Adds each parameter to the XML-RPC call
  params = params || []
  var paramsXml = xml.ele('params')
  for (var i = 0; i < params.length; i++) {
    var paramXml = paramsXml.ele('param')
    serializeParam(params[i], paramXml)
  }

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

/**
 * Creates the XML for an XML-RPC method response.
 *
 * @param {mixed} value - the value to pass in the response
 * @param {Function} callback - function (error, xml)
 *   - {Object|null} error - any errors that occurred while building the XML,
 *     otherwise null
 *   - {String} the method response XML
 */
xmlrpcBuilder.buildMethodResponse = function(value, callback) {
  // Creates the boiler plate for the XML-RPC response
  var xml = xmlBuilder.begin('methodResponse', { version: '1.0' })

  // Adds the parameter to the XML-RPC call
  var paramXml = xml.ele('params')
    .ele('param')
  serializeParam(value, paramXml)

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

xmlrpcBuilder.buildMethodResponseWithAFault = function(fault, callback) {
  // Creates the boiler plate for the XML-RPC response
  var xml = xmlBuilder.begin('methodResponse', { version: '1.0' })

  // Adds the fault to the XML-RPC call
  var faultXml = xml.ele('fault')
  serializeParam(fault, faultXml)

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

// Serializes the parameter (and child parameters recursively) to XML
function serializeParam(param, paramXml) {

  // Adds boiler plate for the parameter
  var paramXml = paramXml.ele('value')

  switch (typeof(param)) {

    case 'boolean':
      logicalValue = param ? 1 : 0
      paramXml.ele('boolean')
        .txt(logicalValue)
      break

    case 'string':
      paramXml.ele('string')
        .txt(param)
      break

    case 'number':
      // Since no is_int or is_float in JavaScript, determines based on if a
      // remainder
      if (param % 1 == 0) {
        paramXml.ele('int')
          .txt(param)
      }
      else {
        paramXml.ele('double')
          .txt(param)
      }
      break

    case 'object':

      // Uses XML-RPC's nil
      if (param == null) {
        paramXml.ele('nil')
      }

      // Uses XML-RPC's date
      else if (param.constructor.name == 'Date') {
        //console.log(param)
        paramXml.ele('dateTime.iso8601')
          .txt(dateFormatter.encodeIso8601(param))
      }

      // Uses XML-RPC's array
      else if (param.constructor.name == 'Array') {
        var arrayXml = paramXml.ele('array')
          .ele('data')

        for (var j = 0; j < param.length; j++) {
          serializeParam(param[j], arrayXml)
        }
      }

      // Uses XML-RPC's struct
      else if (param.constructor.name == 'Object') {
        var arrayXml = paramXml.ele('struct')

        for (var key in param) {
          if (param.hasOwnProperty(key)) {
            var memberXml = arrayXml.ele('member')
            memberXml.ele('name')
              .txt(key)
            serializeParam(param[key], memberXml)
          }
        }
      }
      break
  }
}

<commit_msg>Adding support for CDATA (auto convert a string to CDATA if it contains illegal characters)<commit_after>var xmlBuilder    = require('xmlbuilder')
  , dateFormatter = require('./date-formatter.js')

var xmlrpcBuilder = exports

/**
 * Creates the XML for an XML-RPC method call.
 *
 * @param {String} method - the method name
 * @param {Array} params - params to pass in the call
 * @param {Function} callback - function (error, xml)
 *   - {Object|null} error - any errors that occurred while building the XML,
 *     otherwise null
 *   - {String} the method call XML
 */
xmlrpcBuilder.buildMethodCall = function(method, params, callback) {

  // Creates the boiler plate for the XML-RPC call
  var xml = xmlBuilder.begin('methodCall', { version: '1.0' })
    .ele('methodName')
      .txt(method)
      .up()

  // Adds each parameter to the XML-RPC call
  params = params || []
  var paramsXml = xml.ele('params')
  for (var i = 0; i < params.length; i++) {
    var paramXml = paramsXml.ele('param')
    serializeParam(params[i], paramXml)
  }

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

/**
 * Creates the XML for an XML-RPC method response.
 *
 * @param {mixed} value - the value to pass in the response
 * @param {Function} callback - function (error, xml)
 *   - {Object|null} error - any errors that occurred while building the XML,
 *     otherwise null
 *   - {String} the method response XML
 */
xmlrpcBuilder.buildMethodResponse = function(value, callback) {
  // Creates the boiler plate for the XML-RPC response
  var xml = xmlBuilder.begin('methodResponse', { version: '1.0' })

  // Adds the parameter to the XML-RPC call
  var paramXml = xml.ele('params')
    .ele('param')
  serializeParam(value, paramXml)

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

xmlrpcBuilder.buildMethodResponseWithAFault = function(fault, callback) {
  // Creates the boiler plate for the XML-RPC response
  var xml = xmlBuilder.begin('methodResponse', { version: '1.0' })

  // Adds the fault to the XML-RPC call
  var faultXml = xml.ele('fault')
  serializeParam(fault, faultXml)

  // One more up() to include the <?xml ...> declaration
  var xmlString = xml.up().toString()
  callback(null, xmlString)
}

// Serializes the parameter (and child parameters recursively) to XML
function serializeParam(param, paramXml) {

  // Adds boiler plate for the parameter
  var paramXml = paramXml.ele('value')

  switch (typeof(param)) {

    case 'boolean':
      logicalValue = param ? 1 : 0
      paramXml.ele('boolean')
        .txt(logicalValue)
      break

    case 'string':
      // @xdamman: if the string contains illegal chars, we turn it into a CDATA
      if(!param.match(/^(?![^<&]*]]>[^<&]*)[^<&]*$/)) {
        paramXml.ele('string')
          .d(param)
      }
      else {
        paramXml.ele('string')
          .txt(param)
      }
      break

    case 'number':
      // Since no is_int or is_float in JavaScript, determines based on if a
      // remainder
      if (param % 1 == 0) {
        paramXml.ele('int')
          .txt(param)
      }
      else {
        paramXml.ele('double')
          .txt(param)
      }
      break

    case 'object':

      // Uses XML-RPC's nil
      if (param == null) {
        paramXml.ele('nil')
      }

      // Uses XML-RPC's date
      else if (param.constructor.name == 'Date') {
        //console.log(param)
        paramXml.ele('dateTime.iso8601')
          .txt(dateFormatter.encodeIso8601(param))
      }

      // Uses XML-RPC's array
      else if (param.constructor.name == 'Array') {
        var arrayXml = paramXml.ele('array')
          .ele('data')

        for (var j = 0; j < param.length; j++) {
          serializeParam(param[j], arrayXml)
        }
      }

      // Uses XML-RPC's struct
      else if (param.constructor.name == 'Object') {
        var arrayXml = paramXml.ele('struct')

        for (var key in param) {
          if (param.hasOwnProperty(key)) {
            var memberXml = arrayXml.ele('member')
            memberXml.ele('name')
              .txt(key)
            serializeParam(param[key], memberXml)
          }
        }
      }
      break
  }
}

<|endoftext|>


<commit_before>module('users.timfelgentreff.sutherland.relax_bbb').requires('users.timfelgentreff.sutherland.relax').toRun(function() {

// Babelsberg required interface
// addConstraint, removeConstraint

Relax.prototype.always = function(opts, func) {
    if (opts.priority) {
        throw "soft constraints not implemented for Z3";
    }
    func.varMapping = opts.ctx;
    var constraint = new Constraint(func, this);
    this.addConstraint(constraint.constraintobjects[0]);
    this.solve();
    return constraint;
}

Relax.prototype.constraintVariableFor = function(value, ivarname) {
    if ((typeof(value) == "number") || (value === null) || (value instanceof Number)) {
        var name = ivarname + ":" + Strings.newUUID();
        var v = new RelaxNode("vars[\"" + name + "\"]", [name], this);
        this.addVar(name, value);
        return v;
    } else {
        return null;
    }
}

Relax.prototype.isConstraintObject = function() {
    return true;
}

Relax.prototype.solve = function() {
    // we solve eagerly, so just use this to throw if the error is too large
    this.iterateForUpTo(this.longWaitMillis);
    if (this.shouldRelax) {
        throw new Error("Could not satisfy constraint");
    }
}

Relax.prototype.weight = 100;

RelaxNode.prototype.isConstraintObject = function () {
    return true;
}

RelaxNode.prototype.isReadonly = function() { return false }
RelaxNode.prototype.setReadonly = function(bool) { /* ignored */ }

RelaxNode.prototype.suggestValue = function (v) {
    if (this.vars.length !== 1) throw new Error("Inconsistent RelaxNode");
    return this.solver.changeVarValue(this.vars[0], v);
}

RelaxNode.prototype.value = function () {
    // if (this.vars.length !== 1) throw new Error("Inconsistent RelaxNode");
    return this.solver.vars[this.vars[0]]
}

function _expr(o) {
    if (o instanceof RelaxNode) {
        return o.expr;
    } else {
        return o;
    }
}

RelaxNode.prototype.cnEquals = function(r) {
    return new RelaxNode(
        'Math.abs(' + this.expr + ' - (' + _expr(r) + '))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnIdentical = RelaxNode.prototype.cnEquals;

RelaxNode.prototype.cnGeq = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' >= ' + _expr(r) + ') ? 0 : Math.abs(' + this.expr + ' - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnLeq = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' <= ' + _expr(r) + ') ? 0 : Math.abs(' + this.expr + ' - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnLess = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' < ' + _expr(r) + ') ? 0 : ((' +
            this.expr + ' + (' + _expr(r) + ' * ' + this.solver.epsilon + ')) - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnGreater = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' > ' + _expr(r) + ') ? 0 : ((' +
            _expr(r) + ' + (' + _expr(r) + ' * ' + this.solver.epsilon + ')) - (' + this.expr + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnNeq = function (r) {
    return new RelaxNode(
        '((Math.abs(' + this.expr + ' - ' + _expr(r) + ') > ' + this.solver.epsilon + ') ' +
        '? 0 : Math.abs((' +
            _expr(r) + ' + (' +
                _expr(r) + ' * ' + this.solver.epsilon + ')) - (' +this.expr + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnNotIdentical = RelaxNode.prototype.cnNeq;

RelaxNode.prototype.plus = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' + ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.minus = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' - ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.times = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' * ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.divide = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' / ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.pow = function(r) {
    return new RelaxNode(
        'Math.pow(' + this.expr + ', ' + _expr(r) + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.sin = function(r) {
    return new RelaxNode(
        'Math.sin(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.cos = function(r) {
    return new RelaxNode(
        'Math.cos(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.tan = function(r) {
    return new RelaxNode(
        'Math.tan(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

}) // end of module
<commit_msg>support || in sutherland<commit_after>module('users.timfelgentreff.sutherland.relax_bbb').requires('users.timfelgentreff.sutherland.relax').toRun(function() {

// Babelsberg required interface
// addConstraint, removeConstraint

Relax.prototype.always = function(opts, func) {
    if (opts.priority) {
        throw "soft constraints not implemented for Z3";
    }
    func.varMapping = opts.ctx;
    var constraint = new Constraint(func, this);
    this.addConstraint(constraint.constraintobjects[0]);
    this.solve();
    return constraint;
}

Relax.prototype.constraintVariableFor = function(value, ivarname) {
    if ((typeof(value) == "number") || (value === null) || (value instanceof Number)) {
        var name = ivarname + ":" + Strings.newUUID();
        var v = new RelaxNode("vars[\"" + name + "\"]", [name], this);
        this.addVar(name, value);
        return v;
    } else {
        return null;
    }
}

Relax.prototype.isConstraintObject = function() {
    return true;
}

Relax.prototype.solve = function() {
    // we solve eagerly, so just use this to throw if the error is too large
    this.iterateForUpTo(this.longWaitMillis);
    if (this.shouldRelax) {
        throw new Error("Could not satisfy constraint");
    }
}

Relax.prototype.weight = 100;

RelaxNode.prototype.isConstraintObject = function () {
    return true;
}

RelaxNode.prototype.isReadonly = function() { return false }
RelaxNode.prototype.setReadonly = function(bool) { /* ignored */ }

RelaxNode.prototype.suggestValue = function (v) {
    if (this.vars.length !== 1) throw new Error("Inconsistent RelaxNode");
    return this.solver.changeVarValue(this.vars[0], v);
}

RelaxNode.prototype.value = function () {
    // if (this.vars.length !== 1) throw new Error("Inconsistent RelaxNode");
    return this.solver.vars[this.vars[0]]
}

function _expr(o) {
    if (o instanceof RelaxNode) {
        return o.expr;
    } else {
        return o;
    }
}

RelaxNode.prototype.cnEquals = function(r) {
    return new RelaxNode(
        'Math.abs(' + this.expr + ' - (' + _expr(r) + '))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnIdentical = RelaxNode.prototype.cnEquals;

RelaxNode.prototype.cnGeq = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' >= ' + _expr(r) + ') ? 0 : Math.abs(' + this.expr + ' - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnLeq = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' <= ' + _expr(r) + ') ? 0 : Math.abs(' + this.expr + ' - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnLess = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' < ' + _expr(r) + ') ? 0 : ((' +
            this.expr + ' + (' + _expr(r) + ' * ' + this.solver.epsilon + ')) - (' + _expr(r) + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnGreater = function (r) {
    return new RelaxNode(
        '((' + this.expr + ' > ' + _expr(r) + ') ? 0 : ((' +
            _expr(r) + ' + (' + _expr(r) + ' * ' + this.solver.epsilon + ')) - (' + this.expr + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnNeq = function (r) {
    return new RelaxNode(
        '((Math.abs(' + this.expr + ' - ' + _expr(r) + ') > ' + this.solver.epsilon + ') ' +
        '? 0 : Math.abs((' +
            _expr(r) + ' + (' +
                _expr(r) + ' * ' + this.solver.epsilon + ')) - (' +this.expr + ')))',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.cnNotIdentical = RelaxNode.prototype.cnNeq;

RelaxNode.prototype.plus = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' + ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.minus = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' - ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.times = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' * ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.divide = function(r) {
    return new RelaxNode(
        '(' + this.expr + ' / ' + _expr(r) + ')',
        this.vars.concat(r.vars).uniq(),
        this.solver
    )
}

RelaxNode.prototype.pow = function(r) {
    return new RelaxNode(
        'Math.pow(' + this.expr + ', ' + _expr(r) + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.sin = function(r) {
    return new RelaxNode(
        'Math.sin(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.cos = function(r) {
    return new RelaxNode(
        'Math.cos(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.tan = function(r) {
    return new RelaxNode(
        'Math.tan(' + this.expr + ')',
        this.vars,
        this.solver
    )
}

RelaxNode.prototype.cnOr = function (r) {
    return this;
}

}) // end of module
<|endoftext|>


<commit_before>define(["dojo/_base/lang", "log4javascript/log4javascript", "http://d3eyf2cx8mbems.cloudfront.net/js/loggly-0.2.1.js"],
  function(lang) {

  // log4javascript is not AMD
  // loggly is no AMD

  var LogglyAppender = function(logglyKey) {
    //noinspection JSUnresolvedVariable
    this.castor = new loggly.castor({url: "http://logs.loggly.com/inputs/" + logglyKey, level: "log"});
  };
  LogglyAppender.prototype = new log4javascript.Appender();
  LogglyAppender.prototype.layout = new log4javascript.PatternLayout("%d{dd MMM yyyy HH:mm:ss,SSS} %-5p - %f - %c - %m");
  LogglyAppender.prototype.append = function(loggingEvent) {
    var layout = this.getLayout();
    var formattedMessage = layout.format(loggingEvent);
    if (layout.ignoresThrowable() && loggingEvent.exception) {
      formattedMessage += loggingEvent.getThrowableStrRep();
    }
    if (log4javascript.Level.TRACE.isGreaterOrEqual(loggingEvent.level)) {
      this.castor.log(formattedMessage);
    }
    else if (log4javascript.Level.DEBUG.equals(loggingEvent.level)) {
      this.castor.debug(formattedMessage);
    }
    else if (log4javascript.Level.INFO.equals(loggingEvent.level)) {
      this.castor.info(formattedMessage);
    }
    else if (log4javascript.Level.WARN.equals(loggingEvent.level)) {
      this.castor.warn(formattedMessage);
    }
    else if (loggingEvent.level.isGreaterOrEqual(log4javascript.Level.ERROR)) {
      this.castor.error(formattedMessage);
    }
  };

  LogglyAppender.prototype.toString = function() {
    return "LogglyAppender";
  };

  function getLogger(name) {
    // summary:
    //   Function that returns a configured log4javascript logger for `name`.
    //   Best practice is to use the module.id as name.
    //
    //   The logger has a console appender. All apenders defined on the function
    //   are also added.

    var logger = log4javascript.getLogger(name);
    var layout = new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %-5p - %c - %m");
    var consoleAppender = new log4javascript.BrowserConsoleAppender();
    consoleAppender.setLayout(layout);
    logger.addAppender(consoleAppender);
    if (getLogger.appenders) {
      getLogger.appenders.forEach(function(appender) {
        logger.addAppender(appender);
      });
    }
    return logger;
  }

  getLogger.appenders = [];
  getLogger.LogglyAppender = LogglyAppender;

  lang.mixin(getLogger, log4javascript);

  return getLogger;
});
<commit_msg>use uncompressed version for logger; a build will compress itself<commit_after>define(["dojo/_base/lang", "log4javascript/log4javascript_uncompressed", "http://d3eyf2cx8mbems.cloudfront.net/js/loggly-0.2.1.js"],
  function(lang) {

  // log4javascript is not AMD
  // loggly is no AMD

  var LogglyAppender = function(logglyKey) {
    //noinspection JSUnresolvedVariable
    this.castor = new loggly.castor({url: "http://logs.loggly.com/inputs/" + logglyKey, level: "log"});
  };
  LogglyAppender.prototype = new log4javascript.Appender();
  LogglyAppender.prototype.layout = new log4javascript.PatternLayout("%d{dd MMM yyyy HH:mm:ss,SSS} %-5p - %f - %c - %m");
  LogglyAppender.prototype.append = function(loggingEvent) {
    var layout = this.getLayout();
    var formattedMessage = layout.format(loggingEvent);
    if (layout.ignoresThrowable() && loggingEvent.exception) {
      formattedMessage += loggingEvent.getThrowableStrRep();
    }
    if (log4javascript.Level.TRACE.isGreaterOrEqual(loggingEvent.level)) {
      this.castor.log(formattedMessage);
    }
    else if (log4javascript.Level.DEBUG.equals(loggingEvent.level)) {
      this.castor.debug(formattedMessage);
    }
    else if (log4javascript.Level.INFO.equals(loggingEvent.level)) {
      this.castor.info(formattedMessage);
    }
    else if (log4javascript.Level.WARN.equals(loggingEvent.level)) {
      this.castor.warn(formattedMessage);
    }
    else if (loggingEvent.level.isGreaterOrEqual(log4javascript.Level.ERROR)) {
      this.castor.error(formattedMessage);
    }
  };

  LogglyAppender.prototype.toString = function() {
    return "LogglyAppender";
  };

  function getLogger(name) {
    // summary:
    //   Function that returns a configured log4javascript logger for `name`.
    //   Best practice is to use the module.id as name.
    //
    //   The logger has a console appender. All apenders defined on the function
    //   are also added.

    var logger = log4javascript.getLogger(name);
    var layout = new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %-5p - %c - %m");
    var consoleAppender = new log4javascript.BrowserConsoleAppender();
    consoleAppender.setLayout(layout);
    logger.addAppender(consoleAppender);
    if (getLogger.appenders) {
      getLogger.appenders.forEach(function(appender) {
        logger.addAppender(appender);
      });
    }
    return logger;
  }

  getLogger.appenders = [];
  getLogger.LogglyAppender = LogglyAppender;

  lang.mixin(getLogger, log4javascript);

  return getLogger;
});
<|endoftext|>


<commit_before>
/* Prettyify */
$( document ).ready(function() {
    prettyPrint();
});

/* Scrollspy */
var navHeight = $('.navbar').outerHeight(true) + 10

$('body').scrollspy({
    target: '.bs-sidebar',
    offset: navHeight
})

/* Prevent disabled links from causing a page reload */
$("li.disabled a").click(function() {
    event.preventDefault();
});

/* Adjust the scroll height of anchors to compensate for the fixed navbar */
window.disableShift = false;
var shiftWindow = function() {
    if (window.disableShift) {
        window.disableShift = false;
    } else {
        /* If we're at the bottom of the page, don't erronously scroll up */
        var scrolledToBottomOfPage = (
            (window.innerHeight + window.scrollY) >= document.body.offsetHeight
        );
        if (!scrolledToBottomOfPage) {
            scrollBy(0, -60);
        };
    };
};
if (location.hash) {shiftWindow();}
window.addEventListener("hashchange", shiftWindow);

/* Deal with clicks on nav links that do not change the current anchor link. */
$("ul.nav a" ).click(function() {
    var href = this.href;
    var suffix = location.hash;
    var matchesCurrentHash = (href.indexOf(suffix, href.length - suffix.length) !== -1);
    if (location.hash && matchesCurrentHash) {
        /* Force a single 'hashchange' event to occur after the click event */
        window.disableShift = true;
        location.hash='';
    };
});
<commit_msg>Apply 'table' css class to all tables<commit_after>
/* Prettyify */
$( document ).ready(function() {
    prettyPrint();
    $('table').addClass('table');
});

/* Scrollspy */
var navHeight = $('.navbar').outerHeight(true) + 10

$('body').scrollspy({
    target: '.bs-sidebar',
    offset: navHeight
})

/* Prevent disabled links from causing a page reload */
$("li.disabled a").click(function() {
    event.preventDefault();
});

/* Adjust the scroll height of anchors to compensate for the fixed navbar */
window.disableShift = false;
var shiftWindow = function() {
    if (window.disableShift) {
        window.disableShift = false;
    } else {
        /* If we're at the bottom of the page, don't erronously scroll up */
        var scrolledToBottomOfPage = (
            (window.innerHeight + window.scrollY) >= document.body.offsetHeight
        );
        if (!scrolledToBottomOfPage) {
            scrollBy(0, -60);
        };
    };
};
if (location.hash) {shiftWindow();}
window.addEventListener("hashchange", shiftWindow);

/* Deal with clicks on nav links that do not change the current anchor link. */
$("ul.nav a" ).click(function() {
    var href = this.href;
    var suffix = location.hash;
    var matchesCurrentHash = (href.indexOf(suffix, href.length - suffix.length) !== -1);
    if (location.hash && matchesCurrentHash) {
        /* Force a single 'hashchange' event to occur after the click event */
        window.disableShift = true;
        location.hash='';
    };
});
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community 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://opensource.org/licenses/ECL-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 _ = require('underscore');

var OAE = require('oae-util/lib/oae');
var PreviewProcessorAPI = require('oae-preview-processor');
var Util = require('oae-util/lib/util');

var DiscussionsAPI = require('oae-discussions');
var DiscussionsConstants = require('oae-discussions/lib/constants').DiscussionsConstants;

//////////////////////////////
// CREATE / GET DISCUSSIONS //
//////////////////////////////

/*!
 * Create a new discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/create', function(req, res) {

    var members = {};
    if (_.isArray(req.body.managers)) {
        _.each(req.body.managers, function(manager) {
            members[manager] = DiscussionsConstants.roles.MANAGER;
        });
    } else if (_.isString(req.body.managers)) {
        members[req.body.managers] = DiscussionsConstants.roles.MANAGER;
    }

    if (_.isArray(req.body.members)) {
        _.each(req.body.members, function(member) {
            members[member] = DiscussionsConstants.roles.MEMBER;
        });
    } else if (_.isString(req.body.members)) {
        members[req.body.members] = DiscussionsConstants.roles.MEMBER;
    }

    DiscussionsAPI.Discussions.createDiscussion(req.ctx, req.body.displayName, req.body.description, req.body.visibility, members, null, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/*!
 * Update a discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.updateDiscussion(req.ctx, req.params.discussionId, req.body, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/*!
 * Delete a discussion
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.deleteDiscussion(req.ctx, req.params.discussionId, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/*!
 * Get a user or group's discussions library
 */
OAE.tenantRouter.on('get', '/api/discussion/library/:principalId', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 12, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionsLibrary(req.ctx, req.params.principalId, req.query.start, limit, function(err, discussions, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': discussions, 'nextToken': nextToken});
    });
});

/*!
 * Delete a discussion from a user or group library
 */
OAE.tenantRouter.on('delete', '/api/discussion/library/:principalId/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.removeDiscussionFromLibrary(req.ctx, req.params.principalId, req.params.discussionId, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200);
    });
});

/*!
 * Get a full discussion profile
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.getFullDiscussionProfile(req.ctx, req.params.discussionId, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

//////////////////////////////////////
// UPDATE / GET DISCUSSIONS MEMBERS //
//////////////////////////////////////

/*!
 * Share a discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/share', function(req, res) {

    var members = (_.isArray(req.body.members)) ? req.body.members : [req.body.members];
    members = _.compact(members);

    DiscussionsAPI.Discussions.shareDiscussion(req.ctx, req.params.discussionId, members, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/*!
 * Set discussion permissions
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/members', function(req, res) {

    // Parse the incoming false values
    var permissionUpdates = {};
    _.each(req.body, function(value, key) {
        permissionUpdates[key] = Util.castToBoolean(value);
    });

    DiscussionsAPI.Discussions.setDiscussionPermissions(req.ctx, req.params.discussionId, permissionUpdates, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/*!
 * Get discussion members
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/members', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionMembers(req.ctx, req.params.discussionId, req.query.start, limit, function(err, members, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': members, 'nextToken': nextToken});
    });
});

//////////////////////////////////////
// CREATE / GET DISCUSSION MESSAGES //
//////////////////////////////////////

/*!
 * Get a list of messages from the discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/messages', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getMessages(req.ctx, req.params.discussionId, req.query.start, limit, function(err, messages, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': messages, 'nextToken': nextToken});
    });
});

/*!
 * Create a new message in a discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/messages', function(req, res) {
    DiscussionsAPI.Discussions.createMessage(req.ctx, req.params.discussionId, req.body.body, req.body.replyTo, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/*!
 * Delete a message in a discussion
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId/messages/:created', function(req, res) {
    DiscussionsAPI.Discussions.deleteMessage(req.ctx, req.params.discussionId, req.params.created, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});
<commit_msg>add REST documentation for discussions module<commit_after>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community 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://opensource.org/licenses/ECL-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 _ = require('underscore');

var OAE = require('oae-util/lib/oae');
var PreviewProcessorAPI = require('oae-preview-processor');
var Util = require('oae-util/lib/util');

var DiscussionsAPI = require('oae-discussions');
var DiscussionsConstants = require('oae-discussions/lib/constants').DiscussionsConstants;

//////////////////////////////
// CREATE / GET DISCUSSIONS //
//////////////////////////////

/**
 * @REST postDiscussionCreate
 *
 * Create a new discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/create
 * @BodyParam   {string}                description         Description of discussion
 * @BodyParam   {string}                displayName         Name to display for discussion
 * @BodyParam   {string}                managers            Unique identifier(s) for manager(s) of the discussion (user creating discussion is always a manager)
 * @BodyParam   {string}                members             Unique identifiers(s) for participant(s) in the discussion
 * @BodyParam   {string}                visibility          Visibility for discussion ("loggedin","private","public")
 * @Return      {Discussion}                                Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/create', function(req, res) {

    var members = {};
    if (_.isArray(req.body.managers)) {
        _.each(req.body.managers, function(manager) {
            members[manager] = DiscussionsConstants.roles.MANAGER;
        });
    } else if (_.isString(req.body.managers)) {
        members[req.body.managers] = DiscussionsConstants.roles.MANAGER;
    }

    if (_.isArray(req.body.members)) {
        _.each(req.body.members, function(member) {
            members[member] = DiscussionsConstants.roles.MEMBER;
        });
    } else if (_.isString(req.body.members)) {
        members[req.body.members] = DiscussionsConstants.roles.MEMBER;
    }

    DiscussionsAPI.Discussions.createDiscussion(req.ctx, req.body.displayName, req.body.description, req.body.visibility, members, null, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST postDiscussionDiscussionId
 *
 * Update a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to update
 * @BodyParam   {string}                description         Description of discussion
 * @BodyParam   {string}                displayName         Name to display for discussion
 * @BodyParam   {string}                visibility          Visibility for discussion ("loggedin","private","public")
 * @Return      {Discussion}                                Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.updateDiscussion(req.ctx, req.params.discussionId, req.body, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST deleteDiscussionDiscussionId
 *
 * Delete a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to update
 * @Return      {void}
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.deleteDiscussion(req.ctx, req.params.discussionId, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST getDiscussionLibraryPrincipalId
 *
 * Get a user or group's discussions library
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/library/{principalId}
 * @PathParam   {string}                principalId         Unique identifier for user or group whose discussions are requested
 * @QueryParam  {number}                [limit]             Maximum number of discussions to return (defaults to 12, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {DiscussionsLibrary}                        Returns an object containing followers of user
 */
OAE.tenantRouter.on('get', '/api/discussion/library/:principalId', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 12, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionsLibrary(req.ctx, req.params.principalId, req.query.start, limit, function(err, discussions, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': discussions, 'nextToken': nextToken});
    });
});

/**
 * @REST deleteDiscussionLibraryPrincipalIdDiscussionId
 *
 * Delete a discussion from a user or group library
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/library/{principalId}/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to remove
 * @PathParam   {string}                principalId         Unique identifier for user or group whose library is affected
 * @Return      {void}
 */
OAE.tenantRouter.on('delete', '/api/discussion/library/:principalId/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.removeDiscussionFromLibrary(req.ctx, req.params.principalId, req.params.discussionId, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionId
 *
 * Get a full discussion profile
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to retrieve
 * @Return      {DiscussionDetails}                         Returns an object containing the detailed discussion profile
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.getFullDiscussionProfile(req.ctx, req.params.discussionId, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

//////////////////////////////////////
// UPDATE / GET DISCUSSIONS MEMBERS //
//////////////////////////////////////

/**
 * @REST postDiscussionDiscussionIdShare
 *
 * Share a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/share
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {string}                members             Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/share', function(req, res) {

    var members = (_.isArray(req.body.members)) ? req.body.members : [req.body.members];
    members = _.compact(members);

    DiscussionsAPI.Discussions.shareDiscussion(req.ctx, req.params.discussionId, members, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST postDiscussionDiscussionIdMembers
 *
 * Set discussion permissions
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {string}                members             Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/members', function(req, res) {

    // Parse the incoming false values
    var permissionUpdates = {};
    _.each(req.body, function(value, key) {
        permissionUpdates[key] = Util.castToBoolean(value);
    });

    DiscussionsAPI.Discussions.setDiscussionPermissions(req.ctx, req.params.discussionId, permissionUpdates, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionIdMembers
 *
 * Get discussion members
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of users to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {DiscussionMembers}                         Returns an object containing members of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/members', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionMembers(req.ctx, req.params.discussionId, req.query.start, limit, function(err, members, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': members, 'nextToken': nextToken});
    });
});

//////////////////////////////////////
// CREATE / GET DISCUSSION MESSAGES //
//////////////////////////////////////

/**
 * @REST getDiscussionDiscussionIdMessages
 *
 * Get a list of messages from the discussion
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of messages to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {DiscussionMessages}                        Returns an object containing messages of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/messages', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getMessages(req.ctx, req.params.discussionId, req.query.start, limit, function(err, messages, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': messages, 'nextToken': nextToken});
    });
});

/**
 * @REST postDiscussionDiscussionIdMessages
 *
 * Create a new message in a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}                discussionId        Unique identifier for discusion for new message
 * @BodyParam   {string}                body                Content of new message
 * @BodyParam   {string}                replyTo             Created time for message to which the new message is a reply
 * @Return      {Message}                                   Returns an object representing the new message
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/messages', function(req, res) {
    DiscussionsAPI.Discussions.createMessage(req.ctx, req.params.discussionId, req.body.body, req.body.replyTo, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST deletedDiscussionDiscussionIdMessages/Created
 *
 * Delete a message in a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}/messages{creaeted}
 * @PathParam   {string}                created             Creation time of message to delete
 * @PathParam   {string}                discussionId        Unique identifier for discusion containing message
 * @Return      {Message}                                   Returns an object representing the deleted message
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId/messages/:created', function(req, res) {
    DiscussionsAPI.Discussions.deleteMessage(req.ctx, req.params.discussionId, req.params.created, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

// Add the REST models for Discussions

/**
 * @RESTModel Discussion
 *
 * @Required    [created,createdBy,description,displayName,id,lastModified,profilePath,resourceType,tenant,visibility]
 * @Property    {number}        created                 Time discussion was created (epoch format)
 * @Property    {string}        createdBy               Unique identifier of user that created discussion
 * @Property    {string}        description             Description of discussion
 * @Property    {string}        displayName             Name to display for discussion
 * @Property    {string}        id                      Unique identifier for discusion
 * @Property    {number}        lastModified            Time discussion was last modified (epoch format)
 * @Property    {string}        profilePath             URL to discussion page
 * @Property    {string}        resourceType            Type of resource ("discussion")
 * @Property    {Tenant}        tenant                  Tenant for discussion
 * @Property    {string}        visibility              Visibility of discussion ("loggedin","private","public")
 */

/**
 * @RESTModel DiscussionDetails
 *
 * @Required    [canPost,canShare,created,createdBy,description,displayName,id,isManager,lastModified,profilePath,resourceType,signature,tenant,visibility]
 * @Property    {boolean}       canPost                 Is current user allowed to post messages to discussion
 * @Property    {boolean}       canShare                Is current user allowed to share discussion
 * @Property    {number}        created                 Time discussion was created (epoch format)
 * @Property    {User}          createdBy               Full profile of user that created discussion
 * @Property    {string}        description             Description of discussion
 * @Property    {string}        displayName             Name to display for discussion
 * @Property    {string}        id                      Unique identifier for discusion
 * @Property    {boolean}       isManager               Is current user allowed to manage discussion
 * @Property    {number}        lastModified            Time discussion was last modified (epoch format)
 * @Property    {string}        profilePath             URL to discussion page
 * @Property    {string}        resourceType            Type of resource ("discussion")
 * @Property    {Signature}     signature               Access control information for discussion
 * @Property    {Tenant}        tenant                  Tenant for discussion
 * @Property    {string}        visibility              Visibility of discussion ("loggedin","private","public")
 */

/**
 * @RESTModel DiscussionMembers
 *
 * @Required  [nextToken,results]
 * @Property  {Member[]}        results                 Array of members
 * @Property  {string}          nextToken               Marker to allow continuation of search (empty if search has been exhausted)
 */

/**
 * @RESTModel DiscussionMessages
 *
 * @Required  [nextToken,results]
 * @Property  {Message[]}       results                 Array of messages
 * @Property  {string}          nextToken               Marker to allow continuation of search (empty if search has been exhausted)
 */

/**
 * @RESTModel DiscussionsLibrary
 *
 * @Required  [nextToken,results]
 * @Property  {Discussion[]}    results                 Array of discussions
 * @Property  {string}          nextToken               Marker to allow continuation of search (empty if search has been exhausted)
 */

/**
 * @RESTModel Member
 *
 * @Required  [profile,role]
 * @Property  {User}            profile                 Profile of member
 * @Property  {string}          role                    Role of member ("manager","member")
 */

/**
 * @RESTModel Message
 *
 * @Required  [created,id,level,messageBoxId, replyTo, threadKey]
 * @Property  {string}          body                    Content of message
 * @Property  {string}          created                 Time message was created (epoch format)
 * @Property  {User}            createdBy               User that created message (not present if message deleted)
 * @Property  {string}          deleted                 Time message was deleted (epoch format)
 * @Property  {string}          id                      Unique identifier for message (discussion id + "#" + creation time)
 * @Property  {number}          level                   Nesting level within message/replies (root is 0)
 * @Property  {string}          messageBoxId            Unique identifier of discussion
 * @Property  {string}          replyTo                 Creation time of parent message
 * @Property  {string}          threadKey               Unique identifier for message threat (concatenation of creation times + "#" terminated by "|")
 */
<|endoftext|>


<commit_before>import webpack from 'webpack';
import AssetsPlugin from 'assets-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import postcssImport from 'postcss-import';
import precss from 'precss';
import autoprefixer from 'autoprefixer';
import { merge } from 'lodash';
import { resolve } from 'path';

export const ROOT = resolve(__dirname, '../');
export const buildPath = `${ROOT}/build`;
export const buildStaticPath = `${buildPath}/public`;
export const srcPath = `${ROOT}/src`;
export const AUTOPREFIXER_BROWSERS = [
  'Android 2.3',
  'Android >= 4',
  'Chrome >= 35',
  'Firefox >= 31',
  'Explorer >= 9',
  'iOS >= 7',
  'Opera >= 12',
  'Safari >= 7.1',
];
export const DEBUG = !process.argv.includes('--release');
export const VERBOSE = process.argv.includes('--verbose');
export const WATCH = process.argv.includes('--watch');
const GLOBALS = {
  'process.env.NODE_ENV': DEBUG ? `'development'` : `'production'`,
  __DEV__: DEBUG,
};
export const stats = {
  colors: true,
  reasons: DEBUG,
  hash: VERBOSE,
  version: VERBOSE,
  timings: true,
  chunks: VERBOSE,
  chunkModules: VERBOSE,
  cached: VERBOSE,
  cachedAssets: VERBOSE,
};

const webpackCommon = {
  output: {
    publicPath: '/',
    sourcePrefix: ' ',
  },
  cache: DEBUG,
  debug: DEBUG,
  stats,
  resolve: {
    extensions: ['', '.jsx', '.json', '.js'],
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015', 'stage-0', 'stage-1', 'stage-2', 'stage-3'],
        },
      }, {
        test: /\.json$/,
        loader: 'json-loader',
      }, {
        test: /\.scss$/,
        ...(DEBUG ? {
          loaders: [
            'style-loader',
            'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
            'postcss-loader',
          ],
        } : {
          loader: ExtractTextPlugin.extract(
            'style-loader',
            'css-loader?minimize&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
            'postcss-loader',
          ),
        }),
      }, {
        test: /\.txt$/,
        loader: 'raw-loader',
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
        loader: 'url-loader?limit=10000',
      }, {
        test: /\.(eot|ttf|wav|mp3)$/,
        loader: 'file-loader',
      },
    ],
    postcss(bundler) {
      return [
        postcssImport({
          addDependencyTo: bundler,
        }),
        precss(),
        autoprefixer({
          browsers: AUTOPREFIXER_BROWSERS,
        }),
      ];
    },
  },
};

export const webpackCommonPlugins = [
  new webpack.DefinePlugin(GLOBALS),
  new webpack.optimize.OccurenceOrderPlugin(),
  ...(DEBUG ? [
    // development
  ] : [
    // productions
    new ExtractTextPlugin('style.css', {
      allChunks: true,
    }),
  ]),
];

export const webpackClient = merge({}, webpackCommon, {
  entry: {
    app: [
      ...(DEBUG ? ['webpack-hot-middleware/client'] : []),
      'babel-polyfill',
      `${srcPath}/client.jsx`,
    ],
  },
  target: 'web',
  output: {
    path: buildStaticPath,
    filename: DEBUG ? '[name].js?[hash]' : '[name].[hash].js',
  },
  devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
  plugins: [
    ...webpackCommonPlugins,
    new AssetsPlugin({
      path: buildPath,
      filename: 'assets.json',
    }),
    ...(DEBUG ? [
      // development
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoErrorsPlugin(),
    ] : [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          screw_ie8: true,
          warnings: VERBOSE,
        },
      }),
      new webpack.optimize.AggressiveMergingPlugin(),
    ]),
  ],
});

if (DEBUG) {
  webpackClient.module.loaders
    .filter(x => x.loader === 'babel-loader')
    .forEach(x => x.query = {
      ...x.query,
      plugins: [
        ['react-transform', {
          transforms: [{
            transform: 'react-transform-hmr',
            imports: ['react'],
            locals: ['module'],
          }, {
            'transform': 'react-transform-catch-errors',
            'imports': ['react', 'redbox-react'],
          }],
        }],
      ],
    });
}

export const webpackServer = merge({}, webpackCommon, {
  entry: {
    server: [
      'babel-polyfill',
      `${srcPath}/server.jsx`,
    ],
  },
  output: {
    path: buildPath,
    filename: '[name].js',
    libraryTarget: 'commonjs2',
  },
  devtool: 'source-map',
  target: 'node',
  node: {
    console: false,
    global: false,
    process: false,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },
  externals: [
    /^\.\/assets\.json$/,
    function filter(context, request, cb) {
      const isExternal = request.match(/^[@a-z][a-z\/\.\-0-9]*$/i);
      return cb(null, Boolean(isExternal));
    },
  ],
  plugins: [
    ...webpackCommonPlugins,
    new webpack.BannerPlugin(
      `require('source-map-support').install();`,
      { raw: true, entryOnly: false }
    ),
  ],
});

if (DEBUG) {
  webpackServer.module.loaders
    .filter(x => x.loaders && x.loaders[0] === 'style-loader')
    .forEach(x => x.loaders.shift());
}
<commit_msg>Fix postcss option missed<commit_after>import webpack from 'webpack';
import AssetsPlugin from 'assets-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import postcssImport from 'postcss-import';
import precss from 'precss';
import autoprefixer from 'autoprefixer';
import { merge } from 'lodash';
import { resolve } from 'path';

export const ROOT = resolve(__dirname, '../');
export const buildPath = `${ROOT}/build`;
export const buildStaticPath = `${buildPath}/public`;
export const srcPath = `${ROOT}/src`;
export const AUTOPREFIXER_BROWSERS = [
  'Android 2.3',
  'Android >= 4',
  'Chrome >= 35',
  'Firefox >= 31',
  'Explorer >= 9',
  'iOS >= 7',
  'Opera >= 12',
  'Safari >= 7.1',
];
export const DEBUG = !process.argv.includes('--release');
export const VERBOSE = process.argv.includes('--verbose');
export const WATCH = process.argv.includes('--watch');
const GLOBALS = {
  'process.env.NODE_ENV': DEBUG ? `'development'` : `'production'`,
  __DEV__: DEBUG,
};
export const stats = {
  colors: true,
  reasons: DEBUG,
  hash: VERBOSE,
  version: VERBOSE,
  timings: true,
  chunks: VERBOSE,
  chunkModules: VERBOSE,
  cached: VERBOSE,
  cachedAssets: VERBOSE,
};

const webpackCommon = {
  output: {
    publicPath: '/',
    sourcePrefix: ' ',
  },
  cache: DEBUG,
  debug: DEBUG,
  stats,
  resolve: {
    extensions: ['', '.jsx', '.json', '.js'],
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015', 'stage-0', 'stage-1', 'stage-2', 'stage-3'],
        },
      }, {
        test: /\.json$/,
        loader: 'json-loader',
      }, {
        test: /\.scss$/,
        ...(DEBUG ? {
          loaders: [
            'style-loader',
            'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
            'postcss-loader',
          ],
        } : {
          loader: ExtractTextPlugin.extract(
            'style-loader',
            'css-loader?minimize&modules&importLoaders=1&localIdentName=[hash:base64:5]!postcss-loader',
          ),
        }),
      }, {
        test: /\.txt$/,
        loader: 'raw-loader',
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
        loader: 'url-loader?limit=10000',
      }, {
        test: /\.(eot|ttf|wav|mp3)$/,
        loader: 'file-loader',
      },
    ],
  },
  postcss(bundler) {
    return [
      postcssImport({
        addDependencyTo: bundler,
      }),
      precss(),
      autoprefixer({
        browsers: AUTOPREFIXER_BROWSERS,
      }),
    ];
  },
};

export const webpackCommonPlugins = [
  new webpack.DefinePlugin(GLOBALS),
  new webpack.optimize.OccurenceOrderPlugin(),
  ...(DEBUG ? [
    // development
  ] : [
    // productions
    new ExtractTextPlugin('style.css', {
      allChunks: true,
    }),
  ]),
];

export const webpackClient = merge({}, webpackCommon, {
  entry: {
    app: [
      ...(DEBUG ? ['webpack-hot-middleware/client'] : []),
      'babel-polyfill',
      `${srcPath}/client.jsx`,
    ],
  },
  target: 'web',
  output: {
    path: buildStaticPath,
    filename: DEBUG ? '[name].js?[hash]' : '[name].[hash].js',
  },
  devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
  plugins: [
    ...webpackCommonPlugins,
    new AssetsPlugin({
      path: buildPath,
      filename: 'assets.json',
    }),
    ...(DEBUG ? [
      // development
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NoErrorsPlugin(),
    ] : [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          screw_ie8: true,
          warnings: VERBOSE,
        },
      }),
      new webpack.optimize.AggressiveMergingPlugin(),
    ]),
  ],
});

if (DEBUG) {
  webpackClient.module.loaders
    .filter(x => x.loader === 'babel-loader')
    .forEach(x => x.query = {
      ...x.query,
      plugins: [
        ['react-transform', {
          transforms: [{
            transform: 'react-transform-hmr',
            imports: ['react'],
            locals: ['module'],
          }, {
            'transform': 'react-transform-catch-errors',
            'imports': ['react', 'redbox-react'],
          }],
        }],
      ],
    });
}

export const webpackServer = merge({}, webpackCommon, {
  entry: {
    server: [
      'babel-polyfill',
      `${srcPath}/server.jsx`,
    ],
  },
  output: {
    path: buildPath,
    filename: '[name].js',
    libraryTarget: 'commonjs2',
  },
  devtool: 'source-map',
  target: 'node',
  node: {
    console: false,
    global: false,
    process: false,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },
  externals: [
    /^\.\/assets\.json$/,
    function filter(context, request, cb) {
      const isExternal = request.match(/^[@a-z][a-z\/\.\-0-9]*$/i);
      return cb(null, Boolean(isExternal));
    },
  ],
  plugins: [
    ...webpackCommonPlugins,
    new webpack.BannerPlugin(
      `require('source-map-support').install();`,
      { raw: true, entryOnly: false }
    ),
  ],
});

if (DEBUG) {
  webpackServer.module.loaders
    .filter(x => x.loaders && x.loaders[0] === 'style-loader')
    .forEach(x => {
      x.loaders.shift();
      x.loaders[0] = x.loaders[0].replace(/css-loader?/, 'css-loader/locals?');
    });
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (http://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2015 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import GitRepo from 'git-repository';
import task from './lib/task';
import fetch from './lib/fetch';

// TODO: Update deployment URL
// For more information visit http://gitolite.com/deploy.html
const getHerokuRemote = () => ({
  name: 'heroku',
  url: 'https://git.heroku.com/ancient-ravine-1054.git',
  website: 'http://ancient-ravine-1054.herokuapp.com/'
});

/**
 * Deploy the contents of the `/build` folder to a remote
 * server via Git. Example: `npm run deploy -- production`
 */
export default task('deploy', async () => {
  // By default deploy to heroku
  const remote = getHerokuRemote();

  // Initialize a new Git repository inside the `/build` folder
  // if it doesn't exist yet
  const repo = await GitRepo.open('build', { init: true });
  await repo.setRemote(remote.name, remote.url);

  // Fetch the remote repository if it exists
  if ((await repo.hasRef(remote.url, 'master'))) {
    await repo.fetch(remote.name);
    await repo.reset(`${remote.name}/master`, { hard: true });
    await repo.clean({ force: true });
  }

  // Build the project in RELEASE mode which
  // generates optimized and minimized bundles
  process.argv.push('release');
  await require('./build')();

  // Push the contents of the build folder to the remote server via Git
  await repo.add('--all .');
  await repo.commit('Update');
  await repo.push(remote.name, 'master');

  // Check if the site was successfully deployed
  const response = await fetch(remote.website);
  console.log(`${remote.website} -> ${response.statusCode}`);
});
<commit_msg>Update git heroku remote<commit_after>/**
 * React Starter Kit (http://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2015 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import GitRepo from 'git-repository';
import task from './lib/task';
import fetch from './lib/fetch';

// TODO: Update deployment URL
// For more information visit http://gitolite.com/deploy.html
const getHerokuRemote = () => ({
  name: 'heroku',
  url: 'https://git.heroku.com/workable-observatory.git',
  website: 'http://workable-observatory.herokuapp.com/'
});

/**
 * Deploy the contents of the `/build` folder to a remote
 * server via Git. Example: `npm run deploy -- production`
 */
export default task('deploy', async () => {
  // By default deploy to heroku
  const remote = getHerokuRemote();

  // Initialize a new Git repository inside the `/build` folder
  // if it doesn't exist yet
  const repo = await GitRepo.open('build', { init: true });
  await repo.setRemote(remote.name, remote.url);

  // Fetch the remote repository if it exists
  if ((await repo.hasRef(remote.url, 'master'))) {
    await repo.fetch(remote.name);
    await repo.reset(`${remote.name}/master`, { hard: true });
    await repo.clean({ force: true });
  }

  // Build the project in RELEASE mode which
  // generates optimized and minimized bundles
  process.argv.push('release');
  await require('./build')();

  // Push the contents of the build folder to the remote server via Git
  await repo.add('--all .');
  await repo.commit('Update');
  await repo.push(remote.name, 'master');

  // Check if the site was successfully deployed
  const response = await fetch(remote.website);
  console.log(`${remote.website} -> ${response.statusCode}`);
});
<|endoftext|>