<commit_before>import passport from 'passport'
import { Strategy as LocalStrategy } from 'passport-local'
import { BasicStrategy } from 'passport-http'
import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password'
import { Strategy as BearerStrategy } from 'passport-http-bearer'
import { OAuthUser, OAuthClient, OAuthToken } from '../models'

const local = new LocalStrategy(async (usernameOrEmail, password, done) => {
  try {
    const user = await OAuthUser.getByUsernameOrEmail(usernameOrEmail)
    if (!user) return done(null, false, { message: 'Password or username/email are incorrect' })
    const isAuthenticated = await user.authenticate(password)
    if (!isAuthenticated) return done(null, false, { message: 'Password or username are incorrect' })
    done(null, user)
  } catch (err) {
    done(err)
  }
})

const basic = new BasicStrategy(async (username, password, done) => {
  try {
    const client = await OAuthClient.findById(username)
    if (!client) return done(null, false)
    if (client.secret !== password) return done(null, false)
    done(null, client)
  } catch (err) {
    done(err)
  }
})

const oauth2ClientPassword = new ClientPasswordStrategy(async (clientId, clientSecret, done) => {
  try {
    const client = await OAuthClient.findById(clientId)
    if (!client) return done(null, false)
    if (client.secret !== clientSecret) return done(null, false)
    return done(null, client)
  } catch (err) {
    done(err)
  }
})

const bearer = new BearerStrategy(async (accessToken, done) => {
  try {
    const token = await OAuthToken.getByAccessToken(accessToken)
    if (!token) return done(null, false)

    if (!token.isValid()) {
      await token.remove()
      return done(null, false)
    }

    const client = await OAuthClient.findById(token.client)
    // if (client.trusted) return done(null, client, token)

    if (token.user !== null) {
      const user = await OAuthUser.findById(token.user)
      if (!user) return done(null, false)
      return done(null, user.toJSON(), token)
    }

    done(null, client.toJSON(), token)
  } catch (err) {
    done(err)
  }
})

export default function setupPassport () {
  passport.use(local)
  passport.use(basic)
  passport.use(oauth2ClientPassword)
  passport.use(bearer)
  passport.serializeUser((user, done) => done(null, user))
  passport.deserializeUser((user, done) => done(null, user))
}
<commit_msg>refactor: passport<commit_after>import passport from 'passport'
import { Strategy as LocalStrategy } from 'passport-local'
import { BasicStrategy } from 'passport-http'
import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password'
import { Strategy as BearerStrategy } from 'passport-http-bearer'
import { OAuthUser, OAuthClient, OAuthToken } from '../models'

/**
 * LocalStrategy
 *
 * This strategy is used to authenticate users based on a username and password.
 * Anytime a request is made to authorize an application, we must ensure that
 * a user is logged in before asking them to approve the request.
 */
const local = new LocalStrategy(async (usernameOrEmail, password, done) => {
  try {
    const user = await OAuthUser.getByUsernameOrEmail(usernameOrEmail)
    if (!user) return done(null, false)
    const isAuthenticated = await user.authenticate(password)
    if (!isAuthenticated) return done(null, false)
    done(null, user)
  } catch (err) {
    done(err)
  }
})

/**
 * BasicStrategy & ClientPasswordStrategy
 *
 * These strategies are used to authenticate registered OAuth clients.  They are
 * employed to protect the `token` endpoint, which consumers use to obtain
 * access tokens.  The OAuth 2.0 specification suggests that clients use the
 * HTTP Basic scheme to authenticate.  Use of the client password strategy
 * allows clients to send the same credentials in the request body (as opposed
 * to the `Authorization` header).  While this approach is not recommended by
 * the specification, in practice it is quite common.
 */
