<commit_before>const fs = require('fs')
const fse = require('fs-extra')
const path = require('path')
const name = require('./package.json').name
const DEFAULT_SEP = '/'
const FILTER_OUT_DIR = ['.idea', '.vscode', '.gitignore', 'node_modules']
const DEFAULT_OPTION = {
  src: resolve('src'),
  dist: resolve('src'),
  resolve: ['html'],
  urlCb (input) { return input}
}

// 1. gather html file
// 2. gather production file
// 3. upload all production file
// 4. find the usage of production file in html file
// 5. if found, replace

function resolve (...input) {
  return path.resolve(...input)
}

function normalize (input, sep = DEFAULT_SEP) {
  const _input = path.normalize(input)
  return _input.split(path.sep).join(sep)
}

function join (...inputs) {
  return normalize(path.join(...inputs))
}

function isFilterOutDir (input) {
  return FILTER_OUT_DIR.includes(input)
}

/**
 * produce RegExp to match local path
 * @param {string} localPath
 * @return {RegExp}
 */
function generateLocalPathReg (localPath) {
  const pathArr = localPath
    .split(DEFAULT_SEP)
  const len = pathArr.length
  const regStr = pathArr
    .map((part, index) => {
      if (index === len - 1) {
        return `${part}`
      } else {
        return `\\.?(${part})?`
      }
    })
    .join(`\\${DEFAULT_SEP}?`)
  return new RegExp(regStr, 'g')
}

/**
 * find file usage
 * 1. make sure the range: srcPath
 * 2. provide inline path to search and to replace with: localCdnPair
 * @param {string} srcPath
 * @param {string} distPath
 * @return {function}
 */
function simpleReplace (srcPath, distPath = srcPath) {
  const srcFile = fs.readFileSync(srcPath, 'utf-8')
  return function savePair (localCdnPair) {
    const ret = localCdnPair
      .reduce((last, file) => {
        const localPath = normalize(file[0])
        const cdnPath = file[1]
        const localPathReg = generateLocalPathReg(localPath)
        last = last.replace(localPathReg, match => cdnPath)
        return last
      }, srcFile)
    fse.ensureFileSync(distPath)
    fs.writeFileSync(distPath, ret)
  }
}

/**
 * gather specific file type within directory provided
 * 1. provide range to search: src
 * 2. provide the type of file to search: type
 * @param {string} src: directory to search
 * @return {function}
 */
function gatherFileIn (src) {
  return function gatherFileType (type) {
    return fs.readdirSync(src)
      .reduce((last, file) => {
        const filePath = resolve(src, file)
        if (isFile(filePath)) {
          path.extname(file) === `.${type}` && last.push(normalize(filePath))
        } else if (isFilterOutDir(file)) {
          // do nothing
        } else if (isDir(filePath)) {
          last = last.concat(gatherFileIn(filePath)(type))
        }
        return last
      }, [])
  }
}

function isFile (input) {
  return fs.statSync(input).isFile()
}

function isDir (input) {
  return fs.statSync(input).isDirectory()
}

function isType (type) {
  return function enterFile (file) {
    return isFile(file) && path.extname(file) === '.' + type
  }
}

/**
 * give the power of playing with cdn url
 * @param {string[][]} entries
 * @param {function} cb
 * @returns {[string, string][]}
 */
function processCdnUrl (entries, cb) {
  if (typeof cb !== 'function') return console.error(`[${name}]: urlCb is not function`)
  return entries.map(pair => {
    // pair[1] should be cdn url
    pair[1] = cb(pair[1])
    if (typeof pair[1] !== 'string') console.error(`[${name}]: the return result of urlCb is not string`)
    return pair
  })
}

function mapSrcToDist (srcFilePath, srcRoot, distRoot) {
  return srcFilePath.replace(srcRoot, distRoot)
}

const isJpg = isType('jpg')
const isPng = isType('png')
const isGif = isType('gif')
const isWebp = isType('webp')
const isCss = isType('css')
const isJs = isType('js')

/**
 * webpack upload plugin
 * early version need more work
 * @param {{upload: Promise}} cdn
 * custom cdn module, need to have an upload API, return a Promise with structured response
 * like {localPath: cdnPath}
 * @param {{src: string, dist: string}} option
 * provide information about what the source html directory and compiled html directory
 * @constructor
 */
function UploadPlugin (cdn, option = DEFAULT_OPTION) {
  this.cdn = cdn
  this.option = Object.assign({}, DEFAULT_OPTION, option)
}

UploadPlugin.prototype.apply = function (compiler) {
  const self = this
  // extra treatment for cdnUrl
  const urlCb = this.option.urlCb
  // could process other type of files rather than limited to html
  const resolveList = this.option.resolve
  // get absolute path of src and dist directory
  const srcRoot = resolve(this.option.src)
  const distRoot = resolve(this.option.dist)

  compiler.plugin('done', async function (stats) {
    const hash = stats.compilation.hash
    // all assets including js/css/img
    const assets = stats.compilation.assets
    const assetsNames = Object.keys(assets)
    // classify assets
    const desireAssets = assetsNames.reduce((last, name) => {
      const assetInfo = assets[name]
      const location = assetInfo.existsAt
      if (isGif(location) || isPng(location) || isJpg(location) || isWebp(location)) {
        last.img[name] = assetInfo
      } else if (isCss(location)) {
        last.css[name] = assetInfo
      } else if (isJs(location)) {
        last.js[name] = assetInfo
      }
      return last
    }, {
      img: {},
      css: {},
      js: {}
    })

    const {
      img,
      css,
      js
    } = desireAssets

    // make assets object to array with local path
    function makeArr (input) {
      return Object.keys(input)
        .map(name => {
          const info = input[name]
          return info.existsAt
        })
    }

    const imgArr = makeArr(img)

    // upload img
    // find img in css
    // replace css
    // now css ref to img with cdn path
    const imgPairs = await self.cdn.upload(imgArr)
    Object.keys(css)
      .forEach(name => {
        const location = css[name].existsAt
        simpleReplace(location)(processCdnUrl([...Object.entries(imgPairs)], urlCb))
      })
    // concat js + css
    const adjustedFiles = [...makeArr(js), ...makeArr(css)]
    const findFileInRoot = gatherFileIn(self.option.src)
    const tplFiles = resolveList.reduce((last, type) => {
      last = last.concat(findFileInRoot(type))
      return last
    }, [])
    const jsCssPair = await self.cdn.upload(adjustedFiles)
    const localCdnPair = Object.entries(jsCssPair)
    tplFiles
      .forEach(filePath => {
        simpleReplace(filePath, mapSrcToDist(filePath, srcRoot, distRoot))(processCdnUrl([...localCdnPair], urlCb))
      })
  })
}

module.exports = UploadPlugin
<commit_msg>support font files and dynamic import()<commit_after>const fs = require('fs')
const fse = require('fs-extra')
const path = require('path')
const name = require('./package.json').name
const DEFAULT_SEP = '/'
const FILTER_OUT_DIR = ['.idea', '.vscode', '.gitignore', 'node_modules']
const SCRIPT_SRC_MATCH = /script\.src\s*=\s*__webpack_require__\.p[^;]+;?/g
const DEFAULT_OPTION = {
  src: resolve('src'),
  dist: resolve('src'),
  resolve: ['html'],
  urlCb (input) {
    return input
  }
}

// 1. gather html file
// 2. gather production file
// 3. upload all production file
// 4. find the usage of production file in html file
// 5. if found, replace

function resolve (...input) {
  return path.resolve(...input)
}

function normalize (input, sep = DEFAULT_SEP) {
  const _input = path.normalize(input)
  return _input.split(path.sep).join(sep)
}

function join (...inputs) {
  return normalize(path.join(...inputs))
}

function isFilterOutDir (input) {
  return FILTER_OUT_DIR.includes(input)
}

/**
 * produce RegExp to match local path
 * @param {string} localPath
 * @return {RegExp}
 */
function generateLocalPathReg (localPath) {
  const pathArr = localPath.split(DEFAULT_SEP)
  const len = pathArr.length
  const regStr = pathArr
    .map((part, index) => {
      if (index === len - 1) {
        return `${part}`
      } else {
        return `\\.?(${part})?`
      }
    })
    .join(`\\${DEFAULT_SEP}?`)
  return new RegExp(regStr, 'g')
}

/**
 * find file usage
 * 1. make sure the range: srcPath
 * 2. provide inline path to search and to replace with: localCdnPair
 * @param {string} srcPath
 * @param {string} distPath
 * @return {function}
 */
function simpleReplace (srcPath, distPath = srcPath) {
  const srcFile = fs.readFileSync(srcPath, 'utf-8')
  return function savePair (localCdnPair) {
    const ret = localCdnPair.reduce((last, file) => {
      const localPath = normalize(file[0])
      const cdnPath = file[1]
      const localPathReg = generateLocalPathReg(localPath)
      last = last.replace(localPathReg, match => cdnPath)
      return last
    }, srcFile)
    fse.ensureFileSync(distPath)
    fs.writeFileSync(distPath, ret)
  }
}

/**
 * gather specific file type within directory provided
 * 1. provide range to search: src
 * 2. provide the type of file to search: type
 * @param {string} src: directory to search
 * @return {function}
 */
function gatherFileIn (src) {
  return function gatherFileType (type) {
    return fs.readdirSync(src).reduce((last, file) => {
      const filePath = resolve(src, file)
      if (isFile(filePath)) {
        path.extname(file) === `.${type}` && last.push(normalize(filePath))
      } else if (isFilterOutDir(file)) {
        // do nothing
      } else if (isDir(filePath)) {
        last = last.concat(gatherFileIn(filePath)(type))
      }
      return last
    }, [])
  }
}

function isFile (input) {
  return fs.statSync(input).isFile()
}

function isDir (input) {
  return fs.statSync(input).isDirectory()
}

function isType (type) {
  return function enterFile (file) {
    return isFile(file) && path.extname(file) === '.' + type
  }
}

/**
 * give the power of playing with cdn url
 * @param {*[] | Iterator<*>} entries
 * @param {function} cb
 * @returns {[string, string][]}
 */
function processCdnUrl (entries, cb) {
  if (typeof cb !== 'function')
    return console.error(`[${name}]: urlCb is not function`)
  return entries.map(pair => {
    // pair[1] should be cdn url
    pair[1] = cb(pair[1])
    if (typeof pair[1] !== 'string')
      console.error(`[${name}]: the return result of urlCb is not string`)
    return pair
  })
}

function mapSrcToDist (srcFilePath, srcRoot, distRoot) {
  return srcFilePath.replace(srcRoot, distRoot)
}

const isJpg = isType('jpg')
const isPng = isType('png')
const isGif = isType('gif')
const isWebp = isType('webp')
const isCss = isType('css')
const isJs = isType('js')
const isWoff = isType('woff')
const isWoff2 = isType('woff2')
const isTtf = isType('ttf')
const isOtf = isType('otf')
const isSvg = isType('svg')

function isFont (path) {
  return (
    isWoff(path) || isWoff2(path) || isTtf(path) || isOtf(path) || isSvg(path)
  )
}

/**
 * generate {id: name} object for all chunk chunk
 * @param {*[]} chunks
 * @param {string} chunkFileName
 */
function gatherChunks (chunks, chunkFileName) {
  return chunks.reduce((last, chunk) => {
    const id = chunk.id
    const name = chunk.name
    const hash = chunk.renderedHash
    last[id] = chunkFileName
      .replace(/\[name]/g, name || id)
      .replace(/\[hash]/g, hash)
    return last
  }, {})
}

/**
 * update script.src property for request for dynamic import
 * experimental
 * @param {string[]} files
 * @param {{id: string}} chunkCdnMap
 */
function updateScriptSrc (files, chunkCdnMap) {
  files.forEach(file => {
    const content = fs.readFileSync(file, 'utf-8')
    if (SCRIPT_SRC_MATCH.test(content)) {
      const srcAssignStr = `script.src = ${JSON.stringify(
        chunkCdnMap
      )}[chunkId];`
      const newContent = content.replace(SCRIPT_SRC_MATCH, srcAssignStr)
      fs.writeFileSync(file, newContent)
    }
  })
}

/**
 * get id of chunk given a absolute path of chunk file and id:chunk map
 * @param {string} chunkAbsPath
 * @param {{id: string}} chunkMap
 */
function getIdForChunk (chunkAbsPath, chunkMap) {
  return Object.keys(chunkMap).findIndex(
    key => chunkAbsPath.indexOf(chunkMap[key]) > -1
  )
}

/**
 * webpack upload plugin
 * early version need more work
 * @param {{upload: Promise}} cdn
 * custom cdn module, need to have an upload API, return a Promise with structured response
 * like {localPath: cdnPath}
 * @param {{src: string, dist: string}} option
 * provide information about what the source html directory and compiled html directory
 * @constructor
 */
function UploadPlugin (cdn, option = DEFAULT_OPTION) {
  this.cdn = cdn
  this.option = Object.assign({}, DEFAULT_OPTION, option)
}

UploadPlugin.prototype.apply = function (compiler) {
  const self = this
  // extra treatment for cdnUrl
  const urlCb = this.option.urlCb
  // could process other type of files rather than limited to html
  const resolveList = this.option.resolve
  // get absolute path of src and dist directory
  const srcRoot = resolve(this.option.src)
  const distRoot = resolve(this.option.dist)

  compiler.plugin('done', async function (stats) {
    const chunks = stats.compilation.chunks
    const options = stats.compilation.options

    // here we get chunks needs to be dealt with
    const chunkMap = gatherChunks(chunks, options.output.chunkFilename)

    // all assets including js/css/img
    const assets = stats.compilation.assets
    const assetsNames = Object.keys(assets)
    // classify assets
    const desireAssets = assetsNames.reduce(
      (last, name) => {
        const assetInfo = assets[name]
        const location = assetInfo.existsAt
        if (
          isGif(location) ||
          isPng(location) ||
          isJpg(location) ||
          isWebp(location)
        ) {
          last.img[name] = assetInfo
        } else if (isCss(location)) {
          last.css[name] = assetInfo
        } else if (isJs(location)) {
          last.js[name] = assetInfo
        } else if (isFont(location)) {
          last.font[name] = assetInfo
        }
        return last
      },
      {
        img: {},
        css: {},
        js: {},
        font: {}
      }
    )

    const {img, css, js, font} = desireAssets

    // make assets object to array with local path
    function makeArr (input) {
      return Object.keys(input).map(name => {
        const info = input[name]
        return info.existsAt
      })
    }

    const imgArr = makeArr(img)
    const fontArr = makeArr(font)
    const jsArr = makeArr(js)
    const chunkLen = Object.keys(chunkMap).length
    const chunkArr = Array.from(
      Object.assign({}, chunkMap, {
        length: chunkLen
      })
    )

    // find out which js files are chunk chunk, which are not
    const {notChunkJsArr, chunkArrWAbs} = jsArr.reduce(
      (last, js) => {
        const isChunk = chunkArr.some(chunk => js.indexOf(chunk) > -1)
        isChunk ? last.chunkArrWAbs.push(js) : last.notChunkJsArr.push(js)
        return last
      },
      {
        notChunkJsArr: [],
        chunkArrWAbs: []
      }
    )

    // upload img/font
    // find img/font in css
    // replace css
    // now css ref to img/font with cdn path
    // meanwhile upload chunk files to save time
    const [imgAndFontPairs, chunkPairs] = await Promise.all([
      self.cdn.upload([...imgArr, ...fontArr]),
      self.cdn.upload(chunkArrWAbs)
    ])
    // update css files with cdn img/font
    Object.keys(css).forEach(name => {
      const location = css[name].existsAt
      simpleReplace(location)(
        processCdnUrl(Object.entries(imgAndFontPairs), urlCb)
      )
    })
    // update chunkMap
    const newChunkMap = processCdnUrl(
      Object.entries(chunkPairs),
      urlCb
    ).reduce((last, entry) => {
      const localPath = entry[0]
      const cdnPath = entry[1]

      const id = getIdForChunk(localPath, chunkMap)
      last[id] = cdnPath
      return last
    }, {})
    updateScriptSrc(notChunkJsArr, newChunkMap)

    // concat js + css + img
    const adjustedFiles = [...notChunkJsArr, ...makeArr(css), ...imgArr]
    const findFileInRoot = gatherFileIn(self.option.src)
    const tplFiles = resolveList.reduce((last, type) => {
      last = last.concat(findFileInRoot(type))
      return last
    }, [])
    const jsCssPair = await self.cdn.upload(adjustedFiles)
    const localCdnPair = Object.entries(jsCssPair)
    tplFiles.forEach(filePath => {
      simpleReplace(filePath, mapSrcToDist(filePath, srcRoot, distRoot))(
        processCdnUrl(localCdnPair, urlCb)
      )
    })
  })
}

module.exports = UploadPlugin
<|endoftext|>


<commit_before>const chalk = require('chalk');
const inquirer = require("inquirer");
const deasync = require("deasync")

const getGlobal = () => {
  if(typeof gloabal !== "undefined") return gloabal;
  return window;
}
const callbackify = (promiseFactory) => {
  return (...args) => {
    const cb = args[args.length-1];
    args.pop();
    return promiseFactory(...args)
      .then( result => cb(undefined,result) )
      .catch( e => cb(e,undefined) )
  }
}

let display_development_output = false;
const colors = {
}
const defaultColors = {
  info: (...input) => chalk.blue(...input),
  form: (...input) => chalk.magenta(...input),
  success: (...input) => chalk.green(...input),
  warning: (...input) => chalk.red(...input),
  error: (...input) => chalk.white.bgRed(...input),
}
const apply_color = (colorId, ...input) => {
  const brush = colors[colorId] || console.log;
  return brush(...input);
}
const out = (colorId, ...input) => {
  console.log(apply_color(colorId, ...input));
}
const dev = (...args) => {
  if (display_development_output) out(...args);
}

const setColor = (colorId, brush) => {
  colors[colorId] = brush;
  out[colorId] = (...input) => out(colorId, ...input)
  dev[colorId] = (...input) => dev(colorId, ...input)
}

for (const colorId in defaultColors) {
  if (defaultColors.hasOwnProperty(colorId)) {
    setColor(colorId, defaultColors[colorId])
  }
}

const input = {
  text: async (questionText, defaultValue, validator) => {
    const question = {
      type: "input",
      name: "inp",
      message: questionText
    };
    if (["string", "number", "boolean", "array", "function"].includes(defaultValue))
      question.default = defaultValue;

    if (typeof validator === "function") {
      question.validate = validator;
    }
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      out.error("unable to querry", e)
    }
  },
  list: async (questionText, choices) => {
    const question = {
      type: "list",
      name: "inp",
      choices,
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      out.error("unable to querry", e)
    }
  },
  checkbox: async (questionText, choices) => {
    const question = {
      type: "checkbox",
      name: "inp",
      choices,
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      out.error("unable to querry", e)
    }
  },
  confirm: async (questionText) => {
    const question = {
      type: "confirm",
      name: "inp",
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      out.error("unable to querry", e)
    }
  },
  pass: async (questionText, validator) => {
    const question = {
      type: "password",
      name: "inp",
      message: questionText
    }
    if (typeof validator === "function") {
      question.validate = validator;
    }
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      out.error("unable to querry", e)
    }
  }
}

const syncInput = {
  text: (...args) => {
    return deasync(
      callbackify(input.text)
    )(...args);
  }
}

for (const inputType in input) {
  if (input.hasOwnProperty(inputType)) {
    syncInput[inputType] = (...args) => {
      return deasync(
        callbackify(input[inputType])
      )(...args);
    }
  }
}

module.exports = {
  setDevelopmentMode: (active) => {
    display_development_output = active;
    return active;
  },
  out,
  dev,
  apply_color,
  input,
  syncInput,
  setColor
}
<commit_msg>simplify naming<commit_after>const chalk = require('chalk');
const inquirer = require("inquirer");
const deasync = require("deasync")

const getGlobal = () => {
  if(typeof gloabal !== "undefined") return gloabal;
  return window;
}
const callbackify = (promiseFactory) => {
  return (...args) => {
    const cb = args[args.length-1];
    args.pop();
    return promiseFactory(...args)
      .then( result => cb(undefined,result) )
      .catch( e => cb(e,undefined) )
  }
}

let display_development_output = false;
const colors = {
}
const defaultColors = {
  log: (...input) => input.join(""),
  info: (...input) => chalk.blue(...input),
  form: (...input) => chalk.magenta(...input),
  success: (...input) => chalk.green(...input),
  warning: (...input) => chalk.red(...input),
  warn: (...input) => chalk.red(...input),
  error: (...input) => chalk.white.bgRed(...input),
  err: (...input) => chalk.white.bgRed(...input),
}
const apply_color = (colorId, ...input) => {
  const brush = colors[colorId] || console.log;
  return brush(...input);
}
const output = (colorId, ...input) => {
  console.log(apply_color(colorId, ...input));
}
const devOutput = (...args) => {
  if (display_development_output) output(...args);
}

const setColor = (colorId, brush) => {
  colors[colorId] = brush;
  output[colorId] = (...input) => output(colorId, ...input)
  devOutput[colorId] = (...input) => devOutput(colorId, ...input)
}

for (const colorId in defaultColors) {
  if (defaultColors.hasOwnProperty(colorId)) {
    setColor(colorId, defaultColors[colorId])
  }
}

const input = {
  text: async (questionText, defaultValue, validator) => {
    const question = {
      type: "input",
      name: "inp",
      message: questionText
    };
    if (["string", "number", "boolean", "array", "function"].includes(defaultValue))
      question.default = defaultValue;

    if (typeof validator === "function") {
      question.validate = validator;
    }
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      output.error("unable to querry", e)
    }
  },
  list: async (questionText, choices) => {
    const question = {
      type: "list",
      name: "inp",
      choices,
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      output.error("unable to querry", e)
    }
  },
  checkbox: async (questionText, choices) => {
    const question = {
      type: "checkbox",
      name: "inp",
      choices,
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      output.error("unable to querry", e)
    }
  },
  confirm: async (questionText) => {
    const question = {
      type: "confirm",
      name: "inp",
      message: questionText
    };
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      output.error("unable to querry", e)
    }
  },
  pass: async (questionText, validator) => {
    const question = {
      type: "password",
      name: "inp",
      message: questionText
    }
    if (typeof validator === "function") {
      question.validate = validator;
    }
    try {
      const response = await inquirer.prompt([question]);
      return response.inp;
    }
    catch (e) {
      output.error("unable to querry", e)
    }
  }
}

const syncInput = {
  text: (...args) => {
    return deasync(
      callbackify(input.text)
    )(...args);
  }
}

for (const inputType in input) {
  if (input.hasOwnProperty(inputType)) {
    syncInput[inputType] = (...args) => {
      return deasync(
        callbackify(input[inputType])
      )(...args);
    }
  }
}

module.exports = {
  setDevelopmentMode: (active) => {
    display_development_output = active;
    return active;
  },

  output,
  out:output,

  devOutput,
  dev:devOutput,

  apply_color,
  setColor,

  input,
  syncInput,
}
<|endoftext|>


<commit_before>/**
  imperative/index.js (https://github.com/1egoman/que)
  This file is concerned with parsing user commands.
*/

// dependencies
var _ = require("underscore"),
    fs = require("fs"),
    S = require('string');

var wV = require("./wordValidator");
var objectFragment = require("./objectFragment");

// turn an array like ['element'] into 'element'
// while keeping ['element', 'element2'] the same.
var condense = function(array) {
  return array.length == 1 ? array[0] : array;
}

// top level class
var phrase = function(textual) {

  // set class globals
  this.snt = textual;
  var self = this;

  // get verb identifiers
  var IDENT = require("./config/verb_identifiers.js").isVerbIf;

  // Split up a sentence into its general parts:
  // subject (most likely you),
  // verb, and
  // object
  this.getParts = function() {
    var parts = [];
    var words = this.getWords();

    // get the most likely verb (aka highest probability)
    var mostLikelyVerb = _.max(this.rateVerbs(), function(i) {
      return i.prob;
    });

    // is there even a verb in the sentence?
    if (mostLikelyVerb.prob === 0)
        mostLikelyVerb = {
          word: undefined,
          prob: 0,
          possibles: {}
        }

    // get our new verb's index, and from that determine subject and object
    index = words.indexOf(mostLikelyVerb.word);

    // in our case, a subject is defined as everything before the verb
    // for now, we don't really care about it, acctully
    // subject = words.slice(0, index);

    // likewise, an object is defined as everything after the verb
    object = words.slice(index+1);
    obj = new objectFragment(object);

    return {
      verb: mostLikelyVerb,
      object: condense( obj.getRequested() )
    };
  }

  /*
  where is the verb in the sentence?
  We are looking through each word in the sentence
  and ranking them from least likely to most likely
  */
  this.rateVerbs = function() {

    var allWords = this.getWords();

    // create data structure
    var words = _.map(allWords, function(w) {
      return {
        word: w,
        prob: 0,
        possibles: {
          tenses: [],
          meanings: []
        }
      }
    });

    // for each word
    _.each(words, function(word, index) {

      // look through patterns
      _.each(IDENT, function(identifier) {

        // the tests: this is where the probability is ranked
        if ( wV.validateFilter(allWords, index, identifier) ) {
          // increment probability
          word.prob += identifier.then.weight || 1;
          identifier.then.tense && word.possibles.tenses.push(identifier.then.tense);
          identifier.then.means && word.possibles.meanings.push(identifier.then.means);
        }

      });

    });

    return words;
  }

  // remove punctuation
  this.dePunctuate = function() {
    _.each(['.', '!', '?'], function(a) {
      if ( S(self.snt).endsWith(a) )
        self.snt = self.snt.replace(a, '');
    });
  }

  /*
    split up sentence into words
  */
  this.getWords = function() {
    self.dePunctuate()
    return self.snt.split(' ');
  }

}

var tests = function(){

  // test phrases
  PHR = [
    "what is the time in london?",
    "time in london",
    "get me a beer"
  ]

  // test each one
  _.each(PHR, function(t) {
    console.log("========================", "\nphrase:", t);

    // output
    p = new phrase(t);
    pts = p.getParts();
    console.log(
      pts.verb.word,
      "->",
      pts.verb.possibles
    );
    console.log(pts.object)
  });
  console.log("========================");

}

if (require.main === module) {
  tests();
}
<commit_msg>added mostlikelyverb<commit_after>/**
  imperative/index.js (https://github.com/1egoman/que)
  This file is concerned with parsing user commands.
*/

// dependencies
var _ = require("underscore"),
    fs = require("fs"),
    S = require('string');

var wV = require("./wordValidator");
var objectFragment = require("./objectFragment");

// turn an array like ['element'] into 'element'
// while keeping ['element', 'element2'] the same.
var condense = function(array) {
  return array.length == 1 ? array[0] : array;
}

// top level class
var phrase = function(textual) {

  // set class globals
  this.snt = textual;
  var self = this;

  // get verb identifiers
  var IDENT = require("./config/verb_identifiers.js").isVerbIf;

  // Get the most likely word in the sentence to be a verb
  this.getBestVerb = function() {
    return _.max(this.rateVerbs(), function(i) {
      return i.prob;
    });
  }

  // Split up a sentence into its general parts:
  // subject (most likely you),
  // verb, and
  // object
  this.getParts = function() {
    var parts = [];
    var words = this.getWords();

    // get the most likely verb (aka highest probability)
    var mostLikelyVerb = tis.getBestVerb();

    // is there even a verb in the sentence?
    if (mostLikelyVerb.prob === 0)
        mostLikelyVerb = {
          word: undefined,
          prob: 0,
          possibles: {}
        }

    // get our new verb's index, and from that determine subject and object
    index = words.indexOf(mostLikelyVerb.word);

    // in our case, a subject is defined as everything before the verb
    // for now, we don't really care about it, acctully
    // subject = words.slice(0, index);

    // likewise, an object is defined as everything after the verb
    object = words.slice(index+1);
    obj = new objectFragment(object);

    return {
      verb: mostLikelyVerb,
      object: condense( obj.getRequested() )
    };
  }

  /*
  where is the verb in the sentence?
  We are looking through each word in the sentence
  and ranking them from least likely to most likely
  */
  this.rateVerbs = function() {

    var allWords = this.getWords();

    // create data structure
    var words = _.map(allWords, function(w) {
      return {
        word: w,
        prob: 0,
        possibles: {
          tenses: [],
          meanings: []
        }
      }
    });

    // for each word
    _.each(words, function(word, index) {

      // look through patterns
      _.each(IDENT, function(identifier) {

        // the tests: this is where the probability is ranked
        if ( wV.validateFilter(allWords, index, identifier) ) {
          // increment probability
          word.prob += identifier.then.weight || 1;
          identifier.then.tense && word.possibles.tenses.push(identifier.then.tense);
          identifier.then.means && word.possibles.meanings.push(identifier.then.means);
        }

      });

    });

    return words;
  }

  // remove punctuation
  this.dePunctuate = function() {
    _.each(['.', '!', '?'], function(a) {
      if ( S(self.snt).endsWith(a) )
        self.snt = self.snt.replace(a, '');
    });
  }

  /*
    split up sentence into words
  */
  this.getWords = function() {
    self.dePunctuate()
    return self.snt.split(' ');
  }

}

var tests = function(){

  // test phrases
  PHR = [
    "what is the time in london?",
    "time in london",
    "get me a beer"
  ]

  // test each one
  _.each(PHR, function(t) {
    console.log("========================", "\nphrase:", t);

    // output
    p = new phrase(t);
    pts = p.getParts();
    console.log(
      pts.verb.word,
      "->",
      pts.verb.possibles
    );
    console.log(pts.object)
  });
  console.log("========================");

}

if (require.main === module) {
  tests();
}
<|endoftext|>


<commit_before>var checkCSS    = require('airtight-css-lint');
var loaderUtils = require('loader-utils');
var assign      = require("object-assign");

function checkCSSLoader(input, options, webpack, callback) {
  var results = [];

  checkCSS(input, function (line, col, msg) {
    results.push([ 'Line ' + line + ':' + col + ' - ' + msg ]);
  });

  if (results.length) {
    for (var i = 0; i < results.length; i++){
      if (options.failTypeError) {
        webpack.emitError(results[i]);
      } else {
        webpack.emitWarning(results[i]);
      }
    }

    if (options.failTypeError && options.failOnError) {
      throw new Error("Airtight CSS Lint Error");
    }
  }

  if (callback) {
    callback(null, input);
  }
}

module.exports = function(input) {
  var options = assign(
    {
      failTypeError: true,    // Use warning if false
      failOnError: true       // Only applies to errors
    },
    loaderUtils.parseQuery(this.query)
  );

  this.cacheable();
  var callback = this.async();

  if (!callback) {
    checkCSSLoader(input, options, this);

    return input;
  } else {
    try {
      checkCSSLoader(input, options, this, callback);
    } catch(e) {
      callback(e);
    }
  }
}
<commit_msg>Add source map support<commit_after>var checkCSS    = require('airtight-css-lint');
var loaderUtils = require('loader-utils');
var assign      = require("object-assign");

function checkCSSLoader(source, options, webpack, map, callback) {
  var results = [];

  checkCSS(source, function (line, col, msg) {
    results.push([ 'Line ' + line + ':' + col + ' - ' + msg ]);
  });

  if (results.length) {
    for (var i = 0; i < results.length; i++){
      if (options.failTypeError) {
        webpack.emitError(results[i]);
      } else {
        webpack.emitWarning(results[i]);
      }
    }

    if (options.failTypeError && options.failOnError) {
      throw new Error("Airtight CSS Lint Error");
    }
  }

  if (callback) {
    callback(null, source, map);
  }
}

module.exports = function(source, map) {
  var options = assign(
    {
      failTypeError: true,    // Use warning if false
      failOnError: true       // Only applies to errors
    },
    loaderUtils.parseQuery(this.query)
  );

  if (map !== null && typeof map !== "string") {
		map = JSON.stringify(map);
	}

  this.cacheable();
  var callback = this.async();

  if (!callback) {
    checkCSSLoader(source, options, this, map);

    return source;
  } else {
    try {
      checkCSSLoader(source, options, this, map, callback);
    } catch(e) {
      callback(e);
    }
  }
}
<|endoftext|>


<commit_before>var levelup = require('levelup')
var sublevel = require('sublevelup')
var transaction = require('level-transactions')
var ginga = require('ginga')
var xtend = require('xtend')
var H = require('highland')
// var iterate = require('./iterate')
// var through = require('through2')
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter

var END = '\uffff'

var defaults = {
  db: process.browser ? require('leveldown') : require('level-js'),
  fields: { '*': true }
}
var override = {
  keyEncoding: 'utf8',
  valueEncoding: 'json'
}

// simpler ginga params middleware
function params () {
  var names = Array.prototype.slice.call(arguments)
  var len = names.length
  return function (ctx) {
    var l = Math.min(ctx.args.length, len)
    for (var i = 0; i < l; i++) ctx[names[i]] = ctx.args[i]
  }
}

function Levi (dir, opts) {
  if (!(this instanceof Levi)) return new Levi(dir, opts)
  opts = xtend(defaults, opts, override)

  var db = typeof dir === 'string' ?
    sublevel(levelup(dir, opts)) :
    sublevel(dir, opts)

  this.options = db.options
  this.store = db
  this.tokens = db.sublevel('tokens')
  this.tf = db.sublevel('tf')

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)

  // store: key -> value
  // tokens: key -> tokens
  // inverse index: token!key -> tf
}

inherits(Levi, EventEmitter)

Levi.fn = ginga(Levi.prototype)

Levi.fn.define('get', params('key'), function (ctx, done) {
  this.store.get(ctx.key, done)
})

Levi.fn.define('pipeline', params('value'), function (ctx) {
  ctx.tokens = []
}, function (ctx, done) {
  var counts = {}
  ctx.tokens.forEach(function (token) {
    counts[token] = (counts[token] || 0) + 1
  })
  done(null, {
    tokens: ctx.tokens,
    counts: counts
  })
})

// todo pipeline plugins:
// tokenizer
// stemmer
// stopwords filtering

function pre (ctx, next) {
  ctx.options = xtend(this.options, ctx.options)
  ctx.tx = transaction(this.store)
  ctx.on('end', function (err) {
    if (err) ctx.tx.rollback(err)
  })

  if (
    ctx.key === '' ||
    ctx.key === null ||
    ctx.key === undefined
  ) return next(new Error('Key required.'))
  ctx.key = String(ctx.key)
  next()
}

function clean (ctx, next) {
  var self = this
  ctx.tx.get(ctx.key, function (err, value) {
    if (err && !err.notFound) return next(err)
    if (!value) return next()
    if (!ctx.value) ctx.value = value
    ctx.tx.del(ctx.key)
    // delete all tfs that contains key
    ctx.tx.get(ctx.key, { prefix: self.tokens }, function (err, tokens) {
      if (err) return next(err)
      tokens.forEach(function (token) {
        ctx.tx.del(token + '!' + ctx.key, { prefix: self.tf })
      })
      next()
    })
  })
}

function index (ctx, next) {
  var self = this
  if (!ctx.value) return next(new Error('Value required.'))
  if (typeof ctx.value === 'string') {
    // string value pipeline no fields
    this.pipeline(ctx.value, function (err, result) {
      if (err) return next(err)
      var total = result.tokens.length
      var counts = result.counts
      for (var token in counts) {
        ctx.tx.put(
          token + '!' + ctx.key,
          counts[token] / total,
          { prefix: self.tf }
        )
      }
      ctx.tx.put(
        ctx.key,
        Object.keys(counts),
        { prefix: self.tokens }
      )
      next()
    })
  } else {
    // field based pipeline
    var fields = ctx.options.fields
    var tfs = {}
    H(Object.keys(ctx.value))
    .map(function (field) {
      return {
        name: field,
        value: ctx.value[field],
        boost: Number(fields[field] || fields['*'])
      }
    })
    .filter(function (field) {
      return field.boost
    })
    .map(H.wrapCallback(function (field, cb) {
      self.pipeline(field.value, function (err, result) {
        if (err) return cb(err)
        var total = result.tokens.length
        var counts = result.counts
        var boost = field.boost
        for (var token in counts) {
          tfs[token] = (tfs[token] || 0) + (counts[token] / total * boost)
        }
        cb(null, field.name)
      })
    }))
    .series()
    .collect()
    .pull(function (err, fields) {
      if (err) return next(err)
      for (var token in tfs) {
        ctx.tx.put(token + '!' + ctx.key, tfs[token], { prefix: self.tf })
      }
      ctx.tx.put(ctx.key, Object.keys(tfs), { prefix: self.tokens })
      next()
    })
  }
}

function write (ctx, done) {
  ctx.tx.commit(done)
}

Levi.fn.define('del', params('key', 'options'), pre, clean, write)
Levi.fn.define('put', params('key', 'value', 'options'), pre, clean, index, write)
Levi.fn.define('index', params('key', 'options'), pre, clean, index, write)

Levi.fn.define('rebuildIndex', function (ctx, done) {
  // todo stream through store and .index(key)
})

Levi.fn.createSearchStream =
Levi.fn.searchStream = function (q, opts) {
  opts = xtend(this.options, opts)
  var self = this
  var limit = Number(opts.limit) > 0 ? opts.limit : Infinity
  var values = opts.values !== false
  H([].concat(q))
  .map(H.wrapCallback(function (q, cb) {
    // tokenize query
    self.pipeline(q, function (err, result) {
      if (err) return cb(err)
      cb(null, result.tokens)
    })
  }))
  .series()
  .flatten()
  .map(function (token) {
    return H(self.tf.createReadStream({
      gt: token + '!',
      lt: token + '!' + END
    }))
  })
  .reduce1() // todo union and idf
  .series()
  .sortBy(function (a, b) {
    return b.score - a.score
  })
  .map(H.wrapCallback(function (doc, cb) {
    if (values) {
      self.get(doc.key, function (err, val) {
        if (err) return cb(err)
        doc.value = val
        cb(null, doc)
      })
    } else {
      cb(null, doc)
    }
  }))
  .take(limit)
}

Levi.fn.createLiveStream =
Levi.fn.liveStream = function (q, opts) {
  opts = xtend(this.options, opts)
}

module.exports = Levi
<commit_msg>preparing pipeline<commit_after>var levelup = require('levelup')
var sublevel = require('sublevelup')
var transaction = require('level-transactions')
var ginga = require('ginga')
var xtend = require('xtend')
var H = require('highland')
// var iterate = require('./iterate')
// var through = require('through2')
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter

var END = '\uffff'

var defaults = {
  db: process.browser ? require('leveldown') : require('level-js'),
  fields: { '*': true }
}
var override = {
  keyEncoding: 'utf8',
  valueEncoding: 'json'
}

// simpler ginga params middleware
function params () {
  var names = Array.prototype.slice.call(arguments)
  var len = names.length
  return function (ctx) {
    var l = Math.min(ctx.args.length, len)
    for (var i = 0; i < l; i++) ctx[names[i]] = ctx.args[i]
  }
}

function countTokens (tokens) {
  var counts = {}
  tokens.forEach(function (token) {
    counts[token] = (counts[token] || 0) + 1
  })
  return counts
}

function Levi (dir, opts) {
  if (!(this instanceof Levi)) return new Levi(dir, opts)
  opts = xtend(defaults, opts, override)

  var db = typeof dir === 'string' ?
    sublevel(levelup(dir, opts)) :
    sublevel(dir, opts)

  this.options = db.options
  this.store = db
  this.tokens = db.sublevel('tokens')
  this.tf = db.sublevel('tf')

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)

  // store: key -> value
  // tokens: key -> tokens
  // inverse index: token!key -> tf
}

inherits(Levi, EventEmitter)

Levi.fn = ginga(Levi.prototype)

Levi.fn.define('get', params('key'), function (ctx, done) {
  this.store.get(ctx.key, done)
})

Levi.fn.define('pipeline', params('value'), function (ctx) {
  ctx.tokens = []
}, function (ctx, done) {
  done(null, ctx.tokens)
})

// todo pipeline plugins:
// tokenizer
// stemmer
// stopwords filtering

function pre (ctx, next) {
  ctx.options = xtend(this.options, ctx.options)
  ctx.tx = transaction(this.store)
  ctx.on('end', function (err) {
    if (err) ctx.tx.rollback(err)
  })

  if (
    ctx.key === '' ||
    ctx.key === null ||
    ctx.key === undefined
  ) return next(new Error('Key required.'))
  ctx.key = String(ctx.key)
  next()
}

function clean (ctx, next) {
  var self = this
  ctx.tx.get(ctx.key, function (err, value) {
    if (err && !err.notFound) return next(err)
    if (!value) return next()
    if (!ctx.value) ctx.value = value
    ctx.tx.del(ctx.key)
    // delete all tfs that contains key
    ctx.tx.get(ctx.key, { prefix: self.tokens }, function (err, tokens) {
      if (err) return next(err)
      tokens.forEach(function (token) {
        ctx.tx.del(token + '!' + ctx.key, { prefix: self.tf })
      })
      next()
    })
  })
}

function index (ctx, next) {
  var self = this
  if (!ctx.value) return next(new Error('Value required.'))
  if (typeof ctx.value === 'string') {
    // string value pipeline no fields
    this.pipeline(ctx.value, function (err, tokens) {
      if (err) return next(err)
      var total = tokens.length
      var counts = countTokens(counts)
      for (var token in counts) {
        ctx.tx.put(
          token + '!' + ctx.key,
          counts[token] / total,
          { prefix: self.tf }
        )
      }
      ctx.tx.put(
        ctx.key,
        Object.keys(counts),
        { prefix: self.tokens }
      )
      next()
    })
  } else {
    // field based pipeline
    var fields = ctx.options.fields
    var tfs = {}
    H(Object.keys(ctx.value))
    .map(function (field) {
      return {
        name: field,
        value: ctx.value[field],
        boost: Number(fields[field] || fields['*'])
      }
    })
    .filter(function (field) {
      return field.boost
    })
    .map(H.wrapCallback(function (field, cb) {
      self.pipeline(field.value, function (err, tokens) {
        if (err) return cb(err)
        var total = tokens.length
        var counts = countTokens(counts)
        var boost = field.boost
        for (var token in counts) {
          tfs[token] = (tfs[token] || 0) + (counts[token] / total * boost)
        }
        cb(null, field.name)
      })
    }))
    .series()
    .collect()
    .pull(function (err, fields) {
      if (err) return next(err)
      for (var token in tfs) {
        ctx.tx.put(token + '!' + ctx.key, tfs[token], { prefix: self.tf })
      }
      ctx.tx.put(ctx.key, Object.keys(tfs), { prefix: self.tokens })
      next()
    })
  }
}

function write (ctx, done) {
  ctx.tx.commit(done)
}

Levi.fn.define('del', params('key', 'options'), pre, clean, write)
Levi.fn.define('put', params('key', 'value', 'options'), pre, clean, index, write)
Levi.fn.define('index', params('key', 'options'), pre, clean, index, write)

Levi.fn.define('rebuildIndex', function (ctx, done) {
  // todo stream through store and .index(key)
})

Levi.fn.createSearchStream =
Levi.fn.searchStream = function (q, opts) {
  opts = xtend(this.options, opts)
  var self = this
  var limit = Number(opts.limit) > 0 ? opts.limit : Infinity
  var values = opts.values !== false
  H([].concat(q))
  .map(H.wrapCallback(function (q, cb) {
    // tokenize query
    self.pipeline(q, function (err, tokens) {
      if (err) return cb(err)
      cb(null, tokens)
    })
  }))
  .series()
  .flatten()
  .map(function (token) {
    return H(self.tf.createReadStream({
      gt: token + '!',
      lt: token + '!' + END
    }))
  })
  .reduce1() // todo union and idf
  .series()
  .sortBy(function (a, b) {
    return b.score - a.score
  })
  .map(H.wrapCallback(function (doc, cb) {
    if (values) {
      self.get(doc.key, function (err, val) {
        if (err) return cb(err)
        doc.value = val
        cb(null, doc)
      })
    } else {
      cb(null, doc)
    }
  }))
  .take(limit)
}

Levi.fn.createLiveStream =
Levi.fn.liveStream = function (q, opts) {
  opts = xtend(this.options, opts)
}

module.exports = Levi
<|endoftext|>


<commit_before>/*
 * Latch NodeJS SDK
 * Copyright (C) 2014 Eleven Paths

 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

var crypto = require('crypto')
  , url = require('url')
  , https = require('https')
  , http = require('http')
  , config = require('./config')

var latch = {
    init: function(options) {
        if (!('appId' in options) || (!('secretKey' in options))) {
            throw(new Error('You need to specify both the appId and secretKey'));
        }

        if ((options.appId.length != 20) || (options.secretKey.length != 40)) {
            throw(new Error('Please check your appId and secretKey, they seem to be wrong'));
        }

        config.appId = options.appId;
        config.secretKey = options.secretKey;
        if ('hostname' in options) {
            config.API_HOST = url.parse(options.hostname);
        } else {
            config.API_HOST = url.parse(config.API_HOST);
        }
    },

    pairWithId: function(accountId, next) {
        _http("GET", config.API_PAIR_WITH_ID_URL + "/" + accountId, '', '', next);
    },

    pair: function(token, next) {
        _http("GET", config.API_PAIR_URL + "/" + token, '', '', next);
    },

    status: function(accountId, next) {
        _http("GET", config.API_CHECK_STATUS_URL + "/" + accountId, '', '', next);
    },

    operationStatus: function(accountId, operationId, next) {
        _http("GET", config.API_CHECK_STATUS_URL + "/" + accountId + "/op/" + operationId, '', '', next);
    },

    unpair: function(accountId, next) {
        _http("GET", config.API_UNPAIR_URL + "/" + accountId, '', '', next);
    },
};

module.exports = latch;

var signData = function (data) {
    if (data) {
        var hmac = crypto.createHmac('sha1', config.secretKey);
        hmac.setEncoding('base64');
        hmac.write(data);
        hmac.end();
        return hmac.read();
    } else {
        return '';
    }
}

var dateFormat = function (date, fstr, utc) {
  utc = utc ? 'getUTC' : 'get';
  return fstr.replace (/%[YmdHMS]/g, function (m) {
    switch (m) {
    case '%Y': return date[utc + 'FullYear'] (); // no leading zeros required
    case '%m': m = 1 + date[utc + 'Month'] (); break;
    case '%d': m = date[utc + 'Date'] (); break;
    case '%H': m = date[utc + 'Hours'] (); break;
    case '%M': m = date[utc + 'Minutes'] (); break;
    case '%S': m = date[utc + 'Seconds'] (); break;
    default: return m.slice (1); // unknown code, remove %
    }
    // add leading zero if required
    return ('0' + m).slice (-2);
  });
}

var _http = function(HTTPMethod, queryString, xHeaders, utc, next) {
    xHeaders = xHeaders || '';
    utc = utc || dateFormat(new Date (), config.UTC_STRING_FORMAT, true);

    var stringToSign = (HTTPMethod.toUpperCase().trim() + "\n" +
                    utc + "\n" +
                    xHeaders + "\n" +
                    queryString.trim());

    var authorizationHeader = config.AUTHORIZATION_METHOD + config.AUTHORIZATION_HEADER_FIELD_SEPARATOR +
                           config.appId + config.AUTHORIZATION_HEADER_FIELD_SEPARATOR + signData(stringToSign);

    var headers = {};
    headers[config.AUTHORIZATION_HEADER_NAME] = authorizationHeader;
    headers[config.DATE_HEADER_NAME] = utc;

    var options = {
        'hostname': config.API_HOST.hostname,
        'port':     config.API_HOST.port,
        'path':     queryString,
        'method':   HTTPMethod,
        'headers':  headers,
        'protocol': config.API_HOST.protocol
    };

    var latchResponse = '';

    var req = (options.protocol == 'http:' ? http : https).request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            latchResponse += chunk;
        });
        res.on('end', function() {
            try {
                var jsonresponse = JSON.parse(latchResponse);
            } catch (e) {
                next(new Error('problem with JSON parse: ' + e.message));
            }

            next(null, jsonresponse);
        });
    });

    req.on('error', function(e) {
        next(new Error('problem with request: ' + e.message));
    });

    req.end();
}<commit_msg>Added use strict<commit_after>/*
 * Latch NodeJS SDK
 * Copyright (C) 2014 Eleven Paths

 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

 "use strict";

var crypto = require('crypto')
  , url = require('url')
  , https = require('https')
  , http = require('http')
  , config = require('./config')

var latch = {
    init: function(options) {
        if (!('appId' in options) || (!('secretKey' in options))) {
            throw(new Error('You need to specify both the appId and secretKey'));
        }

        if ((options.appId.length != 20) || (options.secretKey.length != 40)) {
            throw(new Error('Please check your appId and secretKey, they seem to be wrong'));
        }

        config.appId = options.appId;
        config.secretKey = options.secretKey;
        if ('hostname' in options) {
            config.API_HOST = url.parse(options.hostname);
        } else {
            config.API_HOST = url.parse(config.API_HOST);
        }
    },

    pairWithId: function(accountId, next) {
        _http("GET", config.API_PAIR_WITH_ID_URL + "/" + accountId, '', '', next);
    },

    pair: function(token, next) {
        _http("GET", config.API_PAIR_URL + "/" + token, '', '', next);
    },

    status: function(accountId, next) {
        _http("GET", config.API_CHECK_STATUS_URL + "/" + accountId, '', '', next);
    },

    operationStatus: function(accountId, operationId, next) {
        _http("GET", config.API_CHECK_STATUS_URL + "/" + accountId + "/op/" + operationId, '', '', next);
    },

    unpair: function(accountId, next) {
        _http("GET", config.API_UNPAIR_URL + "/" + accountId, '', '', next);
    },
};

module.exports = latch;

var signData = function (data) {
    if (data) {
        var hmac = crypto.createHmac('sha1', config.secretKey);
        hmac.setEncoding('base64');
        hmac.write(data);
        hmac.end();
        return hmac.read();
    } else {
        return '';
    }
}

var dateFormat = function (date, fstr, utc) {
  utc = utc ? 'getUTC' : 'get';
  return fstr.replace (/%[YmdHMS]/g, function (m) {
    switch (m) {
    case '%Y': return date[utc + 'FullYear'] (); // no leading zeros required
    case '%m': m = 1 + date[utc + 'Month'] (); break;
    case '%d': m = date[utc + 'Date'] (); break;
    case '%H': m = date[utc + 'Hours'] (); break;
    case '%M': m = date[utc + 'Minutes'] (); break;
    case '%S': m = date[utc + 'Seconds'] (); break;
    default: return m.slice (1); // unknown code, remove %
    }
    // add leading zero if required
    return ('0' + m).slice (-2);
  });
}

var _http = function(HTTPMethod, queryString, xHeaders, utc, next) {
    xHeaders = xHeaders || '';
    utc = utc || dateFormat(new Date (), config.UTC_STRING_FORMAT, true);

    var stringToSign = (HTTPMethod.toUpperCase().trim() + "\n" +
                    utc + "\n" +
                    xHeaders + "\n" +
                    queryString.trim());

    var authorizationHeader = config.AUTHORIZATION_METHOD + config.AUTHORIZATION_HEADER_FIELD_SEPARATOR +
                           config.appId + config.AUTHORIZATION_HEADER_FIELD_SEPARATOR + signData(stringToSign);

    var headers = {};
    headers[config.AUTHORIZATION_HEADER_NAME] = authorizationHeader;
    headers[config.DATE_HEADER_NAME] = utc;

    var options = {
        'hostname': config.API_HOST.hostname,
        'port':     config.API_HOST.port,
        'path':     queryString,
        'method':   HTTPMethod,
        'headers':  headers,
        'protocol': config.API_HOST.protocol
    };

    var latchResponse = '';

    var req = (options.protocol == 'http:' ? http : https).request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            latchResponse += chunk;
        });
        res.on('end', function() {
            try {
                var jsonresponse = JSON.parse(latchResponse);
            } catch (e) {
                next(new Error('problem with JSON parse: ' + e.message));
            }

            next(null, jsonresponse);
        });
    });

    req.on('error', function(e) {
        next(new Error('problem with request: ' + e.message));
    });

    req.end();
}<|endoftext|>


<commit_before>'use strict';

var through = require('through2'),
    PluginError = require('gulp-util').PluginError,
    pluginName = 'gulp-remember', // name of our plugin for error logging purposes
    caches = {}, // will hold named file caches
    defaultName = '_default'; // name to give a cache if not provided

/**
 * Return a through stream that will:
 *   1. Remember all files that ever pass through it.
 *   2. Add all remembered files back into the stream when not present.
 * @param cacheName {string} Name to give your cache.
 *                           Caches with different names can know about different sets of files.
 */
function gulpRemember(cacheName) {
  var cache; // the files we've ever put our hands on in the current stream

  if (cacheName !== undefined && typeof cacheName !== 'number' && typeof cacheName !== 'string') {
    throw new PluginError(pluginName, 'Usage: require("gulp-remember")(name); where name is undefined, number or string');
  }
  cacheName = cacheName || defaultName; // maybe need to use a default cache
  caches[cacheName] = caches[cacheName] || {}; // maybe initialize the named cache
  cache = caches[cacheName];

  function transform(file, enc, callback) {
    cache[file.path] = file; // add file to our cache
    callback();
  }

  function flush(callback) {
    // add all files we've ever seen back into the stream
    for (var path in cache) {
      if (cache.hasOwnProperty(path)) {
        // check if this guy was seen yet
        this.push(cache[path]); // add this file back into the current stream
      }
    }
    callback();
  }

  return through.obj(transform, flush);
}

/**
 * Forget about a file.
 * @param cacheName {string} name of the cache from which to drop the file
 * @param path {string} path of the file to forget
 */
gulpRemember.forget = function (cacheName, path) {
  if (arguments.length === 1) {
    path = cacheName;
    cacheName = defaultName;
  }
  if (typeof cacheName !== 'number' && typeof cacheName !== 'string') {
    throw new PluginError(pluginName, 'Usage: require("gulp-remember").forget(cacheName, path); where cacheName is undefined, number or string and path is a string');
  }
  delete caches[cacheName][path];
};

module.exports = gulpRemember;<commit_msg>remove dead comment<commit_after>'use strict';

var through = require('through2'),
    PluginError = require('gulp-util').PluginError,
    pluginName = 'gulp-remember', // name of our plugin for error logging purposes
    caches = {}, // will hold named file caches
    defaultName = '_default'; // name to give a cache if not provided

/**
 * Return a through stream that will:
 *   1. Remember all files that ever pass through it.
 *   2. Add all remembered files back into the stream when not present.
 * @param cacheName {string} Name to give your cache.
 *                           Caches with different names can know about different sets of files.
 */
function gulpRemember(cacheName) {
  var cache; // the files we've ever put our hands on in the current stream

  if (cacheName !== undefined && typeof cacheName !== 'number' && typeof cacheName !== 'string') {
    throw new PluginError(pluginName, 'Usage: require("gulp-remember")(name); where name is undefined, number or string');
  }
  cacheName = cacheName || defaultName; // maybe need to use a default cache
  caches[cacheName] = caches[cacheName] || {}; // maybe initialize the named cache
  cache = caches[cacheName];

  function transform(file, enc, callback) {
    cache[file.path] = file; // add file to our cache
    callback();
  }

  function flush(callback) {
    // add all files we've ever seen back into the stream
    for (var path in cache) {
      if (cache.hasOwnProperty(path)) {
        this.push(cache[path]); // add this file back into the current stream
      }
    }
    callback();
  }

  return through.obj(transform, flush);
}

/**
 * Forget about a file.
 * @param cacheName {string} name of the cache from which to drop the file
 * @param path {string} path of the file to forget
 */
gulpRemember.forget = function (cacheName, path) {
  if (arguments.length === 1) {
    path = cacheName;
    cacheName = defaultName;
  }
  if (typeof cacheName !== 'number' && typeof cacheName !== 'string') {
    throw new PluginError(pluginName, 'Usage: require("gulp-remember").forget(cacheName, path); where cacheName is undefined, number or string and path is a string');
  }
  delete caches[cacheName][path];
};

module.exports = gulpRemember;<|endoftext|>


<commit_before>#!/usr/bin/env node

var pkg = require('./package.json');
var lib = require('./lib');
var program = require('commander');
var async = require('async');
var colors = require('colors');
var chalk = require('chalk');
var read = require('read');
var path = require('path');

async.auto(lib.flow, function(err, results) {

program
  .usage("[command] [options]")
  .version(pkg.version)
  .option('-t, --theme <theme name>', 'Specify theme for export or publish (modern, traditional, crisp)', 'flat')
  .option('-F, --force', 'Used by `publish` - bypasses schema testing.')
  .option('-f, --format <file type extension>', 'Used by `export`.')
  .option('-p, --port <port>', 'Used by `serve` (default: 4000)', 4000)
  .option('-s, --silent', 'Used by `serve` to tell it if open browser auto or not.', false);

  program
    .command('init')
    .description('Initialize a resume.json file')
    .action(function() {
      lib.init();
    });

  program
    .command('register')
    .description('Register an account at https://registry.jsonresume.org')
    .action(function() {
      lib.register(results.getResume);
    });

  program
    .command('login')
    .description('Stores a user session.')
    .action(function() {
      lib.login();
    });

  program
    .command('settings')
    .description('Change theme, change password, delete account.')
    .action(function() {
      lib.settings(results.getResume, program, results.getConfig);
    });

  // if validation does not pass type resume test
  program
    .command('test')
    .description('Schema validation test your resume.json')
    .action(function() {
      lib.test.validate(results.getResume, function(error, response) {
        error && console.log(response.message);
      });
    });

  program
    .command('export [fileName]')
    .description('Export locally to .html, .md or .pdf. Supply a --format <file format> flag and argument to specify export format.')
    .action(function(fileName) {
      lib.exportResume(results.getResume, fileName, program, function(err, fileName, format) {
        console.log(chalk.green('\nDone! Find your new', format, 'resume at:\n', path.resolve(process.cwd(), fileName)));
      });
    });

  program
    .command('publish')
    .description('Publish your resume to https://registry.jsonresume.org')
    .action(function() {
      lib.publish(results.getResume, program, results.getConfig);
    });

  program
    .command('serve')
    .description('Serve resume at http://localhost:4000/')
    .action(function() {
      lib.serve(program.port, program.theme, program.silent);
    });

  program.parse(process.argv);

  var validCommands = program.commands.map(function(cmd) {
    return cmd._name;
  });

  if (!program.args.length) {
    console.log('resume-cli:'.cyan, 'http://jsonresume.org', '\n');
    program.help();

  } else if (validCommands.indexOf(process.argv[2]) === -1) {
    console.log('Invalid argument:'.red, process.argv[2]);
    console.log('resume-cli:'.cyan, 'http://jsonresume.org', '\n');
    program.help();
  }
});

// every time you publish, theme is changed to default. need to keep current theme

// error handling on export wrong theme name server side
// prompt user session time.
// export, post to theme server.
// change theme to always use the server

// get rid of npm install warning: html to text, wrong node version
// get text converter working again

// version test on menu does not show
// publishing to non existent account error handling
// use jsonlint before schema tests run.
// run more tests on windows

// settings change theme errors if 'account does not exist errors' or resume does not exist.
// resume doesn't handle test errors on 'resume publish' properly.
// or resume test is not running before publish as it should
<commit_msg>add async pre-flow control flow file.<commit_after>#!/usr/bin/env node

var pkg = require('./package.json');
var lib = require('./lib');
var program = require('commander');
var async = require('async');
var colors = require('colors');
var chalk = require('chalk');
var read = require('read');
var path = require('path');

async.auto(lib['pre-flow'], function(err, results) {

  program
    .usage("[command] [options]")
    .version(pkg.version)
    .option('-t, --theme <theme name>', 'Specify theme for export or publish (modern, traditional, crisp)', 'flat')
    .option('-F, --force', 'Used by `publish` - bypasses schema testing.')
    .option('-f, --format <file type extension>', 'Used by `export`.')
    .option('-p, --port <port>', 'Used by `serve` (default: 4000)', 4000)
    .option('-s, --silent', 'Used by `serve` to tell it if open browser auto or not.', false);

  program
    .command('init')
    .description('Initialize a resume.json file')
    .action(function() {
      lib.init();
    });

  program
    .command('register')
    .description('Register an account at https://registry.jsonresume.org')
    .action(function() {
      lib.register(results.getResume);
    });

  program
    .command('login')
    .description('Stores a user session.')
    .action(function() {
      lib.login();
    });

  program
    .command('settings')
    .description('Change theme, change password, delete account.')
    .action(function() {
      lib.settings(results.getResume, program, results.getConfig);
    });

  program
    .command('test')
    .description('Schema validation test your resume.json')
    .action(function() {
      lib.test.validate(results.getResume, function(error, response) {
        error && console.log(response.message);
      });
    });

  program
    .command('export [fileName]')
    .description('Export locally to .html, .md or .pdf. Supply a --format <file format> flag and argument to specify export format.')
    .action(function(fileName) {
      lib.exportResume(results.getResume, fileName, program, function(err, fileName, format) {
        console.log(chalk.green('\nDone! Find your new', format, 'resume at:\n', path.resolve(process.cwd(), fileName)));
      });
    });

  program
    .command('publish')
    .description('Publish your resume to https://registry.jsonresume.org')
    .action(function() {
      lib.publish(results.getResume, program, results.getConfig);
    });

  program
    .command('serve')
    .description('Serve resume at http://localhost:4000/')
    .action(function() {
      lib.serve(program.port, program.theme, program.silent);
    });

  program.parse(process.argv);

  var validCommands = program.commands.map(function(cmd) {
    return cmd._name;
  });

  if (!program.args.length) {
    console.log('resume-cli:'.cyan, 'http://jsonresume.org', '\n');
    program.help();

  } else if (validCommands.indexOf(process.argv[2]) === -1) {
    console.log('Invalid argument:'.red, process.argv[2]);
    console.log('resume-cli:'.cyan, 'http://jsonresume.org', '\n');
    program.help();
  }

});
<|endoftext|>


<commit_before>'use strict';

const Wit = require('node-wit').Wit;
const Hapi = require('hapi');
const request = require('request');

const config = require('./config');
const witService = require('./app/services/wit');
const keepr = require('./app/services/keepr');

const server = new Hapi.Server();
const port = process.env.PORT || 3000;
const verifyToken = process.env.VERIFY_TOKEN || '';
const token = process.env.PAGE_TOKEN || '';

function sendTextMessage(sender, text) {
  let messageData = {
    text:text
  }
  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token:token},
    method: 'POST',
    json: {
      recipient: {id:sender},
      message: messageData,
    }
  }, (error, response, body) => {
    if (error) {
      console.log('Error sending message: ', error);
    } else if (response.body.error) {
      console.log('Error: ', response.body.error);
    }
  });
}

// Our bot actions
const actions = {
  say(sessionId, context, message, cb) {
    // Our bot has something to say!
    // Let's retrieve the Facebook user whose session belongs to
    const recipientId = sessions[sessionId].fbid;
    if (recipientId) {
      // Yay, we found our recipient!
      // Let's forward our bot response to her.
        // Let's give the wheel back to our bot
        //
        sendTextMessage(recipientId, 'This is the response from our Bot!');
        cb();
    } else {
      console.log('Oops! Couldn\'t find user for session:', sessionId);
      // Giving the wheel back to our bot
      cb();
    }
  },
  merge(sessionId, context, entities, message, cb) {
    console.log('entities');
    console.log(entities);
    let keyword = entities.keyword.value;
    if (keyword) {
      context.keyword = keyword;
    }
    cb(context);
  },
  error(sessionId, context, error) {
    console.log(error.message);
  },
  ['fetch_latest_news_by_keyword'](sessionId, context, cb) {
    console.log('fetching latest news by keyword');
    console.log(context);
  },
  ['fetch_latest_news'](sessionId, context, cb) {
    console.log('executing fetch_latest_news');
    const recipientId = sessions[sessionId].fbid;
    console.log(recipientId);
    if (recipientId) {

      keepr.latestNews().then((response) => {
        const firstBreakingNews = response.numbers[0].text;
        sendTextMessage(recipientId, firstBreakingNews);
        cb(context);
      });
    }
    console.log('No recipientId');
    cb(context);
  }
  // You should implement your custom actions here
  // See https://wit.ai/docs/quickstart
};

const witClient = new Wit(config.Wit.serverToken, actions);
server.connection({port: port});

server.start((err) => {
  if (err) {
    throw err;
  }
  console.log('Server running at:', server.info.uri);
});

const sessions = {};

const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

const getFirstMessagingEntry = (body) => {
  const val = body.object == 'page' &&
    body.entry &&
    Array.isArray(body.entry) &&
    body.entry.length > 0 &&
    body.entry[0] &&
    body.entry[0].id == config.Facebook.pageId &&
    body.entry[0].messaging &&
    Array.isArray(body.entry[0].messaging) &&
    body.entry[0].messaging.length > 0 &&
    body.entry[0].messaging[0]
    ;
  return val || null;
};

server.route([{
  method: 'GET',
  path: '/webhook',
  handler: (req, reply) => {
    if (req.query['hub.verify_token'] === verifyToken) {
      return reply(req.query['hub.challenge']);
    }
    return reply('Error, wrong validation token');
  }
}, {
  method: 'POST',
  path: '/webhook',
  handler: (req, reply) => {
    console.log('Get new message');
    const messaging = getFirstMessagingEntry(req.payload);
    console.log(messaging);
    if (messaging && messaging.message) {
      const msg = messaging.message.text;
      const sender = messaging.sender.id;
      const sessionId = findOrCreateSession(sender);

      witClient.runActions(sessionId, msg, sessions[sessionId].context,
          (error, context) => {
            if (error) {
              console.log(error);
            }

            sessions[sessionId].context = context;
          });
    }
    reply('Accepted').code(200)
  }
}
]);

<commit_msg>Add callback to fetch_latest_news_by_keyword<commit_after>'use strict';

const Wit = require('node-wit').Wit;
const Hapi = require('hapi');
const request = require('request');

const config = require('./config');
const witService = require('./app/services/wit');
const keepr = require('./app/services/keepr');

const server = new Hapi.Server();
const port = process.env.PORT || 3000;
const verifyToken = process.env.VERIFY_TOKEN || '';
const token = process.env.PAGE_TOKEN || '';

function sendTextMessage(sender, text) {
  let messageData = {
    text:text
  }
  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token:token},
    method: 'POST',
    json: {
      recipient: {id:sender},
      message: messageData,
    }
  }, (error, response, body) => {
    if (error) {
      console.log('Error sending message: ', error);
    } else if (response.body.error) {
      console.log('Error: ', response.body.error);
    }
  });
}

// Our bot actions
const actions = {
  say(sessionId, context, message, cb) {
    // Our bot has something to say!
    // Let's retrieve the Facebook user whose session belongs to
    const recipientId = sessions[sessionId].fbid;
    if (recipientId) {
      // Yay, we found our recipient!
      // Let's forward our bot response to her.
        // Let's give the wheel back to our bot
        //
        sendTextMessage(recipientId, 'Fetching...!');
        cb();
    } else {
      console.log('Oops! Couldn\'t find user for session:', sessionId);
      // Giving the wheel back to our bot
      cb();
    }
  },
  merge(sessionId, context, entities, message, cb) {
    console.log('entities');
    console.log(entities);
    let keyword = entities.keyword.value;
    if (keyword) {
      context.keyword = keyword;
    }
    cb(context);
  },
  error(sessionId, context, error) {
    console.log(error.message);
  },
  ['fetch_latest_news_by_keyword'](sessionId, context, cb) {
    console.log('fetching latest news by keyword');
    console.log(context);
    cb(context);
  },
  ['fetch_latest_news'](sessionId, context, cb) {
    console.log('executing fetch_latest_news');
    const recipientId = sessions[sessionId].fbid;
    console.log(recipientId);
    if (recipientId) {

      keepr.latestNews().then((response) => {
        const firstBreakingNews = response.numbers[0].text;
        sendTextMessage(recipientId, firstBreakingNews);
        cb(context);
      });
    }
    console.log('No recipientId');
    cb(context);
  }
  // You should implement your custom actions here
  // See https://wit.ai/docs/quickstart
};

const witClient = new Wit(config.Wit.serverToken, actions);
server.connection({port: port});

server.start((err) => {
  if (err) {
    throw err;
  }
  console.log('Server running at:', server.info.uri);
});

const sessions = {};

const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

const getFirstMessagingEntry = (body) => {
  const val = body.object == 'page' &&
    body.entry &&
    Array.isArray(body.entry) &&
    body.entry.length > 0 &&
    body.entry[0] &&
    body.entry[0].id == config.Facebook.pageId &&
    body.entry[0].messaging &&
    Array.isArray(body.entry[0].messaging) &&
    body.entry[0].messaging.length > 0 &&
    body.entry[0].messaging[0]
    ;
  return val || null;
};

server.route([{
  method: 'GET',
  path: '/webhook',
  handler: (req, reply) => {
    if (req.query['hub.verify_token'] === verifyToken) {
      return reply(req.query['hub.challenge']);
    }
    return reply('Error, wrong validation token');
  }
}, {
  method: 'POST',
  path: '/webhook',
  handler: (req, reply) => {
    console.log('Get new message');
    const messaging = getFirstMessagingEntry(req.payload);
    console.log(messaging);
    if (messaging && messaging.message) {
      const msg = messaging.message.text;
      const sender = messaging.sender.id;
      const sessionId = findOrCreateSession(sender);

      witClient.runActions(sessionId, msg, sessions[sessionId].context,
          (error, context) => {
            if (error) {
              console.log(error);
            }

            sessions[sessionId].context = context;
          });
    }
    reply('Accepted').code(200)
  }
}
]);

<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var walk = require('jade-walk');

function error() {
  throw require('jade-error').apply(null, arguments);
}

module.exports = link;
function link(ast) {
  assert(ast.type === 'Block', 'The top level element should always be a block');
  var extendsNode = null;
  if (ast.nodes.length) {
    var hasExtends = ast.nodes[0].type === 'Extends';
    if (hasExtends) {
      extendsNode = ast.nodes.shift();
    }
    checkExtendPosition(ast, hasExtends);
  }
  ast = applyIncludes(ast);
  ast.declaredBlocks = findDeclaredBlocks(ast);
  if (extendsNode) {
    var mixins = [];
    var expectedBlocks = [];
    function addNode(node) {
      if (node.type === 'NamedBlock') {
        expectedBlocks.push(node.name);
      } else if (node.type === 'Block') {
        node.nodes.forEach(addNode);
      } else if (node.type === 'Mixin' && node.call === false) {
        mixins.push(node);
      } else {
        error('UNEXPECTED_NODES_IN_EXTENDING_ROOT', 'Only named blocks and mixins can appear at the top level of an extending template', node);
      }
    }
    ast.nodes.forEach(addNode);
    var parent = link(extendsNode.file.ast);
    extend(parent.declaredBlocks, ast);
    walk(parent, function (node) {
      if (node.type === 'NamedBlock') {
        expectedBlocks = expectedBlocks.filter(function (name) {
          return name !== node.name;
        });
      }
    });
    if (expectedBlocks.length !== 0) {
      //throw new Error('Unexpected blocks');
      expectedBlocks.forEach(function (expectedBlock) {
        console.warn('Warning: Unexpected block ' + expectedBlock.name + ' on line ' + expectedBlock.line + ' + of ' + expectedBlock.filename + '. This warning will be an error in v2.0.0');
      });
    }
    Object.keys(ast.declaredBlocks).forEach(function (name) {
      parent.declaredBlocks[name] = ast.declaredBlocks[name];
    });
    parent.nodes = mixins.concat(parent.nodes);
    return parent;
  }
  return ast;
}

function findDeclaredBlocks(ast) {
  var definitions = {};
  walk(ast, function before(node) {
    if (node.type === 'NamedBlock' && node.mode === 'replace') {
      definitions[node.name] = node;
    }
  });
  return definitions;
}
function extend(parentBlocks, ast) {
  var stack = {};
  walk(ast, function before(node) {
    if (node.type === 'NamedBlock') {
      if (stack[node.name] === node.name) {
        return node.ignore = true;
      }
      stack[node.name] = node.name;
      var parentBlock = parentBlocks[node.name];
      if (parentBlock) {
        if (parentBlock.parent) parentBlock = parentBlock.parent;
        node.parent = parentBlock;
        switch (node.mode) {
          case 'append':
            parentBlock.nodes = parentBlock.nodes.concat(node.nodes);
            break;
          case 'prepend':
            parentBlock.nodes = node.nodes.concat(parentBlock.nodes);
            break;
          case 'replace':
            parentBlock.nodes = node.nodes;
            break;
        }
      }
    }
  }, function after(node) {
    if (node.type === 'NamedBlock' && !node.ignore) {
      delete stack[node.name];
    }
  });
}
function applyIncludes(ast, child) {
  return walk(ast, function before(node) {

  }, function after(node, replace) {
    if (node.type === 'Include') {
      if (node.filter) {
        replace({
          type: 'Filter',
          name: node.filter,
          block: {type: 'Block', nodes: [ {type: 'Text', val: node.file.str.replace(/\r/g, '')} ] },
          attrs: node.attrs,
          filename: node.fullPath
        });
      } else if (/\.jade$/.test(node.file.fullPath)) {
        replace(applyYield(link(node.file.ast), node.block));
      } else {
        replace({type: 'Text', val: node.file.str.replace(/\r/g, '')});
      }
    }
  });
}
function applyYield(ast, block) {
  if (!block || !block.nodes.length) return ast;
  var replaced = false;
  ast = walk(ast, null, function (node, replace) {
    if (node.type === 'Block' && node.yield === true) {
      replaced = true;
      node.nodes.push(block);
    }
  });
  function defaultYieldLocation(node) {
    var res = node;
    for (var i = 0; i < node.nodes.length; i++) {
      if (node.nodes[i].textOnly) continue;
      if (node.nodes[i].type === 'Block') {
        res = defaultYieldLocation(node.nodes[i]);
      } else if (node.nodes[i].block && node.nodes[i].block.nodes.length) {
        res = defaultYieldLocation(node.nodes[i].block);
      }
    }
    return res;
  }
  if (!replaced) {
    // todo: probably should deprecate this with a warning
    defaultYieldLocation(ast).nodes.push(block);
  }
  return ast;
}
function checkExtendPosition(ast, hasExtends) {
  var legitExtendsReached = false;
  walk(ast, function (node) {
    if (node.type === 'Extends') {
      if (hasExtends && !legitExtendsReached) {
        legitExtendsReached = true;
      } else {
        error('EXTENDS_NOT_FIRST', 'Declaration of template inheritance ("extends") should be the first thing in the file.', node);
      }
    }
  });
}
<commit_msg>Implement AST changes<commit_after>'use strict';

var assert = require('assert');
var walk = require('jade-walk');

function error() {
  throw require('jade-error').apply(null, arguments);
}

module.exports = link;
function link(ast) {
  assert(ast.type === 'Block', 'The top level element should always be a block');
  var extendsNode = null;
  if (ast.nodes.length) {
    var hasExtends = ast.nodes[0].type === 'Extends';
    if (hasExtends) {
      extendsNode = ast.nodes.shift();
    }
    checkExtendPosition(ast, hasExtends);
  }
  ast = applyIncludes(ast);
  ast.declaredBlocks = findDeclaredBlocks(ast);
  if (extendsNode) {
    var mixins = [];
    var expectedBlocks = [];
    function addNode(node) {
      if (node.type === 'NamedBlock') {
        expectedBlocks.push(node.name);
      } else if (node.type === 'Block') {
        node.nodes.forEach(addNode);
      } else if (node.type === 'Mixin' && node.call === false) {
        mixins.push(node);
      } else {
        error('UNEXPECTED_NODES_IN_EXTENDING_ROOT', 'Only named blocks and mixins can appear at the top level of an extending template', node);
      }
    }
    ast.nodes.forEach(addNode);
    var parent = link(extendsNode.file.ast);
    extend(parent.declaredBlocks, ast);
    walk(parent, function (node) {
      if (node.type === 'NamedBlock') {
        expectedBlocks = expectedBlocks.filter(function (name) {
          return name !== node.name;
        });
      }
    });
    if (expectedBlocks.length !== 0) {
      //throw new Error('Unexpected blocks');
      expectedBlocks.forEach(function (expectedBlock) {
        console.warn('Warning: Unexpected block ' + expectedBlock.name + ' on line ' + expectedBlock.line + ' + of ' + expectedBlock.filename + '. This warning will be an error in v2.0.0');
      });
    }
    Object.keys(ast.declaredBlocks).forEach(function (name) {
      parent.declaredBlocks[name] = ast.declaredBlocks[name];
    });
    parent.nodes = mixins.concat(parent.nodes);
    return parent;
  }
  return ast;
}

function findDeclaredBlocks(ast) {
  var definitions = {};
  walk(ast, function before(node) {
    if (node.type === 'NamedBlock' && node.mode === 'replace') {
      definitions[node.name] = node;
    }
  });
  return definitions;
}
function extend(parentBlocks, ast) {
  var stack = {};
  walk(ast, function before(node) {
    if (node.type === 'NamedBlock') {
      if (stack[node.name] === node.name) {
        return node.ignore = true;
      }
      stack[node.name] = node.name;
      var parentBlock = parentBlocks[node.name];
      if (parentBlock) {
        if (parentBlock.parent) parentBlock = parentBlock.parent;
        node.parent = parentBlock;
        switch (node.mode) {
          case 'append':
            parentBlock.nodes = parentBlock.nodes.concat(node.nodes);
            break;
          case 'prepend':
            parentBlock.nodes = node.nodes.concat(parentBlock.nodes);
            break;
          case 'replace':
            parentBlock.nodes = node.nodes;
            break;
        }
      }
    }
  }, function after(node) {
    if (node.type === 'NamedBlock' && !node.ignore) {
      delete stack[node.name];
    }
  });
}
function applyIncludes(ast, child) {
  return walk(ast, function before(node) {

  }, function after(node, replace) {
    if (node.type === 'Include') {
      if (node.filter) {
        replace({
          type: 'Filter',
          name: node.filter,
          block: {type: 'Block', nodes: [ {type: 'Text', val: node.file.str.replace(/\r/g, '')} ] },
          attrs: node.attrs,
          filename: node.fullPath
        });
      } else if (/\.jade$/.test(node.file.fullPath)) {
        replace(applyYield(link(node.file.ast), node.block));
      } else {
        replace({type: 'Text', val: node.file.str.replace(/\r/g, '')});
      }
    }
  });
}
function applyYield(ast, block) {
  if (!block || !block.nodes.length) return ast;
  var replaced = false;
  ast = walk(ast, null, function (node, replace) {
    if (node.type === 'YieldBlock') {
      replaced = true;
      node.type = 'Block';
      node.nodes = [block];
    }
  });
  function defaultYieldLocation(node) {
    var res = node;
    for (var i = 0; i < node.nodes.length; i++) {
      if (node.nodes[i].textOnly) continue;
      if (node.nodes[i].type === 'Block') {
        res = defaultYieldLocation(node.nodes[i]);
      } else if (node.nodes[i].block && node.nodes[i].block.nodes.length) {
        res = defaultYieldLocation(node.nodes[i].block);
      }
    }
    return res;
  }
  if (!replaced) {
    // todo: probably should deprecate this with a warning
    defaultYieldLocation(ast).nodes.push(block);
  }
  return ast;
}
function checkExtendPosition(ast, hasExtends) {
  var legitExtendsReached = false;
  walk(ast, function (node) {
    if (node.type === 'Extends') {
      if (hasExtends && !legitExtendsReached) {
        legitExtendsReached = true;
      } else {
        error('EXTENDS_NOT_FIRST', 'Declaration of template inheritance ("extends") should be the first thing in the file.', node);
      }
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

require('neon');
require('krypton-orm');

var _ = require('lodash');
var Promise = require('bluebird');

var DomainContainer = Class({}, 'DomainContainer')({

  prototype: {

    _knex: null,
    _models: null,
    _modelExtras: null,
    presenters: null,
    props: null,

    init: function (initProps) {
      var that = this;

      if (_.isUndefined(initProps.knex)) {
        throw new Error('initProps.knex property is required');
      }

      that._knex = initProps.knex;

      if (_.isUndefined(initProps.models) || !_.isObject(initProps.models)) {
        throw new Error('initProps.models property is required and should be an object');
      }

      that._models = initProps.models;

      that._modelExtras = initProps.modelExtras || {};
      that.presenters = initProps.presenters || {};
      that.props = initProps.props || {};
    },

    query: function (modelName) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      return Model.query(that._knex);
    },

    create: function (modelName, body) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      var model = new Model(body);
      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.save(that._knex)
        .then(function () {
          return model;
        });
    },

    update: function (model, body) {
      var that = this;

      model.updateAttributes(body || {});

      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.save(that._knex)
        .then(function () {
          return model;
        });
    },

    destroy: function (model) {
      var that = this;

      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.destroy(that._knex)
        .then(function () {
          return model;
        });
    },

    get: function (modelName) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      var tmpMod = Module({}, 'ContainerTemporaryModule')({
        prototype: {
          _modelExtras: that._modelExtras,
          _container: that,
        },
      });

      var tmpModel = Class({}, modelName)
        .inherits(Model)
        .includes(tmpMod)
        ({});

      tmpModel.knex(that._knex);

      return tmpModel;
    },

    cleanup: function () {
      var that = this;

      return new Promise(function (resolve, reject) {
        that._knex.destroy(function () {
          resolve();
        });
      });
    },

  },

});

module.exports = DomainContainer;
<commit_msg>Update DomainContainer class according to spec<commit_after>'use strict';

require('neon');
require('krypton-orm');

var _ = require('lodash');
var Promise = require('bluebird');

var DomainContainer = Class({}, 'DomainContainer')({

  prototype: {

    _knex: null,
    _models: null,
    _modelExtras: null,
    presenters: null,
    props: null,

    init: function (initProps) {
      var that = this;

      if (_.isUndefined(initProps.knex)) {
        throw new Error('initProps.knex property is required');
      }

      that._knex = initProps.knex;

      if (_.isUndefined(initProps.models) || !_.isObject(initProps.models)) {
        throw new Error('initProps.models property is required and should be an object');
      }

      that._models = initProps.models;

      that._modelExtras = initProps.modelExtras || {};
      that.presenters = initProps.presenters || {};
      that.props = initProps.props || {};
    },

    query: function (modelName) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      return Model.query(that._knex);
    },

    create: function (modelName, body) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      var model = new Model(body);
      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.save(that._knex)
        .then(function () {
          return model;
        });
    },

    update: function (model, body) {
      var that = this;

      model.updateAttributes(body || {});

      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.save(that._knex)
        .then(function () {
          return model;
        });
    },

    destroy: function (model) {
      var that = this;

      model._modelExtras = that._modelExtras;
      model._container = that;

      return model.destroy(that._knex)
        .then(function () {
          return model;
        });
    },

    get: function (modelName) {
      var that = this;

      var Model = that._models[modelName];

      if (_.isUndefined(Model)) {
        return Promise.reject(new Error('Model ' + modelName + ' doesn\'t exist in the DomainContainer'));
      }

      var tmpMod = Module({}, 'ContainerTemporaryModule')({
        _modelExtras: that._modelExtras,
        _container: that,

        prototype: {
          _modelExtras: that._modelExtras,
          _container: that,
          _knex: that._knex,
        },
      });

      var tmpModel = Class({}, modelName)
        .inherits(Model)
        .includes(tmpMod)
        ({});

      tmpModel.knex(that._knex);

      return tmpModel;
    },

    cleanup: function () {
      var that = this;

      return new Promise(function (resolve, reject) {
        that._knex.destroy(function () {
          resolve();
        });
      });
    },

  },

});

module.exports = DomainContainer;
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var VersionChecker = require('ember-cli-version-checker');

module.exports = {
  name: 'ember-get-helper',

  init: function() {
    var checker = new VersionChecker(this);
    this._checkerForEmber = checker.for('ember', 'bower');
  },

  treeFor: function() {
    if (this._checkerForEmber.lt('2.0.0-beta.1')) {
      return this._super.treeFor.apply(this, arguments);
    } else {
      console.warn('ember-get-helper is not required for Ember 2.0.0 and later (a default `get` helper is included with Ember), please remove from your `package.json`.');
    }
  }
};
<commit_msg>Show warning only if being used directly in a project<commit_after>/* jshint node: true */
'use strict';

var VersionChecker = require('ember-cli-version-checker');

module.exports = {
  name: 'ember-get-helper',

  init: function() {
    var checker = new VersionChecker(this);
    this._checkerForEmber = checker.for('ember', 'bower');
  },

  treeFor: function() {
    if (this._checkerForEmber.lt('2.0.0-beta.1')) {
      return this._super.treeFor.apply(this, arguments);
    } else if (this.parent === this.project) {
      console.warn('ember-get-helper is not required for Ember 2.0.0 and later (a default `get` helper is included with Ember), please remove from your `package.json`.');
    }
  }
};
<|endoftext|>