<commit_before>let fs = require("fs")
export default class PHPAutoloader {
    /**
     * Build the object
     * @param {{[x: string]: string[]}} paths
     */
    constructor(paths) {
        this.paths = paths
    }
    /**
     * @type {{[x: string]: string[]}} Class name prefixes mapped to arrays of
     * paths. Each path should end with a /, and most prefixes will also.
     */
    get paths() {
        return this._paths
    }
    set paths(v) {
        this._paths = v
    }
    /**
     * Merges another autoloader into this one.
     * @param {PHPAutoloader} autoloader
     */
    add(autoloader) {
        this.paths = Object.assign(
            {},
            this.paths,
            autoloader.paths
        )
    }
    /**
     * Finds the filename that holds the class, if possible.
     * @param {string} class_name
     * @returns {?string}
     */
    findClassFile(name) {
        let canonical_class_name = name.replace(/^\\+/, "").replace(/_/g, '\\')
        let paths = Object.keys(this.paths)
        paths.sort((a, b) => b.length - a.length || a.localeCompare(b))
        for(let k of paths) {
            if(
                k.length < canonical_class_name.length &&
                k == canonical_class_name.substr(0, k.length)
            ) {
                let path_tail = canonical_class_name.substr(k.length).replace(/\\/g, "/") + ".php"
                let full_path = this.paths[k].map(
                    path => path + path_tail
                ).find(
                    path => fs.existsSync(path)
                )
                if(full_path) {
                    return full_path
                }
            }
        }
        return null
    }
}<commit_msg>Fix path merging<commit_after>let fs = require("fs")
export default class PHPAutoloader {
    /**
     * Build the object
     * @param {{[x: string]: string[]}} paths
     */
    constructor(paths) {
        this.paths = paths
    }
    /**
     * @type {{[x: string]: string[]}} Class name prefixes mapped to arrays of
     * paths. Each path should end with a /, and most prefixes will also.
     */
    get paths() {
        return this._paths
    }
    set paths(v) {
        this._paths = v
    }
    /**
     * Merges another autoloader into this one.
     * @param {PHPAutoloader} autoloader
     */
    add(autoloader) {
        for(var k in autoloader.paths) {
            this.paths[k] = (this.paths[k]||[]).concat(autoloader.paths[k])
        }
    }
    /**
     * Finds the filename that holds the class, if possible.
     * @param {string} class_name
     * @returns {?string}
     */
    findClassFile(name) {
        let canonical_class_name = name.replace(/^\\+/, "").replace(/_/g, '\\')
        let paths = Object.keys(this.paths)
        paths.sort((a, b) => b.length - a.length || a.localeCompare(b))
        for(let k of paths) {
            if(
                k.length < canonical_class_name.length &&
                k == canonical_class_name.substr(0, k.length)
            ) {
                let path_tail = canonical_class_name.substr(k.length).replace(/\\/g, "/") + ".php"
                let full_path = this.paths[k].map(
                    path => path + path_tail
                ).find(
                    path => fs.existsSync(path)
                )
                if(full_path) {
                    return full_path
                }
            }
        }
        return null
    }
}<|endoftext|>


<commit_before>'use strict'

$(function() {

	//
	// Helper function for plotting.
	//
	var plot = function (id, indexColumnName, dataFrame) {
		var index = dataFrame.getColumn(indexColumnName).getValues();
		var remainingColumns = dataFrame.dropColumn(indexColumnName).getColumns();

		var flotSeries = E.from(remainingColumns)
			.select(function (column) {
				var name = column.getName();
				var data = E.from(index)
					.zip(column.getValues(), function (index, value) {
						return [index, value];
					})
					.toArray();

				return {
					label: name,
					data: data,
				};
			})
			.toArray();

		$.plot(id, flotSeries);
	};

	//
	// Create a simple data frame.
	//
	var values = E
		.range(0, 14)
		.select(function (i) {
			return [i, Math.sin(i), Math.cos(i)];
		})
		.toArray();

	var dataFrame = new dataForge.DataFrame(["index", "Sin", "Cos"], values);

	//
	// Plot the data frame.
	//
	plot('#placeholder', "index", dataFrame);
});
<commit_msg>Removed LINQ dependency from example.<commit_after>'use strict'

$(function() {

	//
	// Helper function for plotting.
	//
	var plot = function (id, indexColumnName, dataFrame) {
		var index = dataFrame.getColumn(indexColumnName).getValues();
		var remainingColumns = dataFrame.dropColumn(indexColumnName).getColumns();

		var flotSeries = E.from(remainingColumns)
			.select(function (column) {
				var name = column.getName();
				var data = E.from(index)
					.zip(column.getValues(), function (index, value) {
						return [index, value];
					})
					.toArray();

				return {
					label: name,
					data: data,
				};
			})
			.toArray();

		$.plot(id, flotSeries);
	};

	//
	// Create a simple data frame.
	//
	var values = [];
	for (var i = 0; i < 14; ++i) {
		values.push([i, Math.sin(i), Math.cos(i)]);
	}

	var dataFrame = new dataForge.DataFrame(["index", "Sin", "Cos"], values);

	//
	// Plot the data frame.
	//
	plot('#placeholder', "index", dataFrame);
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var autoprefix = require('autoprefixer');
var rimraf = require('rimraf');
var webpack = require('webpack');
var webpackCfg = require('./webpack.conf.js');
var webpackProdCfg = require('./webpack.pord');
var webpackLibCfg = require('./webpack.modules');
var postcss = require('gulp-postcss');
var cssnano = require('cssnano');

var pkg = require('./package.json');
var spawn = require('child_process').spawn;

var postConfig = [
    autoprefix({
        browsers: ['last 2 versions', 'not ie < 8'],
        cascade: false,
    }),
    cssnano({
        reduceIdents: false, //不压缩keyframe名称
        safe: true
    }),
]

gulp.task('lib_build', ['dist_clean'], function (done) {
    webpack(webpackLibCfg, function (err, stats) {
        if (err) {
            console.log(err);
        } else {
            console.log('webpack log:' + stats.toString({
                hash: false,
                chunks: false,
                children: false,
            }));
            done();
        }
    })
});

gulp.task('dist_clean', function (done) {
    rimraf('./dist', {}, function () {
        done();
    });
})

gulp.task('js_build', ['js_clean'], function (done) {
  webpack(webpackCfg, function (err, stats) {
    if (err) {
      console.log(err);
    } else {
      console.log('webpack log:' + stats.toString({
        hash: false,
        chunks: false,
        children: false,
      }));
      done();
    }
  });
});

gulp.task('js_uglify', ['js_build'], function (done) {
    webpack(webpackProdCfg, function (err, stats) {
        if (err) {
            console.log(err);
        } else {
            console.log('webpack log:' + stats.toString({
                hash: false,
                chunks: false,
                children: false,
            }));
            done();
        }
    });
});

gulp.task('theme', ['theme_clean','copy_theme'], function (done) {
  gulp.src(['./style/index.scss'])
      .pipe(sass())
      .pipe(concat('tinper-bee.css'))
      .pipe(postcss(postConfig))
      .pipe(gulp.dest('./assets'))
      .on('end', function () {
        done();
      });
});

gulp.task('themePrefix', ['theme_clean'], function (done) {
  gulp.src(['./style/tinper-bee.scss'])
      .pipe(sass())
      .pipe(concat('tinper-bee.css'))
      .pipe(postcss(postConfig))
      .pipe(gulp.dest('./assets'))
      .on('end', function () {
        done();
      });
});

gulp.task('copy_theme',function(done){
  gulp.src('theme/tinper-bee-blue.css')
  .pipe(gulp.dest('assets/theme'))
  done();
});

gulp.task('js_clean', function (done) {
  rimraf('./build', {}, function () {
    done();
  });
});

gulp.task('theme_clean', function (done) {
  rimraf('./assets', {}, function () {
    done();
  });
});

gulp.task('update', function (done) {
    var depAry = [];
    for(var key in pkg.devDependencies){
        if(/bee-/.test(key)){
           depAry.push(key + '@' + pkg.devDependencies[key]);
        }
    }

    depAry.push('--production');

    depAry.forEach(function (item) {
        var runner = spawn('npm', ['update', '-d', item], {stdio: 'inherit'});
        runner.on('close', function (code) {
            console.log(code);
            done();
            console.log('done');
        })
    })

})

gulp.task('copy_clean', function (done) {
    rimraf('./lib/*.js', {}, function () {
      done();
    });
  });

gulp.task('copy', ['copy_clean'], function (done) {
    gulp.src([
            './node_modules/bee-table/build/lib/*.js',
            './node_modules/bee-table/build/render/*.js',
        ]).pipe(gulp.dest('./lib'));
})

// gulp.task('themePrefixcss', function (done) {
//   console.log("------themePrefixcss------");
//   return gulp.src('./style/component.scss')
//     .pipe(sass())
//   // .pipe(concat('tinper-bee.css'))
//     .pipe(cssWrap({
//         selector: '.custom-jonyshi' /* 添加的命名空间 */
//     }))
//     .pipe(cleanCSS())
//     .pipe(gulp.dest('src/themePrefixcss/')) /* 存放的目录 */
// });

// gulp.task('build', (done)=> {
//   if(pkg.prefix && pkg.prefix !== ""){
//     gulp.task('online', ['themePrefixcss']);
//   }else{
//     if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='online'){
//         gulp.task('online', ['theme']);
//     }else{
//         gulp.task('default', ['js_uglify', 'theme', 'lib_build', 'copy']);
//     }
//   }
// });

if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='online'){
    gulp.task('online', ['theme']);
}else if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='onlinePrefix'){
    gulp.task('onlinePrefix', ['themePrefix']);
}else{
    gulp.task('default', ['js_uglify', 'theme', 'lib_build', 'copy']);
}
<commit_msg> gulp<commit_after>var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var autoprefix = require('autoprefixer');
var rimraf = require('rimraf');
var webpack = require('webpack');
var webpackCfg = require('./webpack.conf.js');
var webpackProdCfg = require('./webpack.pord');
var webpackLibCfg = require('./webpack.modules');
var postcss = require('gulp-postcss');
var cssnano = require('cssnano');

var pkg = require('./package.json');
var spawn = require('child_process').spawn;

var postConfig = [
    autoprefix({
        browsers: ['last 2 versions', 'not ie < 8'],
        cascade: false,
    }),
    cssnano({
        reduceIdents: false, //不压缩keyframe名称
        safe: true
    }),
]

gulp.task('lib_build', ['dist_clean'], function (done) {
    webpack(webpackLibCfg, function (err, stats) {
        if (err) {
            console.log(err);
        } else {
            console.log('webpack log:' + stats.toString({
                hash: false,
                chunks: false,
                children: false,
            }));
            done();
        }
    })
});

gulp.task('dist_clean', function (done) {
    rimraf('./dist', {}, function () {
        done();
    });
})

gulp.task('js_build', ['js_clean'], function (done) {
  webpack(webpackCfg, function (err, stats) {
    if (err) {
      console.log(err);
    } else {
      console.log('webpack log:' + stats.toString({
        hash: false,
        chunks: false,
        children: false,
      }));
      done();
    }
  });
});

gulp.task('js_uglify', ['js_build'], function (done) {
    webpack(webpackProdCfg, function (err, stats) {
        if (err) {
            console.log(err);
        } else {
            console.log('webpack log:' + stats.toString({
                hash: false,
                chunks: false,
                children: false,
            }));
            done();
        }
    });
});

gulp.task('theme', ['theme_clean'], function (done) {
  gulp.src(['./style/index.scss'])
      .pipe(sass())
      .pipe(concat('tinper-bee.css'))
      .pipe(postcss(postConfig))
      .pipe(gulp.dest('./assets'))
      .on('end', function () {
        done();
      });
});

gulp.task('themePrefix', ['theme_clean'], function (done) {
  gulp.src(['./style/tinper-bee.scss'])
      .pipe(sass())
      .pipe(concat('tinper-bee.css'))
      .pipe(postcss(postConfig))
      .pipe(gulp.dest('./assets'))
      .on('end', function () {
        done();
      });
});

gulp.task('copy_theme',function(done){
  gulp.src('theme/tinper-bee-blue.css')
  .pipe(gulp.dest('assets/theme'))
  .on('end', function () {
    done();
  });
});

gulp.task('js_clean', function (done) {
  rimraf('./build', {}, function () {
    done();
  });
});

gulp.task('theme_clean', function (done) {
  rimraf('./assets', {}, function () {
    done();
  });
});

gulp.task('update', function (done) {
    var depAry = [];
    for(var key in pkg.devDependencies){
        if(/bee-/.test(key)){
           depAry.push(key + '@' + pkg.devDependencies[key]);
        }
    }

    depAry.push('--production');

    depAry.forEach(function (item) {
        var runner = spawn('npm', ['update', '-d', item], {stdio: 'inherit'});
        runner.on('close', function (code) {
            console.log(code);
            done();
            console.log('done');
        })
    })

})

gulp.task('copy_clean', function (done) {
    rimraf('./lib/*.js', {}, function () {
      done();
    });
  });

gulp.task('copy', ['copy_clean'], function (done) {
    gulp.src([
            './node_modules/bee-table/build/lib/*.js',
            './node_modules/bee-table/build/render/*.js',
        ]).pipe(gulp.dest('./lib'));
})

// gulp.task('themePrefixcss', function (done) {
//   console.log("------themePrefixcss------");
//   return gulp.src('./style/component.scss')
//     .pipe(sass())
//   // .pipe(concat('tinper-bee.css'))
//     .pipe(cssWrap({
//         selector: '.custom-jonyshi' /* 添加的命名空间 */
//     }))
//     .pipe(cleanCSS())
//     .pipe(gulp.dest('src/themePrefixcss/')) /* 存放的目录 */
// });

// gulp.task('build', (done)=> {
//   if(pkg.prefix && pkg.prefix !== ""){
//     gulp.task('online', ['themePrefixcss']);
//   }else{
//     if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='online'){
//         gulp.task('online', ['theme']);
//     }else{
//         gulp.task('default', ['js_uglify', 'theme', 'lib_build', 'copy']);
//     }
//   }
// });

if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='online'){
    gulp.task('online', ['theme']);
}else if(gulp.env._&&gulp.env._.length>0&&gulp.env._[0]=='onlinePrefix'){
    gulp.task('onlinePrefix', ['themePrefix']);
}else{
    gulp.task('default', ['js_uglify', 'theme', 'lib_build', 'copy','copy_theme']);
}
<|endoftext|>


<commit_before>/* global cozy */
import { combineReducers } from 'redux'

// action types
const REGISTER_SCHEMAS = 'REGISTER_SCHEMAS'
const GET_OR_CREATE_INDEX = 'GET_OR_CREATE_INDEX'
const FETCH_DOCUMENTS = 'FETCH_DOCUMENTS'
const RECEIVE_DATA = 'RECEIVE_DATA'
const RECEIVE_ERROR = 'RECEIVE_ERROR'

// reducers
const schemas = (state = {}, action) => {
  switch (action.type) {
    case REGISTER_SCHEMAS:
      return Object.assign({}, state, action.schemas)
    case GET_OR_CREATE_INDEX:
      return {
        ...state,
        [action.doctype]: Object.assign({}, state[action.doctype], { index: action.index })
      }
    default:
      return state
  }
}

const entities = (state = {}, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      return {
        ...state,
        [action.doctype]: Object.assign({}, state[action.doctype], objectifyEntitiesArray(action.response.data))
      }
    default:
      return state
  }
}

// endpoint reducers
const type = (state = null, action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
      return action.doctype
    default:
      return state
  }
}

const fetchStatus = (state = 'pending', action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
      return 'loading'
    case RECEIVE_DATA:
      return 'loaded'
    case RECEIVE_ERROR:
      return 'failed'
    default:
      return state
  }
}

const lastFetch = (state = null, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      return Date.now()
    default:
      return state
  }
}

const hasMore = (state = false, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      return action.next !== undefined ? action.next : state
    default:
      return state
  }
}

const count = (state = 0, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      const response = action.response
      return response.meta && response.meta.count ? response.meta.count : response.data.length
    default:
      return state
  }
}

const ids = (state = [], action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      return [
        ...state,
        ...action.response.data.map(doc => doc.id)
      ]
    default:
      return state
  }
}

const endpoint = combineReducers({
  type,
  fetchStatus,
  lastFetch,
  hasMore,
  count,
  ids
})

const endpoints = (state = {}, action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
    case RECEIVE_DATA:
    case RECEIVE_ERROR:
      const endpointKey = action.doctype
      return Object.assign({}, state, { [endpointKey]: endpoint(state[endpointKey] || {}, action) })
    default:
      return state
  }
}

export default combineReducers({
  schemas,
  entities,
  endpoints
})

// utils
const objectifyEntitiesArray = (entities) => {
  let obj = {}
  entities.forEach(entity => obj[entity.id] = entity)
  return obj
}

const mapEntitiesToIds = (entities, doctype, ids) => {
  return ids.map(id => entities[doctype][id])
}

// selectors
const getSchema = (state, doctype) => state.api.schemas[doctype]
const getIndex = (state, doctype) => getSchema(state, doctype).index

export const getEntities = (state, doctype, ids) => mapEntitiesToIds(state.api.entities, doctype, ids)

export const getEntityList = (state, doctype) => getEndpointList(state, doctype)

export const getEndpointList = (state, key) => {
  const list = state.api.endpoints[key]
  if (list !== undefined) {
    // TODO: replace entries by entities when withList() HOC is available
    return Object.assign({}, list, { entries: getEntities(state, list.type, list.ids) })
  }
  return list
}

// action creators
export const registerSchemas = (schemas) => (dispatch) => {
  dispatch({ type: REGISTER_SCHEMAS, schemas })
}

const getOrCreateIndex = (doctype) => async (dispatch, getState) => {
  let index = getIndex(getState(), doctype)
  if (!index) {
    const { fields } = getSchema(getState(), doctype)
    index = await cozy.client.data.defineIndex(doctype, fields)
    dispatch({ type: GET_OR_CREATE_INDEX, doctype, index })
  }
  return index
}

export const fetchDocuments = (doctype) => async (dispatch, getState) => {
  try {
    dispatch({ type: FETCH_DOCUMENTS, doctype })
    // WARN: cozy-client-js lacks a cozy.data.findAll method that uses this route
    const resp = await cozy.client.fetchJSON('GET', `/data/${doctype}/_all_docs?include_docs=true`)
    // WARN: the JSON response from the stack is not homogenous with other routes (offset? rows? total_rows?)
    // see https://github.com/cozy/cozy-stack/blob/master/docs/data-system.md#list-all-the-documents
    // WARN: looks like this route returns something looking like a couchDB design doc, we need to filter it:
    const rows = resp.rows.filter(row => !row.doc.hasOwnProperty('views'))
    // we forge a correct JSONAPI response:
    const docs = rows.map(row => Object.assign({}, row.doc, { id: row.id, type: doctype }))
    const JSONAPIresp = {
      data: docs,
      meta: { count: resp.total_rows },
      skip: resp.offset,
      next: false
    }
    dispatch({ type: RECEIVE_DATA, doctype, response: JSONAPIresp })
  } catch (error) {
    dispatch({ type: RECEIVE_ERROR, doctype, error })
  }
}
<commit_msg>[tech] Added handling of referenced files<commit_after>/* global cozy */
import { combineReducers } from 'redux'

const FILES_DOCTYPE = 'io.cozy.files'
const FETCH_LIMIT = 50

// action types
const REGISTER_SCHEMAS = 'REGISTER_SCHEMAS'
const GET_OR_CREATE_INDEX = 'GET_OR_CREATE_INDEX'
const FETCH_DOCUMENTS = 'FETCH_DOCUMENTS'
const FETCH_DOCUMENT = 'FETCH_DOCUMENT'
const FETCH_REFERENCED_FILES = 'FETCH_REFERENCED_FILES'
const RECEIVE_DATA = 'RECEIVE_DATA'
const RECEIVE_REFERENCED_FILES = 'RECEIVE_REFERENCED_FILES'
const RECEIVE_ERROR = 'RECEIVE_ERROR'

// reducers
const schemas = (state = {}, action) => {
  switch (action.type) {
    case REGISTER_SCHEMAS:
      return Object.assign({}, state, action.schemas)
    case GET_OR_CREATE_INDEX:
      return {
        ...state,
        [action.doctype]: Object.assign({}, state[action.doctype], { index: action.index })
      }
    default:
      return state
  }
}

const entities = (state = {}, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
      return {
        ...state,
        [action.doctype]: Object.assign({}, state[action.doctype], objectifyEntitiesArray(action.response.data))
      }
    case RECEIVE_REFERENCED_FILES:
      return {
        ...state,
        [action.relationType]: Object.assign({}, state[action.relationType], objectifyEntitiesArray(action.response.data))
      }
    default:
      return state
  }
}

// endpoint reducers
const type = (state = null, action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
      return action.doctype
    case FETCH_REFERENCED_FILES:
      return action.relationType
    default:
      return state
  }
}

const fetchStatus = (state = 'pending', action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
    case FETCH_REFERENCED_FILES:
      return 'loading'
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
      return 'loaded'
    case RECEIVE_ERROR:
      return 'failed'
    default:
      return state
  }
}

const lastFetch = (state = null, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
      return Date.now()
    default:
      return state
  }
}

const hasMore = (state = false, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
      return action.next !== undefined ? action.next : state
    default:
      return state
  }
}

const count = (state = 0, action) => {
  switch (action.type) {
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
      const response = action.response
      return response.meta && response.meta.count ? response.meta.count : response.data.length
    default:
      return state
  }
}

const ids = (state = [], action) => {
  switch (action.type) {
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
      if (!action.skip) {
        return action.response.data.map(doc => doc.id)
      }
      return [
        ...state,
        ...action.response.data.map(doc => doc.id)
      ]
    default:
      return state
  }
}

const endpoint = combineReducers({
  type,
  fetchStatus,
  lastFetch,
  hasMore,
  count,
  ids
})

const endpoints = (state = {}, action) => {
  switch (action.type) {
    case FETCH_DOCUMENTS:
    case FETCH_REFERENCED_FILES:
    case RECEIVE_DATA:
    case RECEIVE_REFERENCED_FILES:
    case RECEIVE_ERROR:
      const entity = action.entity // for referenced files fetching
      const endpointKey = entity ? `${entity.type}/${entity.id}/${action.relationName}` : action.doctype
      return Object.assign({}, state, { [endpointKey]: endpoint(state[endpointKey] || {}, action) })
    default:
      return state
  }
}

export default combineReducers({
  schemas,
  entities,
  endpoints
})

// utils
const objectifyEntitiesArray = (entities) => {
  let obj = {}
  entities.forEach(entity => obj[entity.id] = entity)
  return obj
}

const mapEntitiesToIds = (entities, doctype, ids) => {
  if (!entities[doctype]) {
    return ids.map(() => null)
  }
  return ids.map(id => entities[doctype][id])
}

// selectors
const getSchema = (state, doctype) => state.api.schemas[doctype]
const getRelations = (state, doctype) => getSchema(state, doctype).relations || {}
const getIndex = (state, doctype) => getSchema(state, doctype).index

export const getEntity = (state, doctype, id) => getEntities(state, doctype, [id])[0]

export const getEntities = (state, doctype, ids) => mapEntitiesToIds(state.api.entities, doctype, ids)

export const getEntityList = (state, doctype) => getEndpointList(state, doctype)

export const getEndpointList = (state, key) => {
  const list = state.api.endpoints[key]
  if (list !== undefined) {
    // TODO: replace entries by entities when withList() HOC is available
    return Object.assign({}, list, { entries: getEntities(state, list.type, list.ids) })
  }
  return list
}

export const getReferencedFilesList = (state, doctype, id, relationName) => getEndpointList(state, `${doctype}/${id}/${relationName}`)

// action creators
export const registerSchemas = (schemas) => (dispatch) => {
  dispatch({ type: REGISTER_SCHEMAS, schemas })
}

const getOrCreateIndex = (doctype) => async (dispatch, getState) => {
  let index = getIndex(getState(), doctype)
  if (!index) {
    const { fields } = getSchema(getState(), doctype)
    index = await cozy.client.data.defineIndex(doctype, fields)
    dispatch({ type: GET_OR_CREATE_INDEX, doctype, index })
  }
  return index
}

export const fetchDocuments = (doctype) => async (dispatch, getState) => {
  try {
    dispatch({ type: FETCH_DOCUMENTS, doctype })
    // WARN: cozy-client-js lacks a cozy.data.findAll method that uses this route
    const resp = await cozy.client.fetchJSON('GET', `/data/${doctype}/_all_docs?include_docs=true`)
    // WARN: the JSON response from the stack is not homogenous with other routes (offset? rows? total_rows?)
    // see https://github.com/cozy/cozy-stack/blob/master/docs/data-system.md#list-all-the-documents
    // WARN: looks like this route returns something looking like a couchDB design doc, we need to filter it:
    const rows = resp.rows.filter(row => !row.doc.hasOwnProperty('views'))
    // we normalize the data (note that we add _type so that cozy.client.data.listReferencedFiles works...)
    const docs = rows.map(row => Object.assign({}, row.doc, { id: row.id, type: doctype, _type: doctype }))
    // if the doctype references files, we fetch these files IDs here (this is needed for albums)
    // in the future, if we define more complex relations with other doctypes, we may have to deal
    // with the retrieval of these association IDs here
    const relations = getRelations(getState(), doctype)
    for (let name in relations) {
      if (relations[name].type === FILES_DOCTYPE) {
        for (let doc of docs) {
          doc[name] = await cozy.client.data.listReferencedFiles(doc)
        }
      }
    }
    // we forge a correct JSONAPI response:
    const JSONAPIresp = {
      data: docs,
      meta: { count: resp.total_rows },
      skip: resp.offset,
      next: false
    }
    dispatch({ type: RECEIVE_DATA, doctype, response: JSONAPIresp })
  } catch (error) {
    dispatch({ type: RECEIVE_ERROR, doctype, error })
  }
}

const getOrFetchDocument = (doctype, id) => async (dispatch, getState) => {
  let doc = getEntity(getState(), doctype, id)
  if (!doc) {
    // TODO: handle fetch status & errors with specific reducers:
    // { entities: 'io.cozy.photos.albums': { entities: {...}, fetchStatuses: {...}, errors: {...} }}
    dispatch({ type: FETCH_DOCUMENT, doctype, id })
    doc = await cozy.client.data.find(doctype, id)
    // we normalize again...
    doc = Object.assign({}, doc, { id: doc._id, type: doc._type })
  }
  return doc
}

export const fetchDocument = (doctype, id, options) => async (dispatch, getState) => {
  try {
    const doc = await dispatch(getOrFetchDocument(doctype, id))
    if (options.include) {
      const relations = getRelations(getState(), doctype)
      for (let relationName of options.include) {
        const relationType = relations[relationName].type
        // TODO: we only handle files relations here
        if (relationType === FILES_DOCTYPE) {
          dispatch({ type: FETCH_REFERENCED_FILES, entity: doc, relationName, relationType })
          // WARN: the stack API is probably not ideal here: referencedFiles are in the 'included' property
          // (that should be used when fetching an entity AND its relations) and the 'data' property
          // only contains uplets { id, type }
          const { included, meta } = await cozy.client.data.fetchReferencedFiles(doc, { limit: FETCH_LIMIT })
          // we forge a standard response with a 'data' property
          const response = {
            data: included.map(file => Object.assign({}, file.attributes, { id: file.id, _id: file.id, links: file.links })),
            meta,
            next: meta.count > FETCH_LIMIT
          }
          dispatch({ type: RECEIVE_REFERENCED_FILES, entity: doc, relationName, relationType, response })
        }
      }
    }
  } catch (error) {
    dispatch({ type: RECEIVE_ERROR, doctype, id, error })
  }
}
<|endoftext|>


<commit_before>var gulp = require("gulp");
var sourcemaps = require("gulp-sourcemaps");
var babel = require("gulp-babel");
var dest = require('gulp-dest');
var mocha  = require('gulp-mocha');
var jshint = require('gulp-jshint');
var format = require('gulp-esformatter');
var semver = require('semver');
var version = require('node-version').long;
var doc = require('gulp-doxx');
var isNotHarmony = !semver.lt(version.toString(), '0.11.0');
if(!semver.lt(version.toString(), '0.11.0')){
      require("harmonize")(["harmony-generators"]);
}

gulp.task('format', function() {
  return gulp.src('./lib/**/**/*.js')
    .pipe(format(require('./esformatrc')))
    .pipe(gulp.dest(function(file){
      return file.base;
     }));
});

gulp.task("lib:entry", function () {
  return gulp.src('./lib/**/**/*.js')
    .pipe(jshint({esnext:true}))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'))
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write("./source maps/"))
    .pipe(gulp.dest(function(file){
      return file.base.replace('lib/','');
     }));
});

gulp.task('doc', function() {
  return gulp.src('./lib/index.js')
    .pipe(doc({
      title: 'gengojs-accept',
      urlPrefix: '/'
    }))
    .pipe(gulp.dest('docs'));
});

gulp.task('watch', function () {
    return gulp.watch('./lib/**/**/*.js', ['lib:entry']);
});
gulp.task('test', function() {
  if(!isNotHarmony)
    return gulp.src('./tests/**/**/*.js', {read: false})
          // gulp-mocha needs filepaths so you can't have any plugins before it
          .pipe(mocha())
          .once('end', function () {
            process.exit();
          });
   else return gulp.src([
      './tests/express/index.js',
      './tests/hapi/index.js'
     ], {read:false})
      .pipe(mocha())
      .once('end', function () {
        process.exit();
      });
});

gulp.task("default", ['format','lib:entry','doc','watch']);

gulp.task('build', ['format','lib:entry','doc','test']);<commit_msg>Fix<commit_after>var gulp = require("gulp");
var sourcemaps = require("gulp-sourcemaps");
var babel = require("gulp-babel");
var dest = require('gulp-dest');
var mocha  = require('gulp-mocha');
var jshint = require('gulp-jshint');
var format = require('gulp-esformatter');
var semver = require('semver');
var version = require('node-version').long;
var doc = require('gulp-doxx');
var isHarmony = !semver.lt(version.toString(), '0.11.0');
if(!semver.lt(version.toString(), '0.11.0')){
      require("harmonize")(["harmony-generators"]);
}

gulp.task('format', function() {
  return gulp.src('./lib/**/**/*.js')
    .pipe(format(require('./esformatrc')))
    .pipe(gulp.dest(function(file){
      return file.base;
     }));
});

gulp.task("lib:entry", function () {
  return gulp.src('./lib/**/**/*.js')
    .pipe(jshint({esnext:true}))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'))
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write("./source maps/"))
    .pipe(gulp.dest(function(file){
      return file.base.replace('lib/','');
     }));
});

gulp.task('doc', function() {
  return gulp.src('./lib/index.js')
    .pipe(doc({
      title: 'gengojs-accept',
      urlPrefix: '/'
    }))
    .pipe(gulp.dest('docs'));
});

gulp.task('watch', function () {
    return gulp.watch('./lib/**/**/*.js', ['lib:entry']);
});
gulp.task('test', function() {
  if(isHarmony)
    return gulp.src('./tests/**/**/*.js', {read: false})
          // gulp-mocha needs filepaths so you can't have any plugins before it
          .pipe(mocha())
          .once('end', function () {
            process.exit();
          });
   else return gulp.src([
      './tests/express/index.js',
      './tests/hapi/index.js'
     ], {read:false})
      .pipe(mocha())
      .once('end', function () {
        process.exit();
      });
});

gulp.task("default", ['format','lib:entry','doc','watch']);

gulp.task('build', ['format','lib:entry','doc','test']);<|endoftext|>


<commit_before>import {inject, noView, processContent, bindable, TargetInstruction} from 'aurelia-framework';

@noView
@processContent((compiler, resources, element, instruction) => {
  let html = element.innerHTML;
  if (html !== '') {
    instruction.template = html;
  }

  return true;
})
@inject(TargetInstruction)
export class AuCol {
  @bindable title;
  @bindable field;
  @bindable format;
  @bindable command;
  @bindable width;
  @bindable lockable;
  @bindable locked;
  template;

  constructor(targetInstruction) {
    this.template = targetInstruction.elementInstruction.template;
  }
}
<commit_msg>fix(grid): default format value<commit_after>import {inject, noView, processContent, bindable, TargetInstruction} from 'aurelia-framework';

@noView
@processContent((compiler, resources, element, instruction) => {
  let html = element.innerHTML;
  if (html !== '') {
    instruction.template = html;
  }

  return true;
})
@inject(TargetInstruction)
export class AuCol {
  @bindable title;
  @bindable field;
  @bindable format = '';
  @bindable command;
  @bindable width;
  @bindable lockable;
  @bindable locked;
  template;

  constructor(targetInstruction) {
    this.template = targetInstruction.elementInstruction.template;
  }
}
<|endoftext|>


<commit_before>var fs = require('fs');
var gulp = require('gulp');
var util = require('gulp-util');
var stylus = require('gulp-stylus');
var uglify = require('gulp-uglify');
var replace = require('gulp-replace');
var webpack = require('webpack-stream');
var sizereport = require('gulp-sizereport');
var autoprefixer = require('gulp-autoprefixer');
var browserSync = require('browser-sync').create();

var getVersion = function() {
    return JSON.parse(fs.readFileSync('./package.json').toString()).version;
};

var compile = function(isServeTask, done) {
    var options = {
        module: {
            preLoaders: [{
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'eslint-loader'
            }],
            loaders: [{
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader?optional[]=runtime&stage=0'
            }]
        }
    };

    if (isServeTask) {
        options.watch = true;
        options.devtool = 'inline-source-map';
        options.output = {
            filename: 'app.js'
        };
    } else {
        options.output = {
            filename: 'smooth-scrollbar.js',
            library: 'Scrollbar',
            libraryTarget: 'umd'
        };
    }

    return webpack(options, null, function(err, stats) {
        if (err) throw new util.PluginError('webpack', err);

        util.log('[webpack]', stats.toString({
            colors: util.colors.supportsColor,
            chunks: false,
            hash: false,
            version: false
        }));

        browserSync.reload();

        if (isServeTask) {
            isServeTask = false;
            done();
        }
    });
};

gulp.task('scripts:build', function(done) {
    return gulp.src('test/scripts/index.js')
        .pipe(compile(true, done))
        .pipe(replace(/<%= version %>/, getVersion()))
        .pipe(gulp.dest('build/'));
});

gulp.task('scripts:dist', function() {
    return gulp.src('src/index.js')
        .pipe(compile(false))
        .pipe(replace(/<%= version %>/, getVersion()))
        .pipe(uglify())
        .pipe(gulp.dest('build/'));
});

gulp.task('styles:build', function() {
    return gulp.src('test/styles/index.styl')
        .pipe(stylus())
        .pipe(autoprefixer('> 1%, last 2 versions, Firefox ESR, Opera 12.1, ie >= 10'))
        .pipe(gulp.dest('build/'))
        .pipe(browserSync.stream());
});

gulp.task('styles:dist', function() {
    return gulp.src('src/**/*.styl')
        .pipe(stylus())
        .pipe(autoprefixer('> 1%, last 2 versions, Firefox ESR, Opera 12.1, ie >= 10'))
        .pipe(gulp.dest('dist/'));
});

gulp.task('serve', ['scripts:build', 'styles:build'], function() {
    browserSync.init({
        server: ['./test', '.'],
        routes: {
            '/build': 'build',
            '/bower_components': 'bower_components'
        }
    });

    gulp.watch('test/styles/*.styl', ['styles:build']);
    gulp.watch('test/**/*.html').on('change', browserSync.reload);
});

gulp.task('dist', ['scripts:dist', 'styles:dist'], function() {
    return gulp.src('dist/**/*.*')
        .pipe(sizereport());
});

gulp.task('default', ['dist']);
<commit_msg>chore: update workflow<commit_after>var fs = require('fs');
var gulp = require('gulp');
var util = require('gulp-util');
var stylus = require('gulp-stylus');
var uglify = require('gulp-uglify');
var replace = require('gulp-replace');
var webpack = require('webpack-stream');
var sizereport = require('gulp-sizereport');
var autoprefixer = require('gulp-autoprefixer');
var browserSync = require('browser-sync').create();

var getVersion = function() {
    return JSON.parse(fs.readFileSync('./package.json').toString()).version;
};

var compile = function(isServeTask, done) {
    var options = {
        module: {
            preLoaders: [{
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'eslint-loader'
            }],
            loaders: [{
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader?optional[]=runtime&stage=0'
            }]
        }
    };

    if (isServeTask) {
        options.watch = true;
        options.devtool = 'inline-source-map';
        options.output = {
            filename: 'app.js'
        };
    } else {
        options.output = {
            filename: 'smooth-scrollbar.js',
            library: 'Scrollbar',
            libraryTarget: 'umd'
        };
    }

    return webpack(options, null, function(err, stats) {
        if (err) throw new util.PluginError('webpack', err);

        util.log('[webpack]', stats.toString({
            colors: util.colors.supportsColor,
            chunks: false,
            hash: false,
            version: false
        }));

        browserSync.reload();

        if (isServeTask) {
            isServeTask = false;
            done();
        }
    });
};

gulp.task('scripts:build', function(done) {
    return gulp.src('test/scripts/index.js')
        .pipe(compile(true, done))
        .pipe(replace(/<%= version %>/, getVersion()))
        .pipe(gulp.dest('build/'));
});

gulp.task('scripts:dist', function() {
    return gulp.src('src/index.js')
        .pipe(compile(false))
        .pipe(replace(/<%= version %>/, getVersion()))
        .pipe(uglify())
        .pipe(gulp.dest('dist/'));
});

gulp.task('styles:build', function() {
    return gulp.src('test/styles/index.styl')
        .pipe(stylus())
        .pipe(autoprefixer('> 1%, last 2 versions, Firefox ESR, Opera 12.1, ie >= 10'))
        .pipe(gulp.dest('build/'))
        .pipe(browserSync.stream());
});

gulp.task('styles:dist', function() {
    return gulp.src('src/style/*.styl')
        .pipe(stylus())
        .pipe(autoprefixer('> 1%, last 2 versions, Firefox ESR, Opera 12.1, ie >= 10'))
        .pipe(gulp.dest('dist/'));
});

gulp.task('serve', ['scripts:build', 'styles:build'], function() {
    browserSync.init({
        server: ['./test', '.'],
        routes: {
            '/build': 'build',
            '/bower_components': 'bower_components'
        }
    });

    gulp.watch('test/styles/*.styl', ['styles:build']);
    gulp.watch('test/**/*.html').on('change', browserSync.reload);
});

gulp.task('dist', ['scripts:dist', 'styles:dist'], function() {
    return gulp.src('dist/**/*.*')
        .pipe(sizereport());
});

gulp.task('default', ['dist']);
<|endoftext|>


<commit_before>define([
    'dojo/_base/declare',
    'dojo/store/Observable',
    'dijit/tree/ObjectStoreModel'
], function (declare, Observable, ObjectStoreModel) {

    var FileManagerModel = declare('sqleditor.models.FileManagerStoreModel', null, { });

    /**
     * Creates an Observable ObjectStoreModel.
     * @param {Memory || FileManagerStore} store The tree store.
     * @param {Object} rootQuery The root query for the tree store.
     * @returns {ObjectStoreModel} The ObjectStoreModel(Observable(store));
     */
    FileManagerModel.createModel = function (store, rootQuery) {

        FileManagerModel.model =  new ObjectStoreModel({
            store: new Observable(store),
            query: rootQuery,
            labelAttr: 'name',
            mayHaveChildren: function (node) {
                return (node.isDir);
            }
        });

        return FileManagerModel.model;
    };

    /**
     * Gets the file tree model. This model needs to be shared amongst
     * the file manager dialog and the file navigator in the main window.
     * @returns {ObjectStoreModel} The file manager tree model.
     */
    FileManagerModel.getModel = function () {
        if (!FileManagerModel.model) {
            FileManagerModel.createModel();
        }

        return FileManagerModel.model;
    };

    return FileManagerModel;
});
<commit_msg>Update FileManagerModel.js<commit_after>define([
    'dojo/_base/declare',
    'dojo/store/Observable',
    'dijit/tree/ObjectStoreModel'
], function (declare, Observable, ObjectStoreModel) {

    var FileManagerModel = declare('sqleditor.models.FileManagerStoreModel', null, { });

    /**
     * Creates an Observable ObjectStoreModel.
     * @param {Memory || FileManagerStore} store The tree store.
     * @param {Object} rootQuery The root query for the tree store.
     * @returns {ObjectStoreModel} The ObjectStoreModel(Observable(store));
     */
    FileManagerModel.createModel = function (store, rootQuery) {

        FileManagerModel.model =  new ObjectStoreModel({
            store: new Observable(store),
            query: rootQuery,
            labelAttr: 'name',
            mayHaveChildren: function (node) {
                return (node.isDir);
            }
        });

        return FileManagerModel.model;
    };

    /**
     * Gets the file tree model. This model needs to be shared amongst
     * the file manager dialog and the file navigator in the main window.
     * @returns {ObjectStoreModel} The file manager tree model.
     */
    FileManagerModel.getModel = function () {
        if (!FileManagerModel.model) {
            throw "Please initialize the model first with FileManagerModel.createModel(store, rootQuery)"
        }
    };

    return FileManagerModel;
});
<|endoftext|>


<commit_before>var dependencies = ['observeOnScope', '$http', 'rx', '$timeout', '$filter', '$window'];
var oselSearchDirective = function oselSearchDirective(observeOnScope, $http, rx, $timeout, $filter, $window) {
    return {
        templateUrl: 'templates/osel-search.html',
        scope: {
            options: '=oselSearch'
        },
        link: function ($scope, elem, attrs) {

            var DEFAULT_INPUT_BUFFER = 200; // use this if $scope.options.buffer is not set

            $scope.options = $scope.options || {};
            $scope.options.providers = $scope.options.providers || [];
            $scope.options.placeholder = $scope.options.hasOwnProperty('placeholder') ? $scope.options.placeholder : 'Start typing to search';

            $scope.searchResults = {};

            // turn $scope.options.providers into a hashmap, with provider.id as the keys
            $scope.searchProviders = $scope.options.providers.reduce(function (providerHashMap, provider) {
                providerHashMap[provider.id] = provider;
                return providerHashMap;
            }, {});

            // turn search provider JSON into an rx.Observable, with a URL including the search term
            var observableWithAJAXConfig = function observableWithAJAXConfig(provider, term) {
                var config = {
                    params: angular.copy(provider.params),
                    data: angular.copy(provider.data),
                    dataType: provider.dataType,
                    url: provider.url,
                    method: provider.method
                };

                // inject search term into params and data
                for (var k in config.params) {
                    config.params[k] = config.params[k].replace('%s', term);
                }
                for (k in config.data) {
                    config.data[k] = config.data[k].replace('%s', term);
                }

                return rx.Observable.fromPromise($http(config));
            };

            var observableFromFn = function observableFromFn(fn, term) {
                //return rx.Observable.fromCallback(fn)(term);

                return rx.Observable.create(function(observer) {
                    try {
                        observer.onNext(fn.call(this, term));
                        observer.onCompleted();
                    } catch (e) {
                        console.error( e);
                        observer.onError(e);
                    }
                });
            };

            var createProviderObservable = function createProviderObservable(provider, term) {
                // check if provider is 'function' type
                if (provider.hasOwnProperty('fn')) {
                    return observableFromFn(provider.fn, term);
                } else { // else assume provider is 'AJAX' type
                    return observableWithAJAXConfig(provider, term);
                }
            };

            // create an rx.Observable from the user input changes
            var throttledInput = observeOnScope($scope, 'searchInput').debounce($scope.options.buffer || DEFAULT_INPUT_BUFFER).map(function (e) {
                return e.newValue;
            }).distinctUntilChanged(); // ignore duplicate searches if value didn't change since last search

            // fire off requests to providers based on throttled search term
            throttledInput.filter(function (term) {
                // reset the search results for each provider whenever input changes
                $scope.options.providers.forEach(function (provider) {
                    $scope.searchResults[provider.id] = $scope.searchResults[provider.id] || {};
                    $scope.searchResults[provider.id].providerId = provider.id; // need to save the id because orderObjectBy changes Object into an Array
                    $scope.searchResults[provider.id].results = [];
                });

                // only search on 3+ characters
                return term && term.length && term.length > 2;
            }).subscribe(function (term) {

                var observables = $scope.options.providers.map(function(provider) {
                    $timeout(function() {
                        $scope.searchResults[provider.id].inProgress = true;
                        $scope.searchResults[provider.id].results = [];
                        $scope.searchResults[provider.id].error = undefined;
                        $scope.searchResults[provider.id].received = Infinity;
                    });

                    var providerObservable = createProviderObservable(provider, term);
                    providerObservable.providerId = provider.id;
                    providerObservable.term = term;
                    providerObservable.sent = new Date();
                    providerObservable.config = provider;
                    return providerObservable;
                });

                observables.forEach(function(providerObservable) {
                    providerObservable.subscribe(function (response) {

                        $timeout(function() {
                            // call tranformResponse function if provided
                            if (providerObservable.config.transformResponse) {
                                response = providerObservable.config.transformResponse.call(this,response);
                            }

                            // check that response is for the current search term
                            if ($scope.searchInput === providerObservable.term) {
                                $scope.searchResults[providerObservable.providerId].inProgress = false;
                                $scope.searchResults[providerObservable.providerId].results = response.results;
                                $scope.searchResults[providerObservable.providerId].error = "";
                                $scope.searchResults[providerObservable.providerId].sent = providerObservable.sent;
                                $scope.searchResults[providerObservable.providerId].received = new Date();

                                // changes made to scope, so tell angular to digest
                                if (!$scope.$$phase) {
                                    $scope.$digest();
                                }
                            } else {
                                // don't update the UI if the response is from a different search
                            }

                        });

                    }, function (error) {
                        $scope.searchResults[providerObservable.providerId].inProgress = false;
                        $scope.searchResults[providerObservable.providerId].results = [];
                        $scope.searchResults[providerObservable.providerId].error = error.data.error || error.data; // TODO check this logic with a real server error
                        $scope.searchResults[providerObservable.providerId].received = Infinity; // needs to be Infinity so that we can sort errors to the right
                        $scope.searchResults[providerObservable.providerId].sent = providerObservable.sent; // TODO check this is available

                    });
                });
            });

            // helper function which returns true when any results are available
            // ignores errors and inProgress, or empty results
            $scope.resultsAvailable = function resultsAvailable() {
                return $scope.options.providers.filter(function(provider) {
                    var sr = $scope.searchResults[provider.id];
                    return sr.inProgress || sr.error || sr.results.length > 0;

                }).length > 0;
            };

            // search results visible when false
            $scope.searchHidden = false;

            // hide the search results
            $scope.hideSearch = function hideSearch() {
                $scope.searchHidden = true;
            };

            // call onSelect function if provided.  Pass the hideSearch handler so the function may call it
            $scope.selectResult = function selectResult(result, cb) {
                if (cb) {
                    cb.call(null, result, $scope.hideSearch);
                }
            };

            // set focus to a specific search result.  Need to pass the providerId of the result so we can locate it in the DOM
            var focusResult = function focusResult(result, providerId) {
                var index = $scope.searchResults[providerId].results.indexOf(result);
                var searchResultDOM = elem.find('div[data-provider-id=\'' + providerId + '\'] .osel-search-result[data-search-result-index=\'' + index + '\']');
                searchResultDOM[0].focus();
            };

            // sets focus to the search input box, and puts cursor to the end of text
            var focusSearchInput = function focusSearchInput() {
                var input = elem.find('input.osel-search');
                input[0].focus();

                // use the selection properties
                if (input[0].selectionStart) {
                    $timeout(function() {
                        input[0].selectionStart = input[0].selectionEnd = input[0].value.length;
                    });
                } else {
                    // otherwise try this hack
                    $timeout(function() {
                        input.val(input.val());
                    });
                }
            };

            // keydown handler from the search input box
            $scope.keyFromInput = function keyFromInput($event) {
                if ($event.keyCode === 40) {

                    var orderedResults = $filter('orderObjectBy')($scope.searchResults, 'received').filter(function(e) {
                        return !e.error && !e.inProgress && e.results.length > 0;
                    });
                    try {
                        focusResult(orderedResults[0].results[0], orderedResults[0].providerId);
                    } catch (e) {}
                }
            };

            // helper function to find neighbouring search result of a given result
            // takes into account top/bottom and left/right (doesn't exceed length of list)
            var getNeighbour = function getNeighbour(searchResultElement, xOffset, yOffset) {
                // make the ordered array, as is displayed to the user
                var orderedResults = $filter('orderObjectBy')($scope.searchResults, 'received').filter(function(e) {
                    return !e.error && !e.inProgress && e.results.length > 0;
                });

                // create another array of only the provider IDs
                var orderedProviderIds = orderedResults.map(function(column) {
                    return column.providerId;
                });

                var currentProviderId = $(searchResultElement).attr('data-provider-id');
                var currentProviderIndex = orderedProviderIds.indexOf(currentProviderId);

                var neighbourProviderId = orderedProviderIds[currentProviderIndex + xOffset]; // add the offset to go left or right
                if (currentProviderIndex + xOffset < 0) {
                    neighbourProviderId = orderedProviderIds[0];
                } else if (currentProviderIndex + xOffset > orderedResults.length - 1) {
                    neighbourProviderId = orderedProviderIds[orderedResults.length - 1];
                } else if (orderedResults[neighbourProviderId] && (orderedResults[neighbourProviderId].inProgress || orderedResults[neighbourProviderId].error)) {
                    neighbourProviderId = currentProviderId;
                }

                var currentResultIndex = $window.parseInt($(searchResultElement).attr('data-search-result-index'));
                var neighbourResultIndex = currentResultIndex + yOffset;
                if (currentResultIndex + yOffset < 0) {
                    neighbourResultIndex = 0;
                } else if (currentResultIndex + yOffset > $scope.searchResults[neighbourProviderId].results.length - 1) {
                    neighbourResultIndex = $scope.searchResults[neighbourProviderId].results.length - 1;
                }

                return {
                    result: $scope.searchResults[neighbourProviderId].results[neighbourResultIndex],
                    providerId: neighbourProviderId
                };
            };

            // move up/down/left/right from current focused search result
            // also listen for enter/esc to select result or hide search results
            $scope.keyFromSearchResult = function keyFromSearchResult($event, result, providerId, onSelect) {

                var neighbour;

                if ($event.keyCode === 37) { // left
                    neighbour = getNeighbour($window.document.activeElement, -1, 0);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 39) { // right
                    neighbour = getNeighbour($window.document.activeElement, 1, 0);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 40) { // down
                    neighbour = getNeighbour($window.document.activeElement, 0, 1);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 38) { // up
                    if ($scope.searchResults[providerId].results.indexOf(result) === 0) {
                        focusSearchInput();
                    } else {
                        neighbour = getNeighbour($window.document.activeElement, 0, -1);
                        focusResult(neighbour.result, neighbour.providerId);
                    }
                } else if ($event.keyCode === 13) { // enter
                    $scope.selectResult(result, onSelect);
                } else if ($event.keyCode === 27) { // escape
                    $scope.searchHidden = true;
                }

                return neighbour;
            };

            // hide search resutls if user clicks outdside the searchbox or outside the search results
            $('html').on('click', function(event) {
                var el = $(event.target);
                if (!(el.closest('.osel-search').length || el.closest('.osel-search-results').length)) {
                    $timeout(function() {
                        $scope.searchHidden = true;
                    });
                }
            });

        }
    };
};
angular.module('osel-search').directive('oselSearch', dependencies.concat([oselSearchDirective]));
<commit_msg>code comments<commit_after>var dependencies = ['observeOnScope', '$http', 'rx', '$timeout', '$filter', '$window'];
var oselSearchDirective = function oselSearchDirective(observeOnScope, $http, rx, $timeout, $filter, $window) {
    return {
        templateUrl: 'templates/osel-search.html',
        scope: {
            options: '=oselSearch'
        },
        link: function ($scope, elem, attrs) {

            var DEFAULT_INPUT_BUFFER = 200; // use this if $scope.options.buffer is not set

            // ---------- variables setup start -----------
            $scope.options = $scope.options || {};
            $scope.options.providers = $scope.options.providers || [];
            $scope.options.placeholder = $scope.options.hasOwnProperty('placeholder') ? $scope.options.placeholder : 'Start typing to search';
            $scope.searchResults = {};

            // turn $scope.options.providers into a hashmap, with provider.id as the keys
            $scope.searchProviders = $scope.options.providers.reduce(function (providerHashMap, provider) {
                providerHashMap[provider.id] = provider;
                return providerHashMap;
            }, {});
            // ---------- variables setup end -----------

            // turn search provider JSON into an rx.Observable, with a URL including the search term
            var observableWithAJAXConfig = function observableWithAJAXConfig(provider, term) {
                var config = {
                    params: angular.copy(provider.params),
                    data: angular.copy(provider.data),
                    dataType: provider.dataType,
                    url: provider.url,
                    method: provider.method
                };

                // inject search term into params and data
                for (var k in config.params) {
                    config.params[k] = config.params[k].replace('%s', term);
                }
                for (k in config.data) {
                    config.data[k] = config.data[k].replace('%s', term);
                }

                return rx.Observable.fromPromise($http(config));
            };

            var observableFromFn = function observableFromFn(fn, term) {
                //return rx.Observable.fromCallback(fn)(term);

                return rx.Observable.create(function(observer) {
                    try {
                        observer.onNext(fn.call(this, term));
                        observer.onCompleted();
                    } catch (e) {
                        console.error( e);
                        observer.onError(e);
                    }
                });
            };

            var createProviderObservable = function createProviderObservable(provider, term) {
                // check if provider is 'function' type
                if (provider.hasOwnProperty('fn')) {
                    return observableFromFn(provider.fn, term);
                } else { // else assume provider is 'AJAX' type
                    return observableWithAJAXConfig(provider, term);
                }
            };

            // create an rx.Observable from the user input changes
            var throttledInput = observeOnScope($scope, 'searchInput').debounce($scope.options.buffer || DEFAULT_INPUT_BUFFER).map(function (e) {
                return e.newValue;
            }).distinctUntilChanged(); // ignore duplicate searches if value didn't change since last search

            // fire off requests to providers based on throttled search term
            throttledInput.filter(function (term) {
                // reset the search results for each provider whenever input changes
                $scope.options.providers.forEach(function (provider) {
                    $scope.searchResults[provider.id] = $scope.searchResults[provider.id] || {};
                    $scope.searchResults[provider.id].providerId = provider.id; // need to save the id because orderObjectBy changes Object into an Array
                    $scope.searchResults[provider.id].results = [];
                });

                // only search on 3+ characters
                return term && term.length && term.length > 2;
            }).subscribe(function (term) {

                var observables = $scope.options.providers.map(function(provider) {
                    $timeout(function() {
                        $scope.searchResults[provider.id].inProgress = true;
                        $scope.searchResults[provider.id].results = [];
                        $scope.searchResults[provider.id].error = undefined;
                        $scope.searchResults[provider.id].received = Infinity;
                    });

                    var providerObservable = createProviderObservable(provider, term);
                    providerObservable.providerId = provider.id;
                    providerObservable.term = term;
                    providerObservable.sent = new Date();
                    providerObservable.config = provider;
                    return providerObservable;
                });

                observables.forEach(function(providerObservable) {
                    providerObservable.subscribe(function (response) {

                        $timeout(function() {
                            // call tranformResponse function if provided
                            if (providerObservable.config.transformResponse) {
                                response = providerObservable.config.transformResponse.call(this,response);
                            }

                            // check that response is for the current search term
                            if ($scope.searchInput === providerObservable.term) {
                                $scope.searchResults[providerObservable.providerId].inProgress = false;
                                $scope.searchResults[providerObservable.providerId].results = response.results;
                                $scope.searchResults[providerObservable.providerId].error = "";
                                $scope.searchResults[providerObservable.providerId].sent = providerObservable.sent;
                                $scope.searchResults[providerObservable.providerId].received = new Date();

                                // changes made to scope, so tell angular to digest
                                if (!$scope.$$phase) {
                                    $scope.$digest();
                                }
                            } else {
                                // don't update the UI if the response is from a different search
                            }

                        });

                    }, function (error) {
                        $scope.searchResults[providerObservable.providerId].inProgress = false;
                        $scope.searchResults[providerObservable.providerId].results = [];
                        $scope.searchResults[providerObservable.providerId].error = error.data.error || error.data; // TODO check this logic with a real server error
                        $scope.searchResults[providerObservable.providerId].received = Infinity; // needs to be Infinity so that we can sort errors to the right
                        $scope.searchResults[providerObservable.providerId].sent = providerObservable.sent; // TODO check this is available

                    });
                });
            });

            // helper function which returns true when any results are available
            // ignores errors and inProgress, or empty results
            $scope.resultsAvailable = function resultsAvailable() {
                return $scope.options.providers.filter(function(provider) {
                    var sr = $scope.searchResults[provider.id];
                    return sr.inProgress || sr.error || sr.results.length > 0;

                }).length > 0;
            };

            // search results visible when false
            $scope.searchHidden = false;

            // hide the search results
            $scope.hideSearch = function hideSearch() {
                $scope.searchHidden = true;
            };

            // call onSelect function if provided.  Pass the hideSearch handler so the function may call it
            $scope.selectResult = function selectResult(result, cb) {
                if (cb) {
                    cb.call(null, result, $scope.hideSearch);
                }
            };

            // set focus to a specific search result.  Need to pass the providerId of the result so we can locate it in the DOM
            var focusResult = function focusResult(result, providerId) {
                var index = $scope.searchResults[providerId].results.indexOf(result);
                var searchResultDOM = elem.find('div[data-provider-id=\'' + providerId + '\'] .osel-search-result[data-search-result-index=\'' + index + '\']');
                searchResultDOM[0].focus();
            };

            // sets focus to the search input box, and puts cursor to the end of text
            var focusSearchInput = function focusSearchInput() {
                var input = elem.find('input.osel-search');
                input[0].focus();

                // use the selection properties
                if (input[0].selectionStart) {
                    $timeout(function() {
                        input[0].selectionStart = input[0].selectionEnd = input[0].value.length;
                    });
                } else {
                    // otherwise try this hack
                    $timeout(function() {
                        input.val(input.val());
                    });
                }
            };

            // keydown handler from the search input box
            $scope.keyFromInput = function keyFromInput($event) {
                if ($event.keyCode === 40) {

                    var orderedResults = $filter('orderObjectBy')($scope.searchResults, 'received').filter(function(e) {
                        return !e.error && !e.inProgress && e.results.length > 0;
                    });
                    try {
                        focusResult(orderedResults[0].results[0], orderedResults[0].providerId);
                    } catch (e) {}
                }
            };

            // helper function to find neighbouring search result of a given result
            // takes into account top/bottom and left/right (doesn't exceed length of list)
            var getNeighbour = function getNeighbour(searchResultElement, xOffset, yOffset) {
                // make the ordered array, as is displayed to the user
                var orderedResults = $filter('orderObjectBy')($scope.searchResults, 'received').filter(function(e) {
                    return !e.error && !e.inProgress && e.results.length > 0;
                });

                // create another array of only the provider IDs
                var orderedProviderIds = orderedResults.map(function(column) {
                    return column.providerId;
                });

                var currentProviderId = $(searchResultElement).attr('data-provider-id');
                var currentProviderIndex = orderedProviderIds.indexOf(currentProviderId);

                var neighbourProviderId = orderedProviderIds[currentProviderIndex + xOffset]; // add the offset to go left or right
                if (currentProviderIndex + xOffset < 0) {
                    neighbourProviderId = orderedProviderIds[0];
                } else if (currentProviderIndex + xOffset > orderedResults.length - 1) {
                    neighbourProviderId = orderedProviderIds[orderedResults.length - 1];
                } else if (orderedResults[neighbourProviderId] && (orderedResults[neighbourProviderId].inProgress || orderedResults[neighbourProviderId].error)) {
                    neighbourProviderId = currentProviderId;
                }

                var currentResultIndex = $window.parseInt($(searchResultElement).attr('data-search-result-index'));
                var neighbourResultIndex = currentResultIndex + yOffset;
                if (currentResultIndex + yOffset < 0) {
                    neighbourResultIndex = 0;
                } else if (currentResultIndex + yOffset > $scope.searchResults[neighbourProviderId].results.length - 1) {
                    neighbourResultIndex = $scope.searchResults[neighbourProviderId].results.length - 1;
                }

                return {
                    result: $scope.searchResults[neighbourProviderId].results[neighbourResultIndex],
                    providerId: neighbourProviderId
                };
            };

            // move up/down/left/right from current focused search result
            // also listen for enter/esc to select result or hide search results
            $scope.keyFromSearchResult = function keyFromSearchResult($event, result, providerId, onSelect) {

                var neighbour;

                if ($event.keyCode === 37) { // left
                    neighbour = getNeighbour($window.document.activeElement, -1, 0);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 39) { // right
                    neighbour = getNeighbour($window.document.activeElement, 1, 0);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 40) { // down
                    neighbour = getNeighbour($window.document.activeElement, 0, 1);
                    focusResult(neighbour.result, neighbour.providerId);

                } else if ($event.keyCode === 38) { // up
                    if ($scope.searchResults[providerId].results.indexOf(result) === 0) {
                        focusSearchInput();
                    } else {
                        neighbour = getNeighbour($window.document.activeElement, 0, -1);
                        focusResult(neighbour.result, neighbour.providerId);
                    }
                } else if ($event.keyCode === 13) { // enter
                    $scope.selectResult(result, onSelect);
                } else if ($event.keyCode === 27) { // escape
                    $scope.searchHidden = true;
                }

                return neighbour;
            };

            // hide search resutls if user clicks outdside the searchbox or outside the search results
            $('html').on('click', function(event) {
                var el = $(event.target);
                if (!(el.closest('.osel-search').length || el.closest('.osel-search-results').length)) {
                    $timeout(function() {
                        $scope.searchHidden = true;
                    });
                }
            });

        }
    };
};
angular.module('osel-search').directive('oselSearch', dependencies.concat([oselSearchDirective]));
<|endoftext|>


<commit_before>var angular = require('angular'),
    moduleName = 'wow.guild',
    mod = angular.module(moduleName, [
        require('../core/configuration')
    ]);

mod.provider('wowResource', function() {
    this.$get = ['$http', 'wowConfig', function($http, config) {
        var options = config.options;

        return {
            members: members
        };

        function getUrl(opts) {
            opts = opts ?  opts : options;
            return config.getUrl() + '/guild/' + opts.realm + '/' + opts.guild;
        }

        function getData(params, options) {
            var url = options ? getUrl(options) : getUrl();
            params = params ? params : {};

            angular.extend(params, {jsonp: 'JSON_CALLBACK'});

            return $http.jsonp(url, {
                params: params,
                cache: true
            })
        }

        function members() {
            return getData({fields: 'members'});
        }

    }]
});

module.exports = moduleName;
<commit_msg>feat(guild): implement logic<commit_after>var angular = require('angular'),
    moduleName = 'wow.guild',
    mod = angular.module(moduleName, [
        require('../core/configuration')
    ]);

module.exports = moduleName;

mod.provider('wowGuild', function() {
    this.$get = ['$http', 'wowConfig', function($http, config) {
        var options = config.options;

        return {
            members: members,
            news: news
        };

        function getUrl(opts) {
            opts = opts ?  opts : options;
            return config.getUrl() + '/guild/' + opts.realm + '/' + opts.guild;
        }

        function getData(params, options) {
            var url = options ? getUrl(options) : getUrl();
            params = params ? params : {};

            angular.extend(params, {jsonp: 'JSON_CALLBACK'});

            return $http.jsonp(url, {
                params: params,
                cache: true
            })
        }

        function members() {
            return getData({fields: 'members'});
        }

        function news() {
            return getData({fields: 'news'});
        }

    }]
});
<|endoftext|>


<commit_before>import {PluginError} from 'gulp-util';
import through from 'through2';
import path from 'path';
import {spawn} from 'child_process';
import childProcessData from 'child-process-data';
import {InputStream, CommonTokenStream} from 'antlr4';
import {ParseTreeWalker} from 'antlr4/tree';

const PLUGIN_NAME = 'gulp-antlr4';

export default function (_options) {
  checkJava();

  const options = formatOptions(_options);
  const parserDir = getParserDir(options);
  const mode = getMode(options);
  const ANTLR4 = getClasses(options);

  return through.obj(function (file, encoding, callback) {
    if (file.isNull()) {
      return callback(null, file);
    }

    if (file.isStream()) {
      this.emit('error', new PluginError(PLUGIN_NAME,
        'Streams not supported (yet)!'));
    } else if (file.isBuffer()) {
      const inputFile = file.history[0];

      switch (path.extname(inputFile)) {
      case '.g4':
        const args = ['org.antlr.v4.Tool', '-Dlanguage=JavaScript', '-o',
          parserDir];
        if (mode === 'visitor' || mode === 'both') {
          args.push('-visitor');
        }
        if (mode !== 'listener' && mode !== 'both') {
          args.push('-no-listener');
        }
        args.push(inputFile);
        return childProcessData(spawn('java', args))
        .then(() => {
          callback(null, file);
        }, err => {
          this.emit('error', new PluginError(PLUGIN_NAME, err));
          callback(null, file);
        });

      default:
        if (ANTLR4.isProperlySetup()) {
          const data = file.contents.toString('utf8');
          const chars = new InputStream(data, true);
          const lexer = new ANTLR4.Lexer(chars);
          const tokens = new CommonTokenStream(lexer);
          const parser = new ANTLR4.Parser(tokens);
          parser.buildParseTrees = true;
          const tree = parser[ANTLR4.rule]();

          switch (mode) {
          case 'tree':
            console.log(tree.toStringTree(parser.ruleNames));
            break;

          case 'listener':
            try {
              const walker = new ParseTreeWalker();
              const listener = new ANTLR4.Listener();
              walker.walk(listener, tree);
              console.log('');
            } catch (err) {
              this.emit('error', new PluginError(PLUGIN_NAME, err));
            }
            break;

          case 'visitor':
            try {
              const visitor = new ANTLR4.Visitor();

              Promise
                .resolve(visitor.visit(tree))
                .then(() => {
                  this.emit('finish');
                });

              return; // Don't use callback but rely on above Promise
              // to emit eventually the proper 'finish' event
            } catch (err) {
              this.emit('error', new _gulpUtil.PluginError(PLUGIN_NAME, err));
            }
            break;
          }
        }

        return callback(null, file);
      }
    }
  });
}

function checkJava () {
  const CLASSPATH = process.env.CLASSPATH;

  if (!CLASSPATH) {
    throw new PluginError(PLUGIN_NAME,
      new ReferenceError(`Environment variable CLASSPATH is not defined;
Java is not installed or is improperly set`));
  }

  // Not matching '~' as it is not understood by Java anyway
  const matchJar = CLASSPATH.match(
    /.*:((\d|\w|\/|-|_|\.)+antlr-\d+\.\d+-complete\.jar):.*/);

  if (matchJar === null) {
    throw new PluginError(PLUGIN_NAME,
      new ReferenceError(`Cannot find ANTLR4 .jar file;
It should appear in your CLASSPATH`));
  }
}

function formatOptions (options) {
  if (typeof options === 'string') {
    return {parserDir: options};
  }
  return typeof options === 'object' ? Object.assign({
    listenerDir: options.parserDir, // Default is same dir
    visitorDir: options.parserDir, // Default is same dir
  }, options) : {};
}

function getParserDir (options) {
  const {parserDir} = options;

  if (typeof parserDir !== 'string') {
    throw new PluginError(PLUGIN_NAME,
      new TypeError(`You must provide the directory where to write or read
     the generated lexing and parsing tools (option 'parserDir')`));
  }

  return parserDir;
}

function getMode (options) {
  const {mode, listener, visitor} = options;

  if (typeof mode !== 'string' && mode !== undefined) {
    throw new PluginError(PLUGIN_NAME,
      new TypeError(`Bad option: ${mode}`));
  }

  if (listener && visitor) {
    return 'both';
  }

  if (listener) {
    return 'listener';
  }

  if (visitor) {
    return 'visitor';
  }

  return mode || 'listener';
}

function getClasses (options) {
  const {grammar} = options;

  if (!grammar) {
    return {
      isProperlySetup () {
        return false;
      },
    };
  }

  return {
    rule: getRule(options),
    Lexer: getLexer(options),
    Parser: getParser(options),
    Listener: getListener(options),
    Visitor: getVisitor(options),
    isProperlySetup () {
      return true;
    },
  };
}

function getRule (options) {
  const {rule} = options;

  if (!rule) {
    throw new PluginError(PLUGIN_NAME,
      `Undefined starting rule (option 'rule')`);
  }

  return rule;
}

function getLexer (options) {
  const {grammar, parserDir} = options;
  const lexer = `${grammar}Lexer`;

  return requireAfresh(lexer, parserDir);
}

function getParser (options) {
  const {grammar, parserDir} = options;
  const parser = `${grammar}Parser`;

  return requireAfresh(parser, parserDir);
}

function getListener (options) {
  const {listener, listenerDir} = options;

  if (!listener) {
    return;
  }

  return requireAfresh(listener, listenerDir);
}

function getVisitor (options) {
  const {visitor, visitorDir} = options;

  if (!visitor) {
    return;
  }

  return requireAfresh(visitor, visitorDir);
}

function requireAfresh (name, dir) {
  // Convert relative to absolute path
  const base = process.cwd();
  const rel = path.relative(base, dir);
  const file = path.join(base, rel, name);

  // Don't cache parser files
  if (require.cache && require.cache[file]) {
    delete require.cache[file];
  }

  return require(file)[name];
}
<commit_msg>Fixed reemitted err for visitor<commit_after>import {PluginError} from 'gulp-util';
import through from 'through2';
import path from 'path';
import {spawn} from 'child_process';
import childProcessData from 'child-process-data';
import {InputStream, CommonTokenStream} from 'antlr4';
import {ParseTreeWalker} from 'antlr4/tree';

const PLUGIN_NAME = 'gulp-antlr4';

export default function (_options) {
  checkJava();

  const options = formatOptions(_options);
  const parserDir = getParserDir(options);
  const mode = getMode(options);
  const ANTLR4 = getClasses(options);

  return through.obj(function (file, encoding, callback) {
    if (file.isNull()) {
      return callback(null, file);
    }

    if (file.isStream()) {
      this.emit('error', new PluginError(PLUGIN_NAME,
        'Streams not supported (yet)!'));
    } else if (file.isBuffer()) {
      const inputFile = file.history[0];

      switch (path.extname(inputFile)) {
      case '.g4':
        const args = ['org.antlr.v4.Tool', '-Dlanguage=JavaScript', '-o',
          parserDir];
        if (mode === 'visitor' || mode === 'both') {
          args.push('-visitor');
        }
        if (mode !== 'listener' && mode !== 'both') {
          args.push('-no-listener');
        }
        args.push(inputFile);
        return childProcessData(spawn('java', args))
        .then(() => {
          callback(null, file);
        }, err => {
          this.emit('error', new PluginError(PLUGIN_NAME, err));
          callback(null, file);
        });

      default:
        if (ANTLR4.isProperlySetup()) {
          const data = file.contents.toString('utf8');
          const chars = new InputStream(data, true);
          const lexer = new ANTLR4.Lexer(chars);
          const tokens = new CommonTokenStream(lexer);
          const parser = new ANTLR4.Parser(tokens);
          parser.buildParseTrees = true;
          const tree = parser[ANTLR4.rule]();

          switch (mode) {
          case 'tree':
            console.log(tree.toStringTree(parser.ruleNames));
            break;

          case 'listener':
            try {
              const walker = new ParseTreeWalker();
              const listener = new ANTLR4.Listener();
              walker.walk(listener, tree);
              console.log('');
            } catch (err) {
              this.emit('error', new PluginError(PLUGIN_NAME, err));
            }
            break;

          case 'visitor':
            try {
              const visitor = new ANTLR4.Visitor();

              Promise
                .resolve(visitor.visit(tree))
                .then(() => {
                  this.emit('finish');
                });

              return; // Don't use callback but rely on above Promise
              // to emit eventually the proper 'finish' event
            } catch (err) {
              this.emit('error', new PluginError(PLUGIN_NAME, err));
            }
            break;
          }
        }

        return callback(null, file);
      }
    }
  });
}

function checkJava () {
  const CLASSPATH = process.env.CLASSPATH;

  if (!CLASSPATH) {
    throw new PluginError(PLUGIN_NAME,
      new ReferenceError(`Environment variable CLASSPATH is not defined;
Java is not installed or is improperly set`));
  }

  // Not matching '~' as it is not understood by Java anyway
  const matchJar = CLASSPATH.match(
    /.*:((\d|\w|\/|-|_|\.)+antlr-\d+\.\d+-complete\.jar):.*/);

  if (matchJar === null) {
    throw new PluginError(PLUGIN_NAME,
      new ReferenceError(`Cannot find ANTLR4 .jar file;
It should appear in your CLASSPATH`));
  }
}

function formatOptions (options) {
  if (typeof options === 'string') {
    return {parserDir: options};
  }
  return typeof options === 'object' ? Object.assign({
    listenerDir: options.parserDir, // Default is same dir
    visitorDir: options.parserDir, // Default is same dir
  }, options) : {};
}

function getParserDir (options) {
  const {parserDir} = options;

  if (typeof parserDir !== 'string') {
    throw new PluginError(PLUGIN_NAME,
      new TypeError(`You must provide the directory where to write or read
     the generated lexing and parsing tools (option 'parserDir')`));
  }

  return parserDir;
}

function getMode (options) {
  const {mode, listener, visitor} = options;

  if (typeof mode !== 'string' && mode !== undefined) {
    throw new PluginError(PLUGIN_NAME,
      new TypeError(`Bad option: ${mode}`));
  }

  if (listener && visitor) {
    return 'both';
  }

  if (listener) {
    return 'listener';
  }

  if (visitor) {
    return 'visitor';
  }

  return mode || 'listener';
}

function getClasses (options) {
  const {grammar} = options;

  if (!grammar) {
    return {
      isProperlySetup () {
        return false;
      },
    };
  }

  return {
    rule: getRule(options),
    Lexer: getLexer(options),
    Parser: getParser(options),
    Listener: getListener(options),
    Visitor: getVisitor(options),
    isProperlySetup () {
      return true;
    },
  };
}

function getRule (options) {
  const {rule} = options;

  if (!rule) {
    throw new PluginError(PLUGIN_NAME,
      `Undefined starting rule (option 'rule')`);
  }

  return rule;
}

function getLexer (options) {
  const {grammar, parserDir} = options;
  const lexer = `${grammar}Lexer`;

  return requireAfresh(lexer, parserDir);
}

function getParser (options) {
  const {grammar, parserDir} = options;
  const parser = `${grammar}Parser`;

  return requireAfresh(parser, parserDir);
}

function getListener (options) {
  const {listener, listenerDir} = options;

  if (!listener) {
    return;
  }

  return requireAfresh(listener, listenerDir);
}

function getVisitor (options) {
  const {visitor, visitorDir} = options;

  if (!visitor) {
    return;
  }

  return requireAfresh(visitor, visitorDir);
}

function requireAfresh (name, dir) {
  // Convert relative to absolute path
  const base = process.cwd();
  const rel = path.relative(base, dir);
  const file = path.join(base, rel, name);

  // Don't cache parser files
  if (require.cache && require.cache[file]) {
    delete require.cache[file];
  }

  return require(file)[name];
}
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var runSequence = require('run-sequence');

var tasks = fs.readdirSync('./gulp/').filter(function(task) {
  return /^(?!config)[\w_-]+\.js$/i.test(path.basename(task));
});

tasks.forEach(function(task) {
  require('./gulp/' + task);
});

gulp.task('qa', function() {
  runSequence(
    'phplint',
    ['phpcs', 'phpcs-fixer-test', 'phpmd', 'phpcpd']
  );
});

gulp.task('test',  function() {
  runSequence(
    'phplint',
    'phpunit'
  );
});

gulp.task('fix', ['phpcs-fixer']);

gulp.task('security', ['composer-outdated']);

gulp.task('build', ['test'], function() {
  console.log('Task ready to be implemented');
});

gulp.task('default', ['qa', 'test']);
<commit_msg>sequence<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var runSequence = require('run-sequence');

var tasks = fs.readdirSync('./gulp/').filter(function(task) {
  return /^(?!config)[\w_-]+\.js$/i.test(path.basename(task));
});

tasks.forEach(function(task) {
  require('./gulp/' + task);
});

gulp.task('qa', function() {
  runSequence(
    'phplint',
    ['phpcs', 'phpcs-fixer-test', 'phpmd', 'phpcpd']
  );
});

gulp.task('test',  function() {
  runSequence(
    'phplint',
    'phpunit'
  );
});

gulp.task('fix', function() {
  runSequence(
    'phplint',
    'phpcs-fixer'
  );
});

gulp.task('security', function() {
  runSequence(
    'phplint',
    'composer-outdated'
  );
});

gulp.task('build', ['test'], function() {
  console.log('Task ready to be implemented');
});

gulp.task('default', ['qa', 'test']);
<|endoftext|>