const basic = new BasicStrategy(async (username, password, done) => {
  try {
    const client = await OAuthClient.findById(username)
    if (!client) return done(null, false)
    if (client.secret !== password) return done(null, false)
    done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * Client Password strategy
 *
 * The OAuth 2.0 client password authentication strategy authenticates clients
 * using a client ID and client secret. The strategy requires a verify callback,
 * which accepts those credentials and calls done providing a client.
 */

const oauth2ClientPassword = new ClientPasswordStrategy(async (clientId, clientSecret, done) => {
  try {
    const client = await OAuthClient.findById(clientId)
    if (!client) return done(null, false)
    if (client.secret !== clientSecret) return done(null, false)
    return done(null, client)
  } catch (err) {
    done(err)
  }
})

/**
 * BearerStrategy
 *
 * This strategy is used to authenticate either users or clients based on an access token
 * (aka a bearer token).  If a user, they must have previously authorized a client
 * application, which is issued an access token to make requests on behalf of
 * the authorizing user.
 *
 * To keep this example simple, restricted scopes are not implemented, and this is just for
 * illustrative purposes
 */
const bearer = new BearerStrategy(async (accessToken, done) => {
  try {
    const token = await OAuthToken.getByAccessToken(accessToken)
    if (!token) return done(null, false)

    if (!token.isValid()) {
      await token.remove()
      return done(null, false)
    }

    const client = await OAuthClient.findById(token.client)
    // if (client.trusted) return done(null, client, token)

    if (token.user !== null) {
      const user = await OAuthUser.findById(token.user)
      if (!user) return done(null, false)
      return done(null, user.toJSON(), token)
    }

    done(null, client.toJSON(), token)
  } catch (err) {
    done(err)
  }
})

// Register serialialization and deserialization functions.
//
// When a client redirects a user to user authorization endpoint, an
// authorization transaction is initiated.  To complete the transaction, the
// user must authenticate and approve the authorization request.  Because this
// may involve multiple HTTPS request/response exchanges, the transaction is
// stored in the session.
//
// An application must supply serialization functions, which determine how the
// client object is serialized into the session.  Typically this will be a
// simple matter of serializing the client's ID, and deserializing by finding
// the client by ID from the database.

const serializeUser = (user, done) => done(null, user)
const deserializeUser = (user, done) => done(null, user)

export default function setupPassport () {
  passport.use(local)
  passport.use(basic)
  passport.use(oauth2ClientPassword)
  passport.use(bearer)
  passport.serializeUser(serializeUser)
  passport.deserializeUser(deserializeUser)
}
<|endoftext|>


<commit_before>var fs = require('fs')
var path = require('path')

var async = require('async')
var DSStore = require('ds-store')
var sizeOf = require('image-size')
var validator = require('is-my-json-valid')

var util = require('./util')
var hdiutil = require('./hdiutil')
var Pipeline = require('./pipeline')
var schema = require('../schema')

var validateSpec = validator(schema)

function hasKeys (obj, props) {
  function hasKey (key) { return obj.hasOwnProperty(key) }

  return (props.filter(hasKey).length === props.length)
}

function parseOptions (options) {
  if (typeof options !== 'object') {
    throw new Error('`options` must be an object')
  }

  if (hasKeys(options, ['target']) === false) {
    throw new Error('Missing option `target`')
  }

  var parsed = {}
  var hasSource = hasKeys(options, ['source'])
  var hasSpec = hasKeys(options, ['basepath', 'specification'])

  if (hasSource === hasSpec) {
    throw new Error('Supply one of `source` or `(basepath, specification)`')
  }

  if (hasSource) {
    parsed.hasSpec = false
    parsed.source = options.source
    parsed.target = options.target
    parsed.resolveBase = path.dirname(options.source)
  }

  if (hasSpec) {
    parsed.hasSpec = true
    parsed.target = options.target
    parsed.opts = options.specification
    parsed.resolveBase = options.basepath
  }

  return parsed
}

module.exports = exports = function (options) {
  if (process.platform !== 'darwin') {
    throw new Error('Platform not supported: ' + process.platform)
  }

  var global = parseOptions(options)
  var resolvePath = function (to) {
    return path.resolve(global.resolveBase, to)
  }

  var pipeline = new Pipeline()

  /**
   **
   **/

  pipeline.addStep('Looking for target', function (next) {
    fs.exists(global.target, function (exists) {
      if (exists) {
        next(new Error('Target already exists'))
      } else {
        next(null)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Reading JSON Specification', function (next) {
    if (global.hasSpec) return next.skip()

    fs.readFile(global.source, function (err, buffer) {
      if (err && err.code === 'ENOENT' && err.path) {
        next(new Error('JSON Specification not found at: ' + err.path))
      } else {
        global.specbuffer = buffer
        next(err)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Parsing JSON Specification', function (next) {
    if (global.hasSpec) return next.skip()

    try {
      var obj = JSON.parse(global.specbuffer.toString())

      if (obj.icons) {
        var legacy = require('./legacy')
        global.opts = legacy.convert(obj)
      } else {
        global.opts = obj
      }

      next(null)
    } catch (err) {
      next(err)
    }
  })

  /**
   **
   **/

  pipeline.addStep('Validating JSON Specification', function (next) {
    if (validateSpec(global.opts)) return next(null)

    function formatError (error) {
      return error.field + ' ' + error.message
    }

    var message = validateSpec.errors.map(formatError).join(', ')

    next(new Error(message))
  })

  /**
   **
   **/

  pipeline.addStep('Looking for files', function (next) {
    function find (type) {
      return global.opts.contents.filter(function (e) {
        return (e.type === type)
      })
    }

    global.links = find('link')
    global.files = find('file')

    async.each(global.files, function (file, cb) {
      var path = resolvePath(file.path)

      fs.exists(path, function (exists) {
        if (exists) {
          cb(null)
        } else {
          cb(new Error('"' + file.path + '" not found at: ' + path))
        }
      })
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Calculating size of image', function (next) {
    var dusm = util.dusm.bind(util)
    var paths = global.files.map(function (e) { return resolvePath(e.path) })

    async.map(paths, dusm, function (err, sizes) {
      if (err) return next(err)

      var megabytes = sizes.reduce(function (p, c) {
        return p + c
      }, 0)

      // FIXME: I think that this has something to do
      // with blocksize and minimum file size...
      // This should work for now but requires more
      // space than it should. Note that this does
      // not effect the final image.
      megabytes = megabytes * 1.5

      global.megabytes = (megabytes + 32)
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Creating temporary image', function (next) {
    hdiutil.create(global.opts.title, global.megabytes + 'm', function (err, temporaryImagePath) {
      if (err) return next(err)

      pipeline.addCleanupStep('unlink-temporary-image', 'Removing temporary image', function (next) {
        fs.unlink(temporaryImagePath, next)
      })

      global.temporaryImagePath = temporaryImagePath
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Mounting temporary image', function (next) {
    hdiutil.attach(global.temporaryImagePath, function (err, temporaryMountPath) {
      if (err) return next(err)

      pipeline.addCleanupStep('unmount-temporary-image', 'Unmounting temporary image', function (next) {
        hdiutil.detach(temporaryMountPath, next)
      })

      global.temporaryMountPath = temporaryMountPath
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Making hidden background folder', function (next) {
    global.bkgdir = path.join(global.temporaryMountPath, '.background')
    fs.mkdir(global.bkgdir, next)
  })

  /**
   **
   **/

  pipeline.addStep('Copying background', function (next) {
    var absolutePath = resolvePath(global.opts.background)
    var retinaPath = absolutePath.replace(/\.([a-z]+)$/, '@2x.$1')

    var copyRetinaBackground = function (next) {
      var originalExt = path.extname(global.opts.background)
      var outputName = path.basename(global.opts.background, originalExt) + '.tiff'
      var finalPath = path.join(global.bkgdir, outputName)
      global.bkgname = path.join('.background', outputName)
      util.tiffutil(absolutePath, retinaPath, finalPath, next)
    }

    var copyPlainBackground = function (next) {
      var finalPath = path.join(global.bkgdir, path.basename(global.opts.background))
      global.bkgname = path.join('.background', path.basename(global.opts.background))
      util.cp(absolutePath, finalPath, next)
    }

    fs.exists(retinaPath, function (exists) {
      if (exists) {
        copyRetinaBackground(next)
      } else {
        copyPlainBackground(next)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Reading background dimensions', function (next) {
    sizeOf(resolvePath(global.opts.background), function (err, value) {
      if (err) return next(err)

      global.bkgsize = [value.width, value.height]
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Copying icon', function (next) {
    if (global.opts.icon) {
      var finalPath = path.join(global.temporaryMountPath, '.VolumeIcon.icns')
      util.cp(resolvePath(global.opts.icon), finalPath, next)
    } else {
      next.skip()
    }
  })

  /**
   **
   **/

  pipeline.addStep('Setting icon', function (next) {
    if (global.opts.icon) {
      util.seticonflag(global.temporaryMountPath, next)
    } else {
      next.skip()
    }
  })

  /**
   **
   **/

  pipeline.addStep('Creating links', function (next) {
    if (global.links.length === 0) {
      return next.skip()
    }

    async.each(global.links, function (entry, cb) {
      var title = path.basename(entry.path)
      var finalPath = path.join(global.temporaryMountPath, title)

      fs.symlink(entry.path, finalPath, cb)
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Copying files', function (next) {
    if (global.files.length === 0) {
      return next.skip()
    }

    async.each(global.files, function (entry, cb) {
      var title = path.basename(entry.path)
      var finalPath = path.join(global.temporaryMountPath, title)

      util.sh('cp', ['-R', resolvePath(entry.path), finalPath], cb)
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Making all the visuals', function (next) {
    var ds = new DSStore()

    ds.vSrn(1)
    ds.setIconSize(global.opts['icon-size'])
    ds.setBackground(path.join(global.temporaryMountPath, global.bkgname))
    ds.setWindowSize(global.bkgsize[0], global.bkgsize[1])

    global.opts.contents.forEach(function (e) {
      ds.setIconPos(path.basename(e.path), e.x, e.y)
    })

    ds.write(path.join(global.temporaryMountPath, '.DS_Store'), function (err) {
      next(err)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Blessing image', function (next) {
    var args = []
    args.push('--folder', global.temporaryMountPath)
    args.push('--openfolder', global.temporaryMountPath)

    util.sh('bless', args, next)
  })

  /**
   **
   **/

  pipeline.addStep('Unmounting temporary image', function (next) {
    pipeline.runCleanup('unmount-temporary-image', next)
  })

  /**
   **
   **/

  pipeline.addStep('Finalizing image', function (next) {
    var format = global.opts.compression || 'UDZO'

    hdiutil.convert(global.temporaryImagePath, format, global.target, next)
  })

  /**
   **
   **/

  pipeline.expectAdditional(1)

  return pipeline.run()
}
<commit_msg>Fix format option<commit_after>var fs = require('fs')
var path = require('path')

var async = require('async')
var DSStore = require('ds-store')
var sizeOf = require('image-size')
var validator = require('is-my-json-valid')

var util = require('./util')
var hdiutil = require('./hdiutil')
var Pipeline = require('./pipeline')
var schema = require('../schema')

var validateSpec = validator(schema)

function hasKeys (obj, props) {
  function hasKey (key) { return obj.hasOwnProperty(key) }

  return (props.filter(hasKey).length === props.length)
}

function parseOptions (options) {
  if (typeof options !== 'object') {
    throw new Error('`options` must be an object')
  }

  if (hasKeys(options, ['target']) === false) {
    throw new Error('Missing option `target`')
  }

  var parsed = {}
  var hasSource = hasKeys(options, ['source'])
  var hasSpec = hasKeys(options, ['basepath', 'specification'])

  if (hasSource === hasSpec) {
    throw new Error('Supply one of `source` or `(basepath, specification)`')
  }

  if (hasSource) {
    parsed.hasSpec = false
    parsed.source = options.source
    parsed.target = options.target
    parsed.resolveBase = path.dirname(options.source)
  }

  if (hasSpec) {
    parsed.hasSpec = true
    parsed.target = options.target
    parsed.opts = options.specification
    parsed.resolveBase = options.basepath
  }

  return parsed
}

module.exports = exports = function (options) {
  if (process.platform !== 'darwin') {
    throw new Error('Platform not supported: ' + process.platform)
  }

  var global = parseOptions(options)
  var resolvePath = function (to) {
    return path.resolve(global.resolveBase, to)
  }

  var pipeline = new Pipeline()

  /**
   **
   **/

  pipeline.addStep('Looking for target', function (next) {
    fs.exists(global.target, function (exists) {
      if (exists) {
        next(new Error('Target already exists'))
      } else {
        next(null)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Reading JSON Specification', function (next) {
    if (global.hasSpec) return next.skip()

    fs.readFile(global.source, function (err, buffer) {
      if (err && err.code === 'ENOENT' && err.path) {
        next(new Error('JSON Specification not found at: ' + err.path))
      } else {
        global.specbuffer = buffer
        next(err)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Parsing JSON Specification', function (next) {
    if (global.hasSpec) return next.skip()

    try {
      var obj = JSON.parse(global.specbuffer.toString())

      if (obj.icons) {
        var legacy = require('./legacy')
        global.opts = legacy.convert(obj)
      } else {
        global.opts = obj
      }

      next(null)
    } catch (err) {
      next(err)
    }
  })

  /**
   **
   **/

  pipeline.addStep('Validating JSON Specification', function (next) {
    if (validateSpec(global.opts)) return next(null)

    function formatError (error) {
      return error.field + ' ' + error.message
    }

    var message = validateSpec.errors.map(formatError).join(', ')

    next(new Error(message))
  })

  /**
   **
   **/

  pipeline.addStep('Looking for files', function (next) {
    function find (type) {
      return global.opts.contents.filter(function (e) {
        return (e.type === type)
      })
    }

    global.links = find('link')
    global.files = find('file')

    async.each(global.files, function (file, cb) {
      var path = resolvePath(file.path)

      fs.exists(path, function (exists) {
        if (exists) {
          cb(null)
        } else {
          cb(new Error('"' + file.path + '" not found at: ' + path))
        }
      })
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Calculating size of image', function (next) {
    var dusm = util.dusm.bind(util)
    var paths = global.files.map(function (e) { return resolvePath(e.path) })

    async.map(paths, dusm, function (err, sizes) {
      if (err) return next(err)

      var megabytes = sizes.reduce(function (p, c) {
        return p + c
      }, 0)

      // FIXME: I think that this has something to do
      // with blocksize and minimum file size...
      // This should work for now but requires more
      // space than it should. Note that this does
      // not effect the final image.
      megabytes = megabytes * 1.5

      global.megabytes = (megabytes + 32)
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Creating temporary image', function (next) {
    hdiutil.create(global.opts.title, global.megabytes + 'm', function (err, temporaryImagePath) {
      if (err) return next(err)

      pipeline.addCleanupStep('unlink-temporary-image', 'Removing temporary image', function (next) {
        fs.unlink(temporaryImagePath, next)
      })

      global.temporaryImagePath = temporaryImagePath
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Mounting temporary image', function (next) {
    hdiutil.attach(global.temporaryImagePath, function (err, temporaryMountPath) {
      if (err) return next(err)

      pipeline.addCleanupStep('unmount-temporary-image', 'Unmounting temporary image', function (next) {
        hdiutil.detach(temporaryMountPath, next)
      })

      global.temporaryMountPath = temporaryMountPath
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Making hidden background folder', function (next) {
    global.bkgdir = path.join(global.temporaryMountPath, '.background')
    fs.mkdir(global.bkgdir, next)
  })

  /**
   **
   **/

  pipeline.addStep('Copying background', function (next) {
    var absolutePath = resolvePath(global.opts.background)
    var retinaPath = absolutePath.replace(/\.([a-z]+)$/, '@2x.$1')

    var copyRetinaBackground = function (next) {
      var originalExt = path.extname(global.opts.background)
      var outputName = path.basename(global.opts.background, originalExt) + '.tiff'
      var finalPath = path.join(global.bkgdir, outputName)
      global.bkgname = path.join('.background', outputName)
      util.tiffutil(absolutePath, retinaPath, finalPath, next)
    }

    var copyPlainBackground = function (next) {
      var finalPath = path.join(global.bkgdir, path.basename(global.opts.background))
      global.bkgname = path.join('.background', path.basename(global.opts.background))
      util.cp(absolutePath, finalPath, next)
    }

    fs.exists(retinaPath, function (exists) {
      if (exists) {
        copyRetinaBackground(next)
      } else {
        copyPlainBackground(next)
      }
    })
  })

  /**
   **
   **/

  pipeline.addStep('Reading background dimensions', function (next) {
    sizeOf(resolvePath(global.opts.background), function (err, value) {
      if (err) return next(err)

      global.bkgsize = [value.width, value.height]
      next(null)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Copying icon', function (next) {
    if (global.opts.icon) {
      var finalPath = path.join(global.temporaryMountPath, '.VolumeIcon.icns')
      util.cp(resolvePath(global.opts.icon), finalPath, next)
    } else {
      next.skip()
    }
  })

  /**
   **
   **/

  pipeline.addStep('Setting icon', function (next) {
    if (global.opts.icon) {
      util.seticonflag(global.temporaryMountPath, next)
    } else {
      next.skip()
    }
  })

  /**
   **
   **/

  pipeline.addStep('Creating links', function (next) {
    if (global.links.length === 0) {
      return next.skip()
    }

    async.each(global.links, function (entry, cb) {
      var title = path.basename(entry.path)
      var finalPath = path.join(global.temporaryMountPath, title)

      fs.symlink(entry.path, finalPath, cb)
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Copying files', function (next) {
    if (global.files.length === 0) {
      return next.skip()
    }

    async.each(global.files, function (entry, cb) {
      var title = path.basename(entry.path)
      var finalPath = path.join(global.temporaryMountPath, title)

      util.sh('cp', ['-R', resolvePath(entry.path), finalPath], cb)
    }, next)
  })

  /**
   **
   **/

  pipeline.addStep('Making all the visuals', function (next) {
    var ds = new DSStore()

    ds.vSrn(1)
    ds.setIconSize(global.opts['icon-size'])
    ds.setBackground(path.join(global.temporaryMountPath, global.bkgname))
    ds.setWindowSize(global.bkgsize[0], global.bkgsize[1])

    global.opts.contents.forEach(function (e) {
      ds.setIconPos(path.basename(e.path), e.x, e.y)
    })

    ds.write(path.join(global.temporaryMountPath, '.DS_Store'), function (err) {
      next(err)
    })
  })

  /**
   **
   **/

  pipeline.addStep('Blessing image', function (next) {
    var args = []
    args.push('--folder', global.temporaryMountPath)
    args.push('--openfolder', global.temporaryMountPath)

    util.sh('bless', args, next)
  })

  /**
   **
   **/

  pipeline.addStep('Unmounting temporary image', function (next) {
    pipeline.runCleanup('unmount-temporary-image', next)
  })

  /**
   **
   **/

  pipeline.addStep('Finalizing image', function (next) {
    var format = global.opts.format || 'UDZO'

    hdiutil.convert(global.temporaryImagePath, format, global.target, next)
  })

  /**
   **
   **/

  pipeline.expectAdditional(1)

  return pipeline.run()
}
<|endoftext|>


<commit_before>var curry = require('./curry'),
	map = require('./map'),
	each = require('./each'),
	json = require('./json')

module.exports = {
	request: request,
	get: curry(request, 'get'),
	post: curry(request, 'post'),
	jsonGet: curry(sendJSON, 'get'),
	jsonPost: curry(sendJSON, 'post')
}

var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); }

function request(method, url, params, callback, headers, opts) {
	var xhr = new XHR()
	method = method.toUpperCase()
	headers = headers || {}
	opts = opts || {}
	xhr.onreadystatechange = function() {
		var err, result
		try {
			if (xhr.readyState != 4) { return }
			if (xhr.status != 200) { return callback(new Error(xhr.status)) }
			result = (opts.json ? json.parse(xhr.responseText) : xhr.responseText)
			if (xhr.getResponseHeader('Content-Type') == 'application/json') { result = json.parse(result) }
		} catch(e) {
			err = e
		}
		if (err || typeof result != undefined) {
			_abortXHR(xhr)
			callback(err, result)
		}
	}
	var data = null,
		encode = (opts.encode !== false),
		queryArr = map(params, function(value, key) {
			return (encode ? encodeURIComponent(key) : key) + '=' + (encode ? encodeURIComponent(json.stringify(value)) : value) })
	if (method == 'GET') {
		if (url.indexOf('?') == -1) { url = url + '?' }
		url += queryArr.join('&')
	} else if (method == 'POST') {
		data = queryArr.join('&')
	}
	xhr.open(method, url, true)
	if (method == 'POST') {
    if (!headers['Content-Type']) { headers['Content-Type'] = "application/x-www-form-urlencoded" }
		if (!headers['Content-length']) { headers['Content-length'] = data.length }
		if (!headers['Connection']) { headers['Connection'] = 'close' }
    each(headers, function(val, key) { xhr.setRequestHeader(key, val) })
	}
	xhr.send(data)
}

function sendJSON(method, url, params, callback) {
	return request(method, url, params, callback, { 'Content-Type':'application/json' }, { json:true })
}

function _abortXHR(xhr) {
	try {
		if('onload' in xhr) {
			xhr.onload = xhr.onerror = xhr.ontimeout = null;
		} else if('onreadystatechange' in xhr) {
			xhr.onreadystatechange = null;
		}
		if(xhr.abort) { xhr.abort(); }
	} catch(e) {}
}
<commit_msg>Fix POST data encoding - just json stringify the content<commit_after>var curry = require('./curry'),
	map = require('./map'),
	each = require('./each'),
	json = require('./json')

module.exports = {
	request: request,
	get: curry(request, 'get'),
	post: curry(request, 'post'),
	jsonGet: curry(sendJSON, 'get'),
	jsonPost: curry(sendJSON, 'post')
}

var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); }

function request(method, url, params, callback, headers, opts) {
	var xhr = new XHR()
	method = method.toUpperCase()
	headers = headers || {}
	opts = opts || {}
	xhr.onreadystatechange = function() {
		var err, result
		try {
			if (xhr.readyState != 4) { return }
			if (xhr.status != 200) { return callback(new Error(xhr.status)) }
			result = (opts.json ? json.parse(xhr.responseText) : xhr.responseText)
			if (xhr.getResponseHeader('Content-Type') == 'application/json') { result = json.parse(result) }
		} catch(e) {
			err = e
		}
		if (err || typeof result != undefined) {
			_abortXHR(xhr)
			callback(err, result)
		}
	}

	var data = null

	if (method == 'GET') {
		var encode = (opts.encode !== false),
		queryArr = map(params, function(value, key) { return (encode ? encodeURIComponent(key) : key) + '=' + (encode ? encodeURIComponent(value) : value) })
			url += (url.indexOf('?') == -1 && queryArr.length ? '?' : '') + queryArr.join('&')
	} else if (method == 'POST') {
		data = json.stringify(params)
	}
	xhr.open(method, url, true)
	if (method == 'POST') {
		if (!headers['Content-Type']) { headers['Content-Type'] = "application/x-www-form-urlencoded" }
		if (!headers['Content-length']) { headers['Content-length'] = data.length }
		if (!headers['Connection']) { headers['Connection'] = 'close' }
		each(headers, function(val, key) { xhr.setRequestHeader(key, val) })
	}
	xhr.send(data)
}

function sendJSON(method, url, params, callback) {
	return request(method, url, params, callback, { 'Content-Type':'application/json' }, { json:true })
}

function _abortXHR(xhr) {
	try {
		if('onload' in xhr) {
			xhr.onload = xhr.onerror = xhr.ontimeout = null;
		} else if('onreadystatechange' in xhr) {
			xhr.onreadystatechange = null;
		}
		if(xhr.abort) { xhr.abort(); }
	} catch(e) {}
}
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import Snakeskin from '../core';

// The base directive separators
// >>>

export const
	LEFT_BOUND = '{',
	RIGHT_BOUND = '}',
	ADV_LEFT_BOUND = '#';

// <<<
// The additional directive separators
// >>>

export const
	I18N = '`';

export const
	JS_DOC = '/**',
	SINGLE_COMMENT = '///',
	MULT_COMMENT_START = '/*',
	MULT_COMMENT_END = '*/';

export const COMMENTS = {
	[SINGLE_COMMENT]: SINGLE_COMMENT,
	[MULT_COMMENT_START]: MULT_COMMENT_START,
	[MULT_COMMENT_END]: MULT_COMMENT_END
};

export const
	MICRO_TEMPLATE = '${';

export const BASE_SHORTS = {
	'-': true,
	[ADV_LEFT_BOUND]: true
};

export const
	SHORTS = {};

Snakeskin.forEach(BASE_SHORTS, (el, key) =>
	SHORTS[key] = true);

// <<<
// The context modifiers
// >>>

export const
	G_MOD = '@';

// <<<
// Jade-Like
// >>>

export const
	CONCAT = '&',
	CONCAT_END = '.',
	IGNORE = '|',
	INLINE = ' :: ';

// <<<
// The filter modifiers
// >>>

export const
	FILTER = '|';

// <<<
// Escaping
// >>>

export const BASE_SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[LEFT_BOUND]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

export const SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[LEFT_BOUND]: true,
	[ADV_LEFT_BOUND]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true,
	[CONCAT]: true,
	[CONCAT_END]: true,
	[IGNORE]: true,
	[INLINE.trim().charAt(0)]: true
};

Snakeskin.forEach(BASE_SHORTS, (el, key) =>
	SYS_ESCAPES[key.charAt(0)] = true);

export const STRONG_SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

export const MICRO_TEMPLATE_ESCAPES = {
	'\\': true,
	[MICRO_TEMPLATE.charAt(0)]: true
};

export const ESCAPES = {
	'"': true,
	'\'': true,
	'/': true
};

export const ESCAPES_END = {
	'-': true,
	'+': true,
	'*': true,
	'%': true,
	'~': true,
	'>': true,
	'<': true,
	'^': true,
	',': true,
	';': true,
	'=': true,
	'|': true,
	'&': true,
	'!': true,
	'?': true,
	':': true,
	'(': true,
	'{': true,
	'[': true
};

export const ESCAPES_END_WORD = {
	'typeof': true,
	'void': true,
	'instanceof': true,
	'delete': true,
	'in': true,
	'new': true
};

export const B_OPEN = {
	'(': true,
	'[': true,
	'{': true
};

export const B_CLOSE = {
	')': true,
	']': true,
	'}': true
};

export const P_OPEN = {
	'(': true,
	'[': true
};

export const P_CLOSE = {
	')': true,
	']': true
};

// <<<
// The reserved names
// >>>

export const SYS_CONSTS = {
	'__REQUIRE__': true,
	'__RESULT__': true,
	'__STRING_RESULT__': true,
	'__CDATA__': true,
	'__RETURN__': true,
	'__RETURN_VAL__': true,
	'__LENGTH__': true,
	'__ESCAPE_D_Q__': true,
	'__ATTR_STR__': true,
	'__ATTR_CONCAT_MAP__': true,
	'__ATTR_CACHE__': true,
	'__ATTR_TYPE__': true,
	'__TARGET_REF__': true,
	'__CALL_POS__': true,
	'__CALL_TMP__': true,
	'__CALL_CACHE__': true,
	'__FILTERS__': true,
	'__VARS__': true,
	'__LOCAL__': true,
	'__THIS__': true,
	'__INCLUDE__': true,
	'__INLINE_TAG__': true,
	'__INLINE_TAGS__': true,
	'__TAG__': true,
	'__NODE__': true,
	'__JOIN__': true,
	'__GET_XML_ATTR_KEY_DECL__': true,
	'__APPEND_XML_ATTR_VAL__': true,
	'__GET_XML_ATTRS_DECL_START__': true,
	'__GET_XML_TAG_DECL_END__': true,
	'__GET_END_XML_TAG_DECL__': true,
	'__TARGET_END__': true,
	'__PUTIN_CALL__': true,
	'__PUTIN_TARGET__': true,
	'__SNAKESKIN_MODULES__': true,
	'__SNAKESKIN_MODULES_DECL__': true,
	'GLOBAL': true,
	'TRUE': true,
	'FALSE': true,
	'module': true,
	'exports': true,
	'require': true,
	'__dirname': true,
	'__filename': true,
	'TPL_NAME': true,
	'PARENT_TPL_NAME': true,
	'Raw': true,
	'Unsafe': true,
	'Snakeskin': true,
	'getTplResult': true,
	'clearTplResult': true,
	'arguments': true,
	'self': true,
	'callee': true,
	'$_': true,
	'$0': true,
	'$class': true
};
<commit_msg>Added new words for escaping<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import Snakeskin from '../core';

// The base directive separators
// >>>

export const
	LEFT_BOUND = '{',
	RIGHT_BOUND = '}',
	ADV_LEFT_BOUND = '#';

// <<<
// The additional directive separators
// >>>

export const
	I18N = '`';

export const
	JS_DOC = '/**',
	SINGLE_COMMENT = '///',
	MULT_COMMENT_START = '/*',
	MULT_COMMENT_END = '*/';

export const COMMENTS = {
	[SINGLE_COMMENT]: SINGLE_COMMENT,
	[MULT_COMMENT_START]: MULT_COMMENT_START,
	[MULT_COMMENT_END]: MULT_COMMENT_END
};

export const
	MICRO_TEMPLATE = '${';

export const BASE_SHORTS = {
	'-': true,
	[ADV_LEFT_BOUND]: true
};

export const
	SHORTS = {};

Snakeskin.forEach(BASE_SHORTS, (el, key) =>
	SHORTS[key] = true);

// <<<
// The context modifiers
// >>>

export const
	G_MOD = '@';

// <<<
// Jade-Like
// >>>

export const
	CONCAT = '&',
	CONCAT_END = '.',
	IGNORE = '|',
	INLINE = ' :: ';

// <<<
// The filter modifiers
// >>>

export const
	FILTER = '|';

// <<<
// Escaping
// >>>

export const BASE_SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[LEFT_BOUND]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

export const SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[LEFT_BOUND]: true,
	[ADV_LEFT_BOUND]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true,
	[CONCAT]: true,
	[CONCAT_END]: true,
	[IGNORE]: true,
	[INLINE.trim().charAt(0)]: true
};

Snakeskin.forEach(BASE_SHORTS, (el, key) =>
	SYS_ESCAPES[key.charAt(0)] = true);

export const STRONG_SYS_ESCAPES = {
	'\\': true,
	[I18N]: true,
	[SINGLE_COMMENT.charAt(0)]: true,
	[MULT_COMMENT_START.charAt(0)]: true
};

export const MICRO_TEMPLATE_ESCAPES = {
	'\\': true,
	[MICRO_TEMPLATE.charAt(0)]: true
};

export const ESCAPES = {
	'"': true,
	'\'': true,
	'/': true
};

export const ESCAPES_END = {
	'-': true,
	'+': true,
	'*': true,
	'%': true,
	'~': true,
	'>': true,
	'<': true,
	'^': true,
	',': true,
	';': true,
	'=': true,
	'|': true,
	'&': true,
	'!': true,
	'?': true,
	':': true,
	'(': true,
	'{': true,
	'[': true
};

export const ESCAPES_END_WORD = {
	'return': true,
	'yield': true,
	'await': true,
	'typeof': true,
	'void': true,
	'instanceof': true,
	'delete': true,
	'in': true,
	'new': true
};

export const B_OPEN = {
	'(': true,
	'[': true,
	'{': true
};

export const B_CLOSE = {
	')': true,
	']': true,
	'}': true
};

export const P_OPEN = {
	'(': true,
	'[': true
};

export const P_CLOSE = {
	')': true,
	']': true
};

// <<<
// The reserved names
// >>>

export const SYS_CONSTS = {
	'__REQUIRE__': true,
	'__RESULT__': true,
	'__STRING_RESULT__': true,
	'__CDATA__': true,
	'__RETURN__': true,
	'__RETURN_VAL__': true,
	'__LENGTH__': true,
	'__ESCAPE_D_Q__': true,
	'__ATTR_STR__': true,
	'__ATTR_CONCAT_MAP__': true,
	'__ATTR_CACHE__': true,
	'__ATTR_TYPE__': true,
	'__TARGET_REF__': true,
	'__CALL_POS__': true,
	'__CALL_TMP__': true,
	'__CALL_CACHE__': true,
	'__FILTERS__': true,
	'__VARS__': true,
	'__LOCAL__': true,
	'__THIS__': true,
	'__INCLUDE__': true,
	'__INLINE_TAG__': true,
	'__INLINE_TAGS__': true,
	'__TAG__': true,
	'__NODE__': true,
	'__JOIN__': true,
	'__GET_XML_ATTR_KEY_DECL__': true,
	'__APPEND_XML_ATTR_VAL__': true,
	'__GET_XML_ATTRS_DECL_START__': true,
	'__GET_XML_TAG_DECL_END__': true,
	'__GET_END_XML_TAG_DECL__': true,
	'__TARGET_END__': true,
	'__PUTIN_CALL__': true,
	'__PUTIN_TARGET__': true,
	'__SNAKESKIN_MODULES__': true,
	'__SNAKESKIN_MODULES_DECL__': true,
	'GLOBAL': true,
	'TRUE': true,
	'FALSE': true,
	'module': true,
	'exports': true,
	'require': true,
	'__dirname': true,
	'__filename': true,
	'TPL_NAME': true,
	'PARENT_TPL_NAME': true,
	'Raw': true,
	'Unsafe': true,
	'Snakeskin': true,
	'getTplResult': true,
	'clearTplResult': true,
	'arguments': true,
	'self': true,
	'callee': true,
	'$_': true,
	'$0': true,
	'$class': true
};
<|endoftext|>


<commit_before>var util = require("./util");

module.exports = {
  "default": normal,
  "normal": normal,
  "vee": vee
};

function normal(parent, id, edge, type) {
  var marker = parent.append("marker")
    .attr("id", id)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 9)
    .attr("refY", 5)
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", 8)
    .attr("markerHeight", 6)
    .attr("orient", "auto");

  var path = marker.append("path")
    .attr("d", "M 0 0 L 10 5 L 0 10 z")
    .style("stroke-width", 1)
    .style("stroke-dasharray", "1,0");
  util.applyStyle(path, edge[type + "Style"]);
}

function vee(parent, id, edge, type) {
  var marker = parent.append("marker")
    .attr("id", id)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 9)
    .attr("refY", 5)
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", 8)
    .attr("markerHeight", 6)
    .attr("orient", "auto");

  var path = marker.append("path")
    .attr("d", "M 0 0 L 10 5 L 0 10 L 4 5 z")
    .style("stroke-width", 1)
    .style("stroke-dasharray", "1,0");
  util.applyStyle(path, edge[type + "Style"]);
}
<commit_msg>Drawing undirected graphs<commit_after>var util = require("./util");

module.exports = {
  "default": normal,
  "normal": normal,
  "vee": vee,
  "undirected": undirected
};

function normal(parent, id, edge, type) {
  var marker = parent.append("marker")
    .attr("id", id)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 9)
    .attr("refY", 5)
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", 8)
    .attr("markerHeight", 6)
    .attr("orient", "auto");

  var path = marker.append("path")
    .attr("d", "M 0 0 L 10 5 L 0 10 z")
    .style("stroke-width", 1)
    .style("stroke-dasharray", "1,0");
  util.applyStyle(path, edge[type + "Style"]);
}

function vee(parent, id, edge, type) {
  var marker = parent.append("marker")
    .attr("id", id)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 9)
    .attr("refY", 5)
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", 8)
    .attr("markerHeight", 6)
    .attr("orient", "auto");

  var path = marker.append("path")
    .attr("d", "M 0 0 L 10 5 L 0 10 L 4 5 z")
    .style("stroke-width", 1)
    .style("stroke-dasharray", "1,0");
  util.applyStyle(path, edge[type + "Style"]);
}

function undirected(parent, id, edge, type) {
  var marker = parent.append("marker")
    .attr("id", id)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 9)
    .attr("refY", 5)
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", 8)
    .attr("markerHeight", 6)
    .attr("orient", "auto");

  var path = marker.append("path")
    .attr("d", "M 0 5 L 10 5")
    .style("stroke-width", 1)
    .style("stroke-dasharray", "1,0");
  util.applyStyle(path, edge[type + "Style"]);
}
<|endoftext|>


<commit_before>(function( w, $ ){
  var Dialog = w.componentNamespace.Dialog, doc = document;

	$.fn.dialog = function(){
		return this.each(function(){
			var $el = $( this ), dialog = new Dialog( this );

			$el.data( "instance", dialog );

			$el.addClass( Dialog.classes.content )
				.attr( "role", "dialog" )
				.attr( "tabindex", 0 )
				.bind( Dialog.events.open, function(){
					dialog.open();
				})
				.bind( Dialog.events.close, function(){
					dialog.close();
				})
				.bind( "click", function( e ){
					if( $( e.target ).is( "." + Dialog.classes.close ) ){
						w.history.back();
						e.preventDefault();
					}
				});

			dialog.$background.bind( "click", function() {
				w.history.back();
			});

			// close on hashchange if open (supports back button closure)
			$( w ).bind( "hashchange", function(){
				var hash = w.location.hash.replace( "#", "" );

				if( hash !== dialog.hash ){
					dialog.close();
				}
			});

			// open on matching a[href=#id] click
			$( doc ).bind( "click", function( e ){
        			var $matchingDialog, $a;

        			$a = $( e.target ).closest( "a" );

				if( !dialog.isOpen && $a.length && $a.attr( "href" ) ){

					// catch invalid selector exceptions
					try {
						$matchingDialog = $( $a.attr( "href" ) );
					} catch ( error ) {
						// TODO should check the type of exception, it's not clear how well
						//      the error name "SynatxError" is supported
						return;
					}

					if( $matchingDialog.length && $matchingDialog.is( $el ) ){
						$matchingDialog.trigger( Dialog.events.open );
						e.preventDefault();
					}
				}
			});

			// close on escape key
			$( doc ).bind( "keyup", function( e ){
				if( e.which === 27 ){
					dialog.close();
				}
			});
		});
	};

	// auto-init
	$(function(){
		$( ".dialog" ).dialog();
	});
}( this, window.jQuery ));
<commit_msg>fix lint errors<commit_after>(function( w, $ ){
  var Dialog = w.componentNamespace.Dialog, doc = document;

	$.fn.dialog = function(){
		return this.each(function(){
			var $el = $( this ), dialog = new Dialog( this );

			$el.data( "instance", dialog );

			$el.addClass( Dialog.classes.content )
				.attr( "role", "dialog" )
				.attr( "tabindex", 0 )
				.bind( Dialog.events.open, function(){
					dialog.open();
				})
				.bind( Dialog.events.close, function(){
					dialog.close();
				})
				.bind( "click", function( e ){
					if( $( e.target ).is( "." + Dialog.classes.close ) ){
						w.history.back();
						e.preventDefault();
					}
				});

			dialog.$background.bind( "click", function() {
				w.history.back();
			});

			// close on hashchange if open (supports back button closure)
			$( w ).bind( "hashchange", function(){
				var hash = w.location.hash.replace( "#", "" );

				if( hash !== dialog.hash ){
					dialog.close();
				}
			});

			// open on matching a[href=#id] click
			$( doc ).bind( "click", function( e ){
				var $matchingDialog, $a;

				$a = $( e.target ).closest( "a" );

				if( !dialog.isOpen && $a.length && $a.attr( "href" ) ){

					// catch invalid selector exceptions
					try {
						$matchingDialog = $( $a.attr( "href" ) );
					} catch ( error ) {
						// TODO should check the type of exception, it's not clear how well
						//      the error name "SynatxError" is supported
						return;
					}

					if( $matchingDialog.length && $matchingDialog.is( $el ) ){
						$matchingDialog.trigger( Dialog.events.open );
						e.preventDefault();
					}
				}
			});

			// close on escape key
			$( doc ).bind( "keyup", function( e ){
				if( e.which === 27 ){
					dialog.close();
				}
			});
		});
	};

	// auto-init
	$(function(){
		$( ".dialog" ).dialog();
	});
}( this, window.jQuery ));
<|endoftext|>


<commit_before>exports.exec = function(yql, callback, secure){

	var http 	= require("http");
	var secure  = secure ? "https://" : "http://";
	var url		= "https://query.yahooapis.com/v1/public/yql?q=" + encodeURIComponent(yql) + "&format=json";

	var client	= http.createClient(80, "query.yahooapis.com");
	var request	= client.request("GET", url, {"host": "query.yahooapis.com", "User-Agent": "NodeJS HTTP Client"});

	request.addListener('response', function (response) {

		var responseBody = '';

		response.addListener("data", function (chunk) {
			responseBody += chunk;
		});

		response.addListener("end", function () {
			var r = JSON.parse(responseBody);
			if (r.error) {
				callback(r, r.error.description);
			} else {
				callback(r, false);
			}
		});

	});

	request.end();

}
<commit_msg>fixing schema typo.<commit_after>exports.exec = function(yql, callback, secure){

	var http 	= require("http");
	var schema  = secure ? "https://" : "http://";
	var url		= schema + "query.yahooapis.com/v1/public/yql?q=" + encodeURIComponent(yql) + "&format=json";

	var client	= http.createClient(80, "query.yahooapis.com");
	var request	= client.request("GET", url, {"host": "query.yahooapis.com", "User-Agent": "NodeJS HTTP Client"});

	request.addListener('response', function (response) {

		var responseBody = '';

		response.addListener("data", function (chunk) {
			responseBody += chunk;
		});

		response.addListener("end", function () {
			var r = JSON.parse(responseBody);
			if (r.error) {
				callback(r, r.error.description);
			} else {
				callback(r, false);
			}
		});

	});

	request.end();

}
<|endoftext|>


<commit_before>/*eslint no-unused-vars:0, no-console:0 */
import Header from 'twreporter-react-index-page-components/lib/components/header'
import EditorPicks from 'twreporter-react-index-page-components/lib/components/editor-picks'
import Helmet from 'react-helmet'
import InfographicSection from 'twreporter-react-index-page-components/lib/components/infographic-section'
import Latest from 'twreporter-react-index-page-components/lib/components/latest'
import LatestTopic from 'twreporter-react-index-page-components/lib/components/latest-topic'
import React from 'react'
import Reviews from 'twreporter-react-index-page-components/lib/components/reviews'
import CategorySection from 'twreporter-react-index-page-components/lib/components/category-section'
import PhotographySection from 'twreporter-react-index-page-components/lib/components/photography-section'
import ReporterIntro from 'twreporter-react-index-page-components/lib/components/reporter-intro'
import SideBar, { moduleIdObj } from 'twreporter-react-index-page-components/lib/components/side-bar'
import TopicsSection from 'twreporter-react-index-page-components/lib/components/topics-section'
import categoryListID from '../conf/category-list-id'
import categoryString from '../constants/category-strings'
import categoryURI from '../conf/category-uri'
import clone from 'lodash/clone'
import get from 'lodash/get'
import set from 'lodash/set'
import isEqual from 'lodash/isEqual'
import styled from 'styled-components'
import twreporterRedux from 'twreporter-redux'
import { SITE_NAME, SITE_META } from '../constants/index'
import { connect } from 'react-redux'

const { fetchIndexPageContent, fetchCategoriesPostsOnIndexPage } =  twreporterRedux.actions
const { denormalizePosts, denormalizeTopics } = twreporterRedux.utils
const fieldNames = twreporterRedux.reduxStateFields

const _ = {
  clone,
  get,
  set,
  isEqual
}

const Container = styled.div`
  width 100%;
  margin: 0 auto;
  background-color: white;
  overflow: hidden;
`

const FirstModuleWrapper = styled.div`
  hegight: auto;
`

class Homepage extends React.Component {
  static async fetchData({ store }) {
    await fetchIndexPageContent()(store.dispatch, store.getState)
    const error = _.get(store.getState(), [ fieldNames.indexPage, 'error' ])
    if (error !== null) {
      return Promise.reject(error)
    }
  }

  componentWillMount() {
    this.props.fetchIndexPageContent()
  }

  componentDidMount() {
    this.props.fetchCategoriesPostsOnIndexPage()
  }

  render() {
    // TODO Need to change categories
    const microData = (

          <meta itemProp="name" content="首頁" />
          <link itemProp="url" href="https://www.twreporter.org/" />

          <meta itemProp="name" content="台灣" />
          <link itemProp="url" href="https://www.twreporter.org/category/taiwan" />

          <meta itemProp="name" content="文化" />
          <link itemProp="url" href="https://www.twreporter.org/category/culture" />

          <meta itemProp="name" content="國際" />
          <link itemProp="url" href="https://www.twreporter.org/category/intl" />

          <meta itemProp="name" content="影像" />
          <link itemProp="url" href="https://www.twreporter.org/photography" />

          <meta itemProp="name" content="評論" />
          <link itemProp="url" href="https://www.twreporter.org/category/review" />

    )

    const webSiteJSONLD = `
      {
        "@context" : "http://schema.org",
        "@type" : "WebSite",
        "name" : "報導者 The Reporter",
        "url" : "https://www.twreporter.org/",
        "potentialAction" : {
          "@type" : "SearchAction",
          "target" : "https://www.twreporter.org/search?q={search_term}",
          "query-input" : "required name=search_term"
        }
      }
    `

    // TODO Need to change categories
    const breadcrumbListJSONLD = `
    {
        "@context": "http://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [{
          "@type": "ListItem",
          "position": 1,
          "item": {
            "@id": "https://www.twreporter.org/",
            "name": "首頁"
          }
        },{
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@id": "https://www.twreporter.org/category/taiwan",
            "name": "台灣"
          }
        },{
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@id": "https://www.twreporter.org/category/intl",
            "name": "國際"
          }
        },{
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@id": "https://www.twreporter.org/category/culture",
            "name": "文化"
          }
        },{
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@id": "https://www.twreporter.org/category/review",
            "name": "評論"
          }
        }, {
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@id": "https://www.twreporter.org/photography",
            "name": "影像"
          }
        }]
      }
    `
    return (
      <Container>
        <Helmet
          title={SITE_NAME.FULL}
          link={[
            { rel: 'canonical', href: SITE_META.URL }
          ]}
          meta={[
            { name: 'description', content: SITE_META.DESC },
            { name: 'twitter:title', content: SITE_NAME.FULL },
            { name: 'twitter:image', content: SITE_META.LOGO },
            { name: 'twitter:description', content: SITE_META.DESC },
            { property: 'og:title', content: SITE_NAME.FULL },
            { property: 'og:description', content: SITE_META.DESC },
            { property: 'og:image', content: SITE_META.LOGO },
            { property: 'og:type', content: 'website' },
            { property: 'og:url', content: SITE_META.URL }
          ]}
        />
        <SideBar>
          <FirstModuleWrapper
            moduleId={moduleIdObj.editorPick}
          >

            <Latest data={this.props[fieldNames.latest]} />
            <EditorPicks data={this.props[fieldNames.editorPicks]} />
          </FirstModuleWrapper>
          <LatestTopic
            data={this.props[fieldNames.latestTopic]}
            moduleId={moduleIdObj.latestTopic}
          />
          <Reviews
            data={this.props[fieldNames.reviews]}
            moduleId={moduleIdObj.review}
            moreURI={`categories/${categoryURI.reviews}`}
          />
          <CategorySection
            data={this.props.category}
            moduleId={moduleIdObj.category}
          />
          <TopicsSection
            moduleId={moduleIdObj.topic}
            items={this.props[fieldNames.topics]}
          />
          <PhotographySection
            moduleId={moduleIdObj.photography}
            items={this.props[fieldNames.photos]}
            moreURI="photography"
          />
          <InfographicSection
            moduleId={moduleIdObj.infographic}
            items={this.props[fieldNames.infographics]}
            moreURI={`categories/${categoryURI.infographic}`}
          />
          <ReporterIntro
            moduleId={moduleIdObj.donation}
          />
        </SideBar>
        { microData }


<commit_before>module('lib.squeak.vm').requires().toRun(function() {
/*
 * Copyright (c) 2013 Bert Freudenberg
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

Object.subclass('lib.squeak.vm.Image',
'initialization', {
    initialize: function() {
        // object headers
    	this.HeaderTypeMask = 3;
    	this.HeaderTypeSizeAndClass = 0; //3-word header
    	this.HeaderTypeClass = 1;        //2-word header
    	this.HeaderTypeFree = 2;         //free block
	    this.HeaderTypeShort = 3;        //1-word header

        // Indices into SpecialObjects array
        this.splOb_NilObject = 0;
    	this.splOb_FalseObject = 1;
    	this.splOb_TrueObject = 2;
    	this.splOb_SchedulerAssociation = 3;
    	this.splOb_ClassBitmap = 4;
    	this.splOb_ClassInteger = 5;
    	this.splOb_ClassString = 6;
    	this.splOb_ClassArray = 7;
    	//this.splOb_SmalltalkDictionary = 8;  old slot 8
    	this.splOb_ClassFloat = 9;
    	this.splOb_ClassMethodContext = 10;
    	this.splOb_ClassBlockContext = 11;
    	this.splOb_ClassPoint = 12;
    	this.splOb_ClassLargePositiveInteger = 13;
    	this.splOb_TheDisplay = 14;
    	this.splOb_ClassMessage = 15;
    	this.splOb_ClassCompiledMethod = 16;
    	this.splOb_TheLowSpaceSemaphore = 17;
    	this.splOb_ClassSemaphore = 18;
    	this.splOb_ClassCharacter = 19;
    	this.splOb_SelectorDoesNotUnderstand = 20;
    	this.splOb_SelectorCannotReturn = 21;
    	this.splOb_TheInputSemaphore = 22;
    	this.splOb_SpecialSelectors = 23;
    	this.splOb_CharacterTable = 24;
    	this.splOb_SelectorMustBeBoolean = 25;
    	this.splOb_ClassByteArray = 26;
    	this.splOb_ClassProcess = 27;
    	this.splOb_CompactClasses = 28;
    	this.splOb_TheTimerSemaphore = 29;
    	this.splOb_TheInterruptSemaphore = 30;
    	this.splOb_FloatProto = 31;
    	this.splOb_SelectorCannotInterpret = 34;
    	this.splOb_MethodContextProto = 35;
    	this.splOb_BlockContextProto = 37;
    	this.splOb_ExternalObjectsArray = 38;
    	this.splOb_ClassPseudoContext = 39;
    	this.splOb_ClassTranslatedMethod = 40;
    	this.splOb_TheFinalizationSemaphore = 41;
    	this.splOb_ClassLargeNegativeInteger = 42;
    	this.splOb_ClassExternalAddress = 43;
    	this.splOb_ClassExternalStructure = 44;
    	this.splOb_ClassExternalData = 45;
    	this.splOb_ClassExternalFunction = 46;
    	this.splOb_ClassExternalLibrary = 47;
    	this.splOb_SelectorAboutToReturn = 48;

    },
},
'reading', {
    readFromBuffer: function(buffer) {
        var data = new DataView(buffer),
            littleEndian = false,
            pos = 0;
        var readInt = function() {
            var int = data.getInt32(pos, littleEndian);
            pos += 4;
            return int;
        };
        // read version
        var version = readInt();
        if (version != 6502) {
            littleEndian = true; pos = 0;
            version = readInt();
            if (version != 6502) throw "bad image version";
        }
        // read header
        var headerSize = readInt();
        var endOfMemory = readInt(); //first unused location in heap
        var oldBaseAddr = readInt(); //object memory base address of image
        var specialObjectsOopInt = readInt(); //oop of array of special oops
        this.lastHash = readInt(); //Should be loaded from, and saved to the image header
        var savedWindowSize = readInt();
        var fullScreenFlag = readInt();
        var extraVMMemory = readInt();
        pos += headerSize - (9 * 4); //skip to end of header
        // read objects
        this.objectTable = new Array();
        var oopMap = {};
        for (var i = 0; i < endOfMemory; ) {
            var nWords = 0;
            var classInt = 0;
            var header = readInt();
            switch (header & this.HeaderTypeMask) {
                case this.HeaderTypeSizeAndClass:
                    nWords = header >> 2;
                    classInt = readInt();
                    header = readInt();
                    i += 12;
                    break;
                case this.HeaderTypeClass:
                    classInt = header - this.HeaderTypeClass;
                    header = readInt();
                    nWords = (header >> 2) & 63;
                    i += 8;
                    break;
                case this.HeaderTypeShort:
                    nWords = (header >> 2) & 63;
                    classInt = (header >> 12) & 31; //compact class index
                    //Note classInt<32 implies compact class index
                    i += 4;
                    break;
                case this.HeaderTypeFree:
                    throw "Unexpected free block";
            }
            var baseAddr = i - 4; //0-rel byte oop of this object (base header)
            nWords--;  //length includes base header which we have already read
            var format = ((header>>8) & 15);
            var hash = ((header>>17) & 4095);

            // Note classInt and bits are just raw data; no base addr adjustment and no int conversion
            var bits = new Array(nWords);
            for (var j = 0; j<nWords; j++)
                bits[j] = readInt();
            i += nWords*4;

            var object = new lib.squeak.vm.Object();
            object.initFromImage(classInt, format, hash, bits);
            this.registerObject(object);
            //oopMap is from old oops to new objects
            oopMap[oldBaseAddr + baseAddr] = object;
        }
        show("objects: "+ Object.keys(oopMap).length);
        //create proper objects
        var splObs         = oopMap[specialObjectsOopInt];
        var compactClasses = oopMap[splObs.bits[this.splOb_CompactClasses]].bits;
        var floatClass     = oopMap[splObs.bits[this.splOb_ClassFloat]];
        for (var oop in oopMap)
            oopMap[oop].installFromImage(oopMap, compactClasses, floatClass);
        this.specialObjectsArray = splObs;
        this.decorateKnownObjects();
     },
    decorateKnownObjects: function() {
        var splObjs = this.specialObjectsArray.pointers;
        splObjs[this.splOb_NilObject].isNil = true;
        splObjs[this.splOb_TrueObject].isTrue = true;
        splObjs[this.splOb_FalseObject].isFalse = true;
    }

},
'object table', {
    registerObject: function(obj) {
        this.objectTable.push(obj);
    	this.lastHash = (13849 + (27181 * this.lastHash)) & 0xFFFFFFFF;
        return this.lastHash & 0xFFF;
    }
});
Object.subclass('lib.squeak.vm.Object',
'initialization', {
    initFromImage: function(cls, fmt, hsh, data) {
        // initial creation from Image, with unmapped data
        this.sqClass = cls;
        this.format = fmt;
        this.hash = hsh;
        this.bits = data;
    },
    decodeFloat: function(theBits) {
        var buffer = new ArrayBuffer(8);
        var data = new DataView(buffer);
        data.setUint32(0, theBits[0], false);
        data.setUint32(4, theBits[1], false);
        var float = data.getFloat64(0, false);
        return float;
    },

    installFromImage: function(oopMap, ccArray, floatClass) {
        //Install this object by decoding format, and rectifying pointers
        var ccInt = this.sqClass;
        // map compact classes
        if ((ccInt>0) && (ccInt<32))
            this.sqClass = oopMap[ccArray[ccInt-1]];
        else
            this.sqClass = oopMap[ccInt];
        var nWords= this.bits.length;
        if (this.format < 5) {
            //Formats 0...4 -- Pointer fields
            this.pointers = this.decodePointers(nWords, this.bits, oopMap);
            delete this.bits; }
        else if (this.format >= 12) {
            //Formats 12-15 -- CompiledMethods both pointers and bits
            var methodHeader = this.bits[0];
            var numLits = (methodHeader>>10) & 255;
            this.isCompiledMethod = true;
            this.pointers = this.decodePointers(numLits+1, this.bits, oopMap); //header+lits
            this.bits = this.decodeBytes(nWords-(numLits+1), this.bits, numLits+1, this.format & 3); }
        else if (this.format >= 8) {
            //Formats 8..11 -- ByteArrays (and Strings)
            this.bits = this.decodeBytes(nWords, this.bits, 0, this.format & 3); }
        //Format 6 word objects are already OK (except Floats...)
        else if (this.sqClass == floatClass) {
            //Floats need two ints to be converted to double
            this.isFloat = true;
            this.bits = this.decodeFloat(this.bits); }
    },

    decodePointers: function(nWords, theBits, oopMap) {
        //Convert small ints and look up object pointers in oopMap
        if (nWords == 0)
            return null;
        var ptrs = new Array(nWords);
        for (var i=0; i<nWords; i++) {
            var oldOop = theBits[i];
            if ((oldOop&1) == 1)
                ptrs[i] = oldOop >> 1;      // SmallInteger
            else
                ptrs[i] = oopMap[oldOop];   // Object
        }
        return ptrs;
    },
    decodeBytes: function(nWords, theBits, wordOffset, fmtLowBits) {
        //Adjust size for low bits and extract bytes from ints
        if (nWords == 0)
            return null;
        var nBytes = (nWords*4) - fmtLowBits;
        var newBits = new Array(nBytes);
        var wordIx = wordOffset;
        var fourBytes = 0;
        for (var i=0; i<nBytes; i++) {
            if ((i&3)==0)
                fourBytes = theBits[wordIx++];
            newBits[i]= (fourBytes>>(8*(3-(i&3))))&255;
        }
        return newBits;
    }

},
'printing', {
    toString: function() {
        return Strings.format('sqObj(%s)',
            this.sqClass.constructor == lib.squeak.vm.Object ? this.sqInstName() : this.sqClass);
    },
    bitsAsString: function() {
        return this.bits.map(function(char) { return String.fromCharCode(char); }).join('');
    },
    sqClassName: function() {
        // the 7th inst var of a class holds either the name, or the non-meta class if this is a metaclass
        var nameOrNonMetaClass = this.sqClass.pointers[6];
        var isMeta = !nameOrNonMetaClass.bits;
        var nameObj = isMeta ? nameOrNonMetaClass.pointers[6] : nameOrNonMetaClass;
        var name = nameObj.bitsAsString();
        return isMeta ? name + " class" : name;
    },
    slotNameAt: function(index) {
        // one-based index
        var instSize = this.sqClass.instSize();
        if (index <= instSize)
            return this.sqClass.allInstVarNames()[index - 1];
        else
            return (index - instSize).toString();
    },

    sqInstName: function() {
        if (this.isNil) return "nil";
        if (this.isTrue) return "true";
        if (this.isFalse) return "false";
        var className = this.sqClassName();
        if (/ /.test(className))
            return 'the ' + className;
        var inst = '';
        switch (className) {
            case 'String':
            case 'ByteString':
            case 'WideString':
            case 'Symbol':
            case 'WideSymbol':
            case 'ByteSymbol':
                inst = ' "'+this.bitsAsString()+'"'; break;
        }
        return  (/^[aeiou]/i.test(className) ? 'an ' + className : 'a ' + className) + inst;
    },

},
'as class', {
    instSize: function() {
        // this is a class, answer number of named inst vars
        var format = this.pointers[2];
        return ((format >> 10) & 0xC0) + ((format >> 1) & 0x3F) - 1;
    },
    instVarNames: function() {
        return (this.pointers[4].pointers || []).map(function(each) {
            return each.bitsAsString();
        });
    },

    allInstVarNames: function() {
        var superclass = this.superclass();
        if (superclass.isNil)
            return this.instVarNames();
        else
            return superclass.allInstVarNames().concat(this.instVarNames());
    }

});

}) // end of module
<commit_msg>forgot one method<commit_after>module('lib.squeak.vm').requires().toRun(function() {
/*
 * Copyright (c) 2013 Bert Freudenberg
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

Object.subclass('lib.squeak.vm.Image',
'initialization', {
    initialize: function() {
        // object headers
    	this.HeaderTypeMask = 3;
    	this.HeaderTypeSizeAndClass = 0; //3-word header
    	this.HeaderTypeClass = 1;        //2-word header
    	this.HeaderTypeFree = 2;         //free block
	    this.HeaderTypeShort = 3;        //1-word header

        // Indices into SpecialObjects array
        this.splOb_NilObject = 0;
    	this.splOb_FalseObject = 1;
    	this.splOb_TrueObject = 2;
    	this.splOb_SchedulerAssociation = 3;
    	this.splOb_ClassBitmap = 4;
    	this.splOb_ClassInteger = 5;
    	this.splOb_ClassString = 6;
    	this.splOb_ClassArray = 7;
    	//this.splOb_SmalltalkDictionary = 8;  old slot 8
    	this.splOb_ClassFloat = 9;
    	this.splOb_ClassMethodContext = 10;
    	this.splOb_ClassBlockContext = 11;
    	this.splOb_ClassPoint = 12;
    	this.splOb_ClassLargePositiveInteger = 13;
    	this.splOb_TheDisplay = 14;
    	this.splOb_ClassMessage = 15;
    	this.splOb_ClassCompiledMethod = 16;
    	this.splOb_TheLowSpaceSemaphore = 17;
    	this.splOb_ClassSemaphore = 18;
    	this.splOb_ClassCharacter = 19;
    	this.splOb_SelectorDoesNotUnderstand = 20;
    	this.splOb_SelectorCannotReturn = 21;
    	this.splOb_TheInputSemaphore = 22;
    	this.splOb_SpecialSelectors = 23;
    	this.splOb_CharacterTable = 24;
    	this.splOb_SelectorMustBeBoolean = 25;
    	this.splOb_ClassByteArray = 26;
    	this.splOb_ClassProcess = 27;
    	this.splOb_CompactClasses = 28;
    	this.splOb_TheTimerSemaphore = 29;
    	this.splOb_TheInterruptSemaphore = 30;
    	this.splOb_FloatProto = 31;
    	this.splOb_SelectorCannotInterpret = 34;
    	this.splOb_MethodContextProto = 35;
    	this.splOb_BlockContextProto = 37;
    	this.splOb_ExternalObjectsArray = 38;
    	this.splOb_ClassPseudoContext = 39;
    	this.splOb_ClassTranslatedMethod = 40;
    	this.splOb_TheFinalizationSemaphore = 41;
    	this.splOb_ClassLargeNegativeInteger = 42;
    	this.splOb_ClassExternalAddress = 43;
    	this.splOb_ClassExternalStructure = 44;
    	this.splOb_ClassExternalData = 45;
    	this.splOb_ClassExternalFunction = 46;
    	this.splOb_ClassExternalLibrary = 47;
    	this.splOb_SelectorAboutToReturn = 48;

    },
},
'reading', {
    readFromBuffer: function(buffer) {
        var data = new DataView(buffer),
            littleEndian = false,
            pos = 0;
        var readInt = function() {
            var int = data.getInt32(pos, littleEndian);
            pos += 4;
            return int;
        };
        // read version
        var version = readInt();
        if (version != 6502) {
            littleEndian = true; pos = 0;
            version = readInt();
            if (version != 6502) throw "bad image version";
        }
        // read header
        var headerSize = readInt();
        var endOfMemory = readInt(); //first unused location in heap
        var oldBaseAddr = readInt(); //object memory base address of image
        var specialObjectsOopInt = readInt(); //oop of array of special oops
        this.lastHash = readInt(); //Should be loaded from, and saved to the image header
        var savedWindowSize = readInt();
        var fullScreenFlag = readInt();
        var extraVMMemory = readInt();
        pos += headerSize - (9 * 4); //skip to end of header
        // read objects
        this.objectTable = new Array();
        var oopMap = {};
        for (var i = 0; i < endOfMemory; ) {
            var nWords = 0;
            var classInt = 0;
            var header = readInt();
            switch (header & this.HeaderTypeMask) {
                case this.HeaderTypeSizeAndClass:
                    nWords = header >> 2;
                    classInt = readInt();
                    header = readInt();
                    i += 12;
                    break;
                case this.HeaderTypeClass:
                    classInt = header - this.HeaderTypeClass;
                    header = readInt();
                    nWords = (header >> 2) & 63;
                    i += 8;
                    break;
                case this.HeaderTypeShort:
                    nWords = (header >> 2) & 63;
                    classInt = (header >> 12) & 31; //compact class index
                    //Note classInt<32 implies compact class index
                    i += 4;
                    break;
                case this.HeaderTypeFree:
                    throw "Unexpected free block";
            }
            var baseAddr = i - 4; //0-rel byte oop of this object (base header)
            nWords--;  //length includes base header which we have already read
            var format = ((header>>8) & 15);
            var hash = ((header>>17) & 4095);

            // Note classInt and bits are just raw data; no base addr adjustment and no int conversion
            var bits = new Array(nWords);
            for (var j = 0; j<nWords; j++)
                bits[j] = readInt();
            i += nWords*4;

            var object = new lib.squeak.vm.Object();
            object.initFromImage(classInt, format, hash, bits);
            this.registerObject(object);
            //oopMap is from old oops to new objects
            oopMap[oldBaseAddr + baseAddr] = object;
        }
        show("objects: "+ Object.keys(oopMap).length);
        //create proper objects
        var splObs         = oopMap[specialObjectsOopInt];
        var compactClasses = oopMap[splObs.bits[this.splOb_CompactClasses]].bits;
        var floatClass     = oopMap[splObs.bits[this.splOb_ClassFloat]];
        for (var oop in oopMap)
            oopMap[oop].installFromImage(oopMap, compactClasses, floatClass);
        this.specialObjectsArray = splObs;
        this.decorateKnownObjects();
     },
    decorateKnownObjects: function() {
        var splObjs = this.specialObjectsArray.pointers;
        splObjs[this.splOb_NilObject].isNil = true;
        splObjs[this.splOb_TrueObject].isTrue = true;
        splObjs[this.splOb_FalseObject].isFalse = true;
    }

},
'object table', {
    registerObject: function(obj) {
        this.objectTable.push(obj);
    	this.lastHash = (13849 + (27181 * this.lastHash)) & 0xFFFFFFFF;
        return this.lastHash & 0xFFF;
    }
});
Object.subclass('lib.squeak.vm.Object',
'initialization', {
    initFromImage: function(cls, fmt, hsh, data) {
        // initial creation from Image, with unmapped data
        this.sqClass = cls;
        this.format = fmt;
        this.hash = hsh;
        this.bits = data;
    },
    decodeFloat: function(theBits) {
        var buffer = new ArrayBuffer(8);
        var data = new DataView(buffer);
        data.setUint32(0, theBits[0], false);
        data.setUint32(4, theBits[1], false);
        var float = data.getFloat64(0, false);
        return float;
    },
    installFromImage: function(oopMap, ccArray, floatClass) {
        //Install this object by decoding format, and rectifying pointers
        var ccInt = this.sqClass;
        // map compact classes
        if ((ccInt>0) && (ccInt<32))
            this.sqClass = oopMap[ccArray[ccInt-1]];
        else
            this.sqClass = oopMap[ccInt];
        var nWords= this.bits.length;
        if (this.format < 5) {
            //Formats 0...4 -- Pointer fields
            this.pointers = this.decodePointers(nWords, this.bits, oopMap);
            delete this.bits; }
        else if (this.format >= 12) {
            //Formats 12-15 -- CompiledMethods both pointers and bits
            var methodHeader = this.bits[0];
            var numLits = (methodHeader>>10) & 255;
            this.isCompiledMethod = true;
            this.pointers = this.decodePointers(numLits+1, this.bits, oopMap); //header+lits
            this.bits = this.decodeBytes(nWords-(numLits+1), this.bits, numLits+1, this.format & 3); }
        else if (this.format >= 8) {
            //Formats 8..11 -- ByteArrays (and Strings)
            this.bits = this.decodeBytes(nWords, this.bits, 0, this.format & 3); }
        //Format 6 word objects are already OK (except Floats...)
        else if (this.sqClass == floatClass) {
            //Floats need two ints to be converted to double
            this.isFloat = true;
            this.bits = this.decodeFloat(this.bits); }
    },
    decodePointers: function(nWords, theBits, oopMap) {
        //Convert small ints and look up object pointers in oopMap
        if (nWords == 0)
            return null;
        var ptrs = new Array(nWords);
        for (var i=0; i<nWords; i++) {
            var oldOop = theBits[i];
            if ((oldOop&1) == 1)
                ptrs[i] = oldOop >> 1;      // SmallInteger
            else
                ptrs[i] = oopMap[oldOop];   // Object
        }
        return ptrs;
    },
    decodeBytes: function(nWords, theBits, wordOffset, fmtLowBits) {
        //Adjust size for low bits and extract bytes from ints
        if (nWords == 0)
            return null;
        var nBytes = (nWords*4) - fmtLowBits;
        var newBits = new Array(nBytes);
        var wordIx = wordOffset;
        var fourBytes = 0;
        for (var i=0; i<nBytes; i++) {
            if ((i&3)==0)
                fourBytes = theBits[wordIx++];
            newBits[i]= (fourBytes>>(8*(3-(i&3))))&255;
        }
        return newBits;
    }
},
'printing', {
    toString: function() {
        return Strings.format('sqObj(%s)',
            this.sqClass.constructor == lib.squeak.vm.Object ? this.sqInstName() : this.sqClass);
    },
    bitsAsString: function() {
        return this.bits.map(function(char) { return String.fromCharCode(char); }).join('');
    },
    sqClassName: function() {
        // the 7th inst var of a class holds either the name, or the non-meta class if this is a metaclass
        var nameOrNonMetaClass = this.sqClass.pointers[6];
        var isMeta = !nameOrNonMetaClass.bits;
        var nameObj = isMeta ? nameOrNonMetaClass.pointers[6] : nameOrNonMetaClass;
        var name = nameObj.bitsAsString();
        return isMeta ? name + " class" : name;
    },
    slotNameAt: function(index) {
        // one-based index
        var instSize = this.sqClass.instSize();
        if (index <= instSize)
            return this.sqClass.allInstVarNames()[index - 1];
        else
            return (index - instSize).toString();
    },
    sqInstName: function() {
        if (this.isNil) return "nil";
        if (this.isTrue) return "true";
        if (this.isFalse) return "false";
        var className = this.sqClassName();
        if (/ /.test(className))
            return 'the ' + className;
        var inst = '';
        switch (className) {
            case 'String':
            case 'ByteString':
            case 'WideString':
            case 'Symbol':
            case 'WideSymbol':
            case 'ByteSymbol':
                inst = ' "'+this.bitsAsString()+'"'; break;
        }
        return  (/^[aeiou]/i.test(className) ? 'an ' + className : 'a ' + className) + inst;
    },
},
'as class', {
    instSize: function() {
        // this is a class, answer number of named inst vars
        var format = this.pointers[2];
        return ((format >> 10) & 0xC0) + ((format >> 1) & 0x3F) - 1;
    },
    instVarNames: function() {
        return (this.pointers[4].pointers || []).map(function(each) {
            return each.bitsAsString();
        });
    },
    allInstVarNames: function() {
        var superclass = this.superclass();
        if (superclass.isNil)
            return this.instVarNames();
        else
            return superclass.allInstVarNames().concat(this.instVarNames());
    },
    superclass: function() {
        return this.pointers[0];
    }
});

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


<commit_before>import * as core from '../../core';

const Sprite = core.Sprite;
const Text = core.Text;

/**
 * Renders simple text and updates it without some computations
 *
 * @param {boolean} recompute - Whether recompute line position
 * @private
 **/
Text.prototype.updateTextFast = function (recompute)
{
    const style = this._style;
    const text = this._text;

    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

    let linePositionX;
    let linePositionY;

    if (!this._linePositionX || recompute)
    {
        // const xShadowOffset = Math.cos(style.dropShadowAngle) * style.dropShadowDistance;
        const maxLineWidth = this.canvas.width;
        let lineWidth = this.context.measureText(text).width + (style.letterSpacing * (text.length - 1));

        lineWidth += style.padding * 2 + style.strokeThickness;

        if (style.dropShadow)
        {
            lineWidth += style.dropShadowDistance;
        }

        linePositionX = style.strokeThickness / 2 + style.padding;

        if (style.align === 'right')
        {
            linePositionX += maxLineWidth - lineWidth;
        }
        else if (style.align === 'center')
        {
            linePositionX += (maxLineWidth - lineWidth) / 2;
        }
        this._linePositionX = linePositionX;
    }
    else
    {
        linePositionX = this._linePositionX;
    }

    if (!this._linePositionY || recompute)
    {
        // const yShadowOffset = Math.sin(style.dropShadowAngle) * style.dropShadowDistance;
        const fontProperties = Text.calculateFontProperties(this._font);

        linePositionY = (style.strokeThickness / 2) + fontProperties.ascent + style.padding;
        this._linePositionY = linePositionY;
    }
    else
    {
        linePositionY = this._linePositionY;
    }

    if (style.stroke && style.strokeThickness)
    {
        this.drawLetterSpacing(text, linePositionX, linePositionY, true);
    }

    if (style.fill)
    {
        this.drawLetterSpacing(text, linePositionX, linePositionY);
    }

    this._onTextureUpdate();
    this._texture.baseTexture.emit('update', this._texture.baseTexture);

    this.dirtyFast = false;
};

/**
 * Sets the text & do updateTextFast.
 *
 * @param {string} text - The value to set to
 * @param {boolean} recompute - Whether recompute line position
 */
Text.prototype.setTextFast = function (text, recompute)
{
    text = String(text || ' ');

    if (this._text === text)
    {
        return;
    }
    this._text = text;
    this.dirtyFast = true;
    this.dirtyFastRecompute = recompute;
};

/**
 * Renders the object using the WebGL renderer
 *
 * @param {PIXI.WebGLRenderer} renderer - The renderer
 */
Text.prototype.renderWebGL = function (renderer)
{
    if (this.resolution !== renderer.resolution)
    {
        this.resolution = renderer.resolution;
        this.dirty = true;
    }

    if (this.dirty)
    {
        this.updateText(true);
    }
    else if (this.dirtyFast)
    {
        this.updateTextFast(this.dirtyFastRecompute);
        this.dirtyFastRecompute = false;
    }

    // super.renderWebGL(renderer);
    Sprite.prototype.renderWebGL.call(this, renderer);
};
<commit_msg>update mixin-Text<commit_after>import * as core from '../../core';

const Sprite = core.Sprite;
const Text = core.Text;
const TextMetrics = core.TextMetrics;

/**
 * Renders simple text and updates it without some computations
 *
 * @param {boolean} recompute - Whether recompute line position
 * @private
 **/
Text.prototype.updateTextFast = function (recompute)
{
    const style = this._style;
    const text = this._text;

    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);

    let linePositionX;
    let linePositionY;

    if (!this._linePositionX || recompute)
    {
        // const xShadowOffset = Math.cos(style.dropShadowAngle) * style.dropShadowDistance;
        const maxLineWidth = this.canvas.width;
        let lineWidth = this.context.measureText(text).width + (style.letterSpacing * (text.length - 1));

        lineWidth += style.padding * 2 + style.strokeThickness;

        if (style.dropShadow)
        {
            lineWidth += style.dropShadowDistance;
        }

        linePositionX = style.strokeThickness / 2 + style.padding;

        if (style.align === 'right')
        {
            linePositionX += maxLineWidth - lineWidth;
        }
        else if (style.align === 'center')
        {
            linePositionX += (maxLineWidth - lineWidth) / 2;
        }
        this._linePositionX = linePositionX;
    }
    else
    {
        linePositionX = this._linePositionX;
    }

    if (!this._linePositionY || recompute)
    {
        // const yShadowOffset = Math.sin(style.dropShadowAngle) * style.dropShadowDistance;
        const fontProperties = TextMetrics.measureFont(this._font);

        linePositionY = (style.strokeThickness / 2) + fontProperties.ascent + style.padding;
        this._linePositionY = linePositionY;
    }
    else
    {
        linePositionY = this._linePositionY;
    }

    if (style.stroke && style.strokeThickness)
    {
        this.drawLetterSpacing(text, linePositionX, linePositionY, true);
    }

    if (style.fill)
    {
        this.drawLetterSpacing(text, linePositionX, linePositionY);
    }

    this._onTextureUpdate();
    this._texture.baseTexture.emit('update', this._texture.baseTexture);

    this.dirtyFast = false;
};

/**
 * Sets the text & do updateTextFast.
 *
 * @param {string} text - The value to set to
 * @param {boolean} recompute - Whether recompute line position
 */
Text.prototype.setTextFast = function (text, recompute)
{
    text = String(text || ' ');

    if (this._text === text)
    {
        return;
    }
    this._text = text;
    this.dirtyFast = true;
    this.dirtyFastRecompute = recompute;
};

/**
 * Renders the object using the WebGL renderer
 *
 * @param {PIXI.WebGLRenderer} renderer - The renderer
 */
Text.prototype.renderWebGL = function (renderer)
{
    if (this.resolution !== renderer.resolution)
    {
        this.resolution = renderer.resolution;
        this.dirty = true;
    }

    if (this.dirty)
    {
        this.updateText(true);
    }
    else if (this.dirtyFast)
    {
        this.updateTextFast(this.dirtyFastRecompute);
        this.dirtyFastRecompute = false;
    }

    // super.renderWebGL(renderer);
    Sprite.prototype.renderWebGL.call(this, renderer);
};
<|endoftext|>


<commit_before>(function () {
  "use strict";

  var fs = require('fs'),
    StringDecoder = require('string_decoder').StringDecoder;

  function LineReader(fd, cb, separator, encoding, bufferSize) {
    var filePosition = 0,
      encoding = encoding || 'utf8',
      separator = separator || '\n',
      bufferSize = bufferSize || 1024,
      buffer = new Buffer(bufferSize),
      bufferStr = '',
      decoder = new StringDecoder(encoding),
      closed = false,
      eof = false,
      separatorIndex = -1;

    function close() {
      if (!closed) {
        fs.close(fd, function (err) {
          if (err) {
            throw err;
          }
        });
        closed = true;
      }
    }

    function readToSeparator(cb) {
      function readChunk() {
        fs.read(fd, buffer, 0, bufferSize, filePosition, function (err, bytesRead) {
          var separatorAtEnd;

          if (err) {
            throw err;
          }

          if (bytesRead < bufferSize) {
            eof = true;
            close();
          }

          filePosition += bytesRead;

          bufferStr += decoder.write(buffer.slice(0, bytesRead));

          if (separatorIndex < 0) {
            separatorIndex = bufferStr.indexOf(separator);
          }

          separatorAtEnd = separatorIndex === bufferStr.length - 1;
          if (bytesRead && (separatorIndex === -1 || separatorAtEnd) && !eof) {
            readChunk();
          } else {
            cb();
          }
        });
      }

      readChunk();
    }

    function hasNextLine() {
      return bufferStr.length > 0 || !eof;
    }

    function nextLine(cb) {
      function getLine() {
        var ret = bufferStr.substring(0, separatorIndex - 1);

        bufferStr = bufferStr.substring(separatorIndex + separator.length);
        separatorIndex = -1;
        cb(ret);
      }

      if (separatorIndex < 0) {
        separatorIndex = bufferStr.indexOf(separator);
      }

      if (separatorIndex < 0) {
        if (eof) {
          if (hasNextLine()) {
            separatorIndex = bufferStr.length;
            getLine();
          } else {
            throw new Error('No more lines to read.');
          }
        } else {
          readToSeparator(getLine);
        }
      } else {
        getLine();
      }
    }

    this.hasNextLine = hasNextLine;
    this.nextLine = nextLine;
    this.close = close;

    readToSeparator(cb);
  }

  function open(filename, cb, separator, encoding, bufferSize) {
    fs.open(filename, 'r', parseInt('666', 8), function (err, fd) {
      var reader;
      if (err) {
        throw err;
      }

      reader = new LineReader(fd, function () {
        cb(reader);
      }, separator, encoding, bufferSize);
    });
  }

  function eachLine(filename, cb, separator, encoding, bufferSize) {
    var finalFn,
      asyncCb = cb.length == 3;

    function finish() {
      if (finalFn && typeof finalFn === 'function') {
        finalFn();
      }
    }

    open(filename, function (reader) {
      function newRead() {
        if (reader.hasNextLine()) {
          setImmediate(readNext);
        } else {
          finish();
        }
      }

      function continueCb(continueReading) {
        if (continueReading !== false) {
          newRead();
        } else {
          finish();
          reader.close();
        }
      }

      function readNext() {
        reader.nextLine(function (line) {
          var last = !reader.hasNextLine();

          if (asyncCb) {
            cb(line, last, continueCb);
          } else {
            if (cb(line, last) !== false) {
              newRead();
            } else {
              finish();
              reader.close();
            }
          }
        });
      }

      newRead();
    }, separator, encoding, bufferSize);

    return {
      then: function (cb) {
        finalFn = cb;
      }
    };
  }

  module.exports.open = open;
  module.exports.eachLine = eachLine;
}());
<commit_msg>reset to initial state to test<commit_after>(function () {
  "use strict";

  var fs = require('fs'),
    StringDecoder = require('string_decoder').StringDecoder;

  function LineReader(fd, cb, separator, encoding, bufferSize) {
    var filePosition = 0,
      encoding = encoding || 'utf8',
      separator = separator || '\n',
      bufferSize = bufferSize || 1024,
      buffer = new Buffer(bufferSize),
      bufferStr = '',
      decoder = new StringDecoder(encoding),
      closed = false,
      eof = false,
      separatorIndex = -1;

    function close() {
      if (!closed) {
        fs.close(fd, function (err) {
          if (err) {
            throw err;
          }
        });
        closed = true;
      }
    }

    function readToSeparator(cb) {
      function readChunk() {
        fs.read(fd, buffer, 0, bufferSize, filePosition, function (err, bytesRead) {
          var separatorAtEnd;

          if (err) {
            throw err;
          }

          if (bytesRead < bufferSize) {
            eof = true;
            close();
          }

          filePosition += bytesRead;

          bufferStr += decoder.write(buffer.slice(0, bytesRead));

          if (separatorIndex < 0) {
            separatorIndex = bufferStr.indexOf(separator);
          }

          separatorAtEnd = separatorIndex === bufferStr.length - 1;
          if (bytesRead && (separatorIndex === -1 || separatorAtEnd) && !eof) {
            readChunk();
          } else {
            cb();
          }
        });
      }

      readChunk();
    }

    function hasNextLine() {
      return bufferStr.length > 0 || !eof;
    }

    function nextLine(cb) {
      function getLine() {
        var ret = bufferStr.substring(0, separatorIndex);

        bufferStr = bufferStr.substring(separatorIndex + separator.length);
        separatorIndex = -1;
        cb(ret);
      }

      if (separatorIndex < 0) {
        separatorIndex = bufferStr.indexOf(separator);
      }

      if (separatorIndex < 0) {
        if (eof) {
          if (hasNextLine()) {
            separatorIndex = bufferStr.length;
            getLine();
          } else {
            throw new Error('No more lines to read.');
          }
        } else {
          readToSeparator(getLine);
        }
      } else {
        getLine();
      }
    }

    this.hasNextLine = hasNextLine;
    this.nextLine = nextLine;
    this.close = close;

    readToSeparator(cb);
  }

  function open(filename, cb, separator, encoding, bufferSize) {
    fs.open(filename, 'r', parseInt('666', 8), function (err, fd) {
      var reader;
      if (err) {
        throw err;
      }

      reader = new LineReader(fd, function () {
        cb(reader);
      }, separator, encoding, bufferSize);
    });
  }

  function eachLine(filename, cb, separator, encoding, bufferSize) {
    var finalFn,
      asyncCb = cb.length == 3;

    function finish() {
      if (finalFn && typeof finalFn === 'function') {
        finalFn();
      }
    }

    open(filename, function (reader) {
      function newRead() {
        if (reader.hasNextLine()) {
          setImmediate(readNext);
        } else {
          finish();
        }
      }

      function continueCb(continueReading) {
        if (continueReading !== false) {
          newRead();
        } else {
          finish();
          reader.close();
        }
      }

      function readNext() {
        reader.nextLine(function (line) {
          var last = !reader.hasNextLine();

          if (asyncCb) {
            cb(line, last, continueCb);
          } else {
            if (cb(line, last) !== false) {
              newRead();
            } else {
              finish();
              reader.close();
            }
          }
        });
      }

      newRead();
    }, separator, encoding, bufferSize);

    return {
      then: function (cb) {
        finalFn = cb;
      }
    };
  }

  module.exports.open = open;
  module.exports.eachLine = eachLine;
}());
<|endoftext|>


<commit_before>var Txn = require('./txn.js'),
    binding = require('../../build/Release/kv.node');

var Cursor = module.exports = function (db, txn) {
    if (!(txn instanceof Txn)) throw new Error('LMDB_cursor: Invalid txn param.');

    var CursorClass = binding.lmdb[['Cursor', db._opt.keyType, db._opt.valueType || db._opt.valType].join('_')];
    if (!CursorClass) throw new Error('Unsupported cursor key/value types, this should not happen.');

    this._keySanitize = db._keySanitize;
    this._valSanitize = db._valSanitize;

    this._cursor = new CursorClass(db._db, txn._txn);
};

function delegate(fn) {
    Cursor.prototype[fn] = function () {
        return this._cursor[fn]();
    }
}

delegate('close');
delegate('del');
delegate('current');
delegate('next');
delegate('prev');
delegate('nextDup');
delegate('prevDup');
delegate('close');
delegate('first');
delegate('last');
delegate('firstDup');
delegate('lastDup');

Cursor.prototype.seek = function (key, val) {
    return arguments.length === 1 ?
        this._cursor.seek(this._keySanitize(key)) :
        this._cursor.seek(this._keySanitize(key), this._valSanitize(val));
};

Cursor.prototype.gte = function (key, val) {
    return arguments.length === 1 ?
        this._cursor.gte(this._keySanitize(key)) :
        this._cursor.gte(this._keySanitize(key), this._valSanitize(val));
};
<commit_msg>fix lmdb cursor.<commit_after>var Txn = require('./txn.js'),
    binding = require('../../build/Release/kv.node');

var Cursor = module.exports = function (db, txn) {
    if (!(txn instanceof Txn)) throw new Error('LMDB_cursor: Invalid txn param.');

    var CursorClass = binding.lmdb[['Cursor', db._opt.keyType, db._opt.valueType || db._opt.valType].join('_')];
    if (!CursorClass) throw new Error('Unsupported cursor key/value types, this should not happen.');

    this._keySanitize = db._keySanitize;
    this._valSanitize = db._valSanitize;

    this._cursor = new CursorClass(db._db, txn._txn);
};

function delegate(fn) {
    Cursor.prototype[fn] = function () {
        return this._cursor[fn]();
    }
}

delegate('close');
delegate('del');
delegate('current');
delegate('next');
delegate('prev');
delegate('nextDup');
delegate('prevDup');
delegate('first');
delegate('last');
delegate('firstDup');
delegate('lastDup');

Cursor.prototype.seek = function (key, val) {
    return arguments.length === 1 ?
        this._cursor.seek(this._keySanitize(key)) :
        this._cursor.seek(this._keySanitize(key), this._valSanitize(val));
};

Cursor.prototype.gte = function (key, val) {
    return arguments.length === 1 ?
        this._cursor.gte(this._keySanitize(key)) :
        this._cursor.gte(this._keySanitize(key), this._valSanitize(val));
};
<|endoftext|>