<commit_before>'use strict';

let bl = {
    "model": null,
    "soajs_service": null,
    "localConfig": null,

    "handleError": (soajs, errCode, err) => {
        if (err) {
            soajs.log.error(err);
        }
        return ({
            "code": errCode,
            "msg": bl.localConfig.errors[errCode] + ((err && errCode === 602) ? err.message : "")
        });
    },

    "mt": {
        "getModel": (soajs, options) => {
            let mongoCore = null;
            if (options && options.mongoCore)
                mongoCore = options.mongoCore;
            return new bl.model(soajs, bl.localConfig, mongoCore);
        },
        "closeModel": (modelObj) => {
            modelObj.closeConnection();
        }
    },

    "getGroups": (soajs, inputmaskData, options, cb) => {
        let modelObj = bl.mt.getModel(soajs, options);
        modelObj.getGroupsnull, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    },

    "getGroup": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.id;
        data.code = inputmaskData.code;
        modelObj.getGroup(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            if (!record) {
                return cb(bl.handleError(soajs, 420, err));
            }
            return cb(null, record);
        });
    },

    "add": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.name = inputmaskData.name;
        data.description = inputmaskData.description;
        data.config = inputmaskData.config;
        data.code = inputmaskData.code;
        data.tId = soajs.tenant.id;
        data.tCode = soajs.tenant.code;
        modelObj.add(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "deleteGroup": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.gId;
        modelObj.delete(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "edit": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.gId;
        data.name = inputmaskData.name;
        data.description = inputmaskData.description;
        data.config = inputmaskData.config;

        modelObj.edit(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "addEnvironments": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.allowedEnvironments = inputmaskData.environments;
        data.groups = inputmaskData.groups;
        modelObj.addAllowedEnvironments(data, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    },

    "addPackages": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.allowedPackages = inputmaskData.packages;
        data.groups = inputmaskData.groups;
        modelObj.addAllowedPackages(data, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    }

};

module.exports = bl;<commit_msg>fixed getGroups typo<commit_after>'use strict';

let bl = {
    "model": null,
    "soajs_service": null,
    "localConfig": null,

    "handleError": (soajs, errCode, err) => {
        if (err) {
            soajs.log.error(err);
        }
        return ({
            "code": errCode,
            "msg": bl.localConfig.errors[errCode] + ((err && errCode === 602) ? err.message : "")
        });
    },

    "mt": {
        "getModel": (soajs, options) => {
            let mongoCore = null;
            if (options && options.mongoCore)
                mongoCore = options.mongoCore;
            return new bl.model(soajs, bl.localConfig, mongoCore);
        },
        "closeModel": (modelObj) => {
            modelObj.closeConnection();
        }
    },

    "getGroups": (soajs, inputmaskData, options, cb) => {
        let modelObj = bl.mt.getModel(soajs, options);
        modelObj.getGroups(null, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    },

    "getGroup": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.id;
        data.code = inputmaskData.code;
        modelObj.getGroup(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            if (!record) {
                return cb(bl.handleError(soajs, 420, err));
            }
            return cb(null, record);
        });
    },

    "add": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.name = inputmaskData.name;
        data.description = inputmaskData.description;
        data.config = inputmaskData.config;
        data.code = inputmaskData.code;
        data.tId = soajs.tenant.id;
        data.tCode = soajs.tenant.code;
        modelObj.add(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "deleteGroup": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.gId;
        modelObj.delete(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "edit": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.id = inputmaskData.gId;
        data.name = inputmaskData.name;
        data.description = inputmaskData.description;
        data.config = inputmaskData.config;

        modelObj.edit(data, (err, record) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, record);
        });
    },

    "addEnvironments": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.allowedEnvironments = inputmaskData.environments;
        data.groups = inputmaskData.groups;
        modelObj.addAllowedEnvironments(data, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    },

    "addPackages": (soajs, inputmaskData, options, cb) => {
        if (!inputmaskData) {
            return cb(bl.handleError(soajs, 400, null));
        }
        let modelObj = bl.mt.getModel(soajs, options);
        let data = {};
        data.allowedPackages = inputmaskData.packages;
        data.groups = inputmaskData.groups;
        modelObj.addAllowedPackages(data, (err, records) => {
            bl.mt.closeModel(modelObj);
            if (err) {
                return cb(bl.handleError(soajs, 602, err));
            }
            return cb(null, records);
        });
    }

};

module.exports = bl;<|endoftext|>


<commit_before>'use strict';

/**
 * @license
 * Copyright SOAJS All Rights Reserved.
 *
 * Use of this source code is governed by an Apache license that can be
 * found in the LICENSE file at the root of this repository
 */

const soajsCoreModules = require('soajs');

let coreHasher = soajsCoreModules.hasher;

let bl = {
	"modelObj": null,
	"model": null,
	"soajs_service": null,
	"localConfig": null,

	"handleError": (soajs, errCode, err) => {
		if (err) {
			soajs.log.error(err);
		}
		return ({
			"code": errCode,
			"msg": bl.localConfig.errors[errCode] + ((err && errCode === 602) ? err.message : "")
		});
	},

	"mp": {
		"getModel": (soajs) => {
			let modelObj = bl.modelObj;
			if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) {
				let options = {
					"dbConfig": soajs.tenant.dbConfig,
					"index": soajs.tenant.id
				};
				modelObj = new bl.model(bl.soajs_service, options, null);
			}
			return modelObj;
		},
		"closeModel": (soajs, modelObj) => {
			if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) {
				modelObj.closeConnection();
			}
		}
	},

	"getUser": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}

		inputmaskData = inputmaskData || {};
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"username": inputmaskData.username
		};

		modelObj.getUser(data, (err, record) => {
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			if (record) {
				let hashConfig = {
					"hashIterations": bl.localConfig.hashIterations,
					"seedLength": bl.localConfig.seedLength
				};
				if (soajs.servicesConfig && soajs.servicesConfig.oauth) {
					if (soajs.servicesConfig.oauth.hashIterations && soajs.servicesConfig.oauth.seedLength) {
						hashConfig = {
							"hashIterations": soajs.servicesConfig.oauth.hashIterations,
							"seedLength": soajs.servicesConfig.oauth.seedLength
						};
					}
				}
				coreHasher.init(hashConfig);
				coreHasher.compare(inputmaskData.password, record.password, function (err, result) {
					if (err || !result) {
						return cb(bl.handleError(soajs, 413, err));
					}

					delete record.password;
					if (record.tId && soajs.tenant) {
						if (record.tId.toString() !== soajs.tenant.id) {
							return cb(bl.handleError(soajs, 403, null));
						}
					}
					if (record) {
						record.loginMode = inputmaskData.loginMode;
						record.id = record._id.toString();
					}
					return cb(null, record);
				});
			}
			else {
				return cb(bl.handleError(soajs, 401, null));
			}
		});
	},

	"deleteAccessToken": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"token": inputmaskData.token,
			"type": "accessToken"
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records);
		});
	},

	"deleteRefreshToken": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"token": inputmaskData.token,
			"type": "refreshToken"
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records);
		});
	},

	"deleteAllUserTokens": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		options.provision.getTenantOauth(soajs.tenant.id, (err, tenantOauth) => {
			soajs.tenantOauth = tenantOauth;

			let loginMode = bl.localConfig.loginMode;
			if (soajs && soajs.tenantOauth && soajs.tenantOauth.loginMode) {
				loginMode = soajs.tenantOauth.loginMode;
			}

			let data = {
				"user": {
					"loginMode": loginMode,
					"id": inputmaskData.userId
				}
			};
			let modelObj = bl.mp.getModel(soajs, options);
			modelObj.delete(data, (err, records) => {
				bl.mp.closeModel(soajs, modelObj);
				if (err) {
					return cb(bl.handleError(soajs, 602, err));
				}
				return cb(null, records);
			});
		});
	},

	"deleteAllClientTokens": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"clientId": inputmaskData.clientId
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records);
		});
	}

};

module.exports = bl;<commit_msg>fixed mongo delete return upon delete<commit_after>'use strict';

/**
 * @license
 * Copyright SOAJS All Rights Reserved.
 *
 * Use of this source code is governed by an Apache license that can be
 * found in the LICENSE file at the root of this repository
 */

const soajsCoreModules = require('soajs');

let coreHasher = soajsCoreModules.hasher;

let bl = {
	"modelObj": null,
	"model": null,
	"soajs_service": null,
	"localConfig": null,

	"handleError": (soajs, errCode, err) => {
		if (err) {
			soajs.log.error(err);
		}
		return ({
			"code": errCode,
			"msg": bl.localConfig.errors[errCode] + ((err && errCode === 602) ? err.message : "")
		});
	},

	"mp": {
		"getModel": (soajs) => {
			let modelObj = bl.modelObj;
			if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) {
				let options = {
					"dbConfig": soajs.tenant.dbConfig,
					"index": soajs.tenant.id
				};
				modelObj = new bl.model(bl.soajs_service, options, null);
			}
			return modelObj;
		},
		"closeModel": (soajs, modelObj) => {
			if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) {
				modelObj.closeConnection();
			}
		}
	},

	"getUser": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}

		inputmaskData = inputmaskData || {};
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"username": inputmaskData.username
		};

		modelObj.getUser(data, (err, record) => {
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			if (record) {
				let hashConfig = {
					"hashIterations": bl.localConfig.hashIterations,
					"seedLength": bl.localConfig.seedLength
				};
				if (soajs.servicesConfig && soajs.servicesConfig.oauth) {
					if (soajs.servicesConfig.oauth.hashIterations && soajs.servicesConfig.oauth.seedLength) {
						hashConfig = {
							"hashIterations": soajs.servicesConfig.oauth.hashIterations,
							"seedLength": soajs.servicesConfig.oauth.seedLength
						};
					}
				}
				coreHasher.init(hashConfig);
				coreHasher.compare(inputmaskData.password, record.password, function (err, result) {
					if (err || !result) {
						return cb(bl.handleError(soajs, 413, err));
					}

					delete record.password;
					if (record.tId && soajs.tenant) {
						if (record.tId.toString() !== soajs.tenant.id) {
							return cb(bl.handleError(soajs, 403, null));
						}
					}
					if (record) {
						record.loginMode = inputmaskData.loginMode;
						record.id = record._id.toString();
					}
					return cb(null, record);
				});
			}
			else {
				return cb(bl.handleError(soajs, 401, null));
			}
		});
	},

	"deleteAccessToken": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"token": inputmaskData.token,
			"type": "accessToken"
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records.result);
		});
	},

	"deleteRefreshToken": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"token": inputmaskData.token,
			"type": "refreshToken"
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records.result);
		});
	},

	"deleteAllUserTokens": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		options.provision.getTenantOauth(soajs.tenant.id, (err, tenantOauth) => {
			soajs.tenantOauth = tenantOauth;

			let loginMode = bl.localConfig.loginMode;
			if (soajs && soajs.tenantOauth && soajs.tenantOauth.loginMode) {
				loginMode = soajs.tenantOauth.loginMode;
			}

			let data = {
				"user": {
					"loginMode": loginMode,
					"id": inputmaskData.userId
				}
			};
			let modelObj = bl.mp.getModel(soajs, options);
			modelObj.delete(data, (err, records) => {
				bl.mp.closeModel(soajs, modelObj);
				if (err) {
					return cb(bl.handleError(soajs, 602, err));
				}
				return cb(null, records.result);
			});
		});
	},

	"deleteAllClientTokens": (soajs, inputmaskData, options, cb) => {
		if (!inputmaskData) {
			return cb(bl.handleError(soajs, 400, null));
		}
		let modelObj = bl.mp.getModel(soajs, options);
		let data = {
			"clientId": inputmaskData.clientId
		};
		modelObj.delete(data, (err, records) => {
			bl.mp.closeModel(soajs, modelObj);
			if (err) {
				return cb(bl.handleError(soajs, 602, err));
			}
			return cb(null, records.result);
		});
	}

};

module.exports = bl;<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const fullPath = path.resolve.bind(null, __dirname);

/**
 *
 */
module.exports = {
	entry: [
		'babel-polyfill',
		'whatwg-fetch',
		'./<%= props.jsPath %>/index',
		'./<%= props.cssPath %>/index.scss'
	],
	output: {
		path: fullPath('<%= props.distPath %>'),
		publicPath: '<%= props.distPath %>',
		filename: '<%= props.distJsName %>',
	},
	devtool: 'source-map',
	devServer: {
		historyApiFallback: true
	},
	module: {
		loaders: [
			{
				test: /\.js$/,
				include: fullPath('<%= props.jsPath %>'),
				loader: 'babel'
			},
			{
				test: /\.scss$/,
				include: fullPath('<%= props.cssPath %>'),
				loader: ExtractTextPlugin.extract('style', [
					'css?-url&sourceMap',
					'sass?sourceMap',
					'postcss'
				])
			}
		]
	},
	postcss: [
		autoprefixer()
	],
	plugins: [
		new ExtractTextPlugin('<%= props.distCssName %>', {
			allChunks: true
		})
	]
};
<commit_msg>Fixed autoprefixer config<commit_after>'use strict';

const path = require('path');
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const fullPath = path.resolve.bind(null, __dirname);

/**
 *
 */
module.exports = {
	entry: [
		'babel-polyfill',
		'whatwg-fetch',
		'./<%= props.jsPath %>/index',
		'./<%= props.cssPath %>/index.scss'
	],
	output: {
		path: fullPath('<%= props.distPath %>'),
		publicPath: '<%= props.distPath %>',
		filename: '<%= props.distJsName %>',
	},
	devtool: 'source-map',
	devServer: {
		historyApiFallback: true
	},
	module: {
		loaders: [
			{
				test: /\.js$/,
				include: fullPath('<%= props.jsPath %>'),
				loader: 'babel'
			},
			{
				test: /\.scss$/,
				include: fullPath('<%= props.cssPath %>'),
				loader: ExtractTextPlugin.extract('style', [
					'css?-url&sourceMap',
					'postcss',
					'sass?sourceMap'
				])
			}
		]
	},
	postcss: function(webpack) {
		return [
			autoprefixer({
				browsers: [
					'ie >= 8',
					'ie_mob >= 10',
					'ff >= 20',
					'chrome >= 34',
					'safari >= 7',
					'opera >= 23',
					'ios >= 7',
					'android >= 4.4',
					'bb >= 10'
				]
			})
		];
	},
	plugins: [
		new ExtractTextPlugin('<%= props.distCssName %>', {
			allChunks: true
		})
	]
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name        unlink.is
// @namespace   http://gmscript.gentoo.moe
// @include     https://twitter.com/*
// @version     0.2
// @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @downloadURL https://raw.githubusercontent.com/perillamint/unlink.is/master/unlinkis.js
// @updateURL   https://raw.githubusercontent.com/perillamint/unlink.is/master/unlinkis.meta.js
// @grant       GM_xmlhttpRequest
// @license     GPLv3 or later
// ==/UserScript==

//Caution: This parsing method is not code-change resist.
var jsblock_regex = /<script[^>]*>[\s\S]([.\s\S]*?)<\/script>/g;
var urlgrabber_regex = /longUrl:[ ]*"(.+?)"/;
var linkdata_obj_regex = /var LinkData/;

var linkis_detect = /(?:ln\.is|linkis\.com)\/\w+/;
var card_iframe_regex = /xdm_default\d+?_provider/;

//Caution: This url extractor WILL CRASH when twitter changes working method of t.co
var tco_url_extract_regex = /location\.replace\("(.*?)"\)/;
var tco_url_detect = /http(|s):\/\/t.co\/[^\/]*$/;

function get_jsblock(str) {
  var match = str.match(jsblock_regex);
  var ret = [];
  for (var i = 1; i < match.length; i++) {
    ret[i - 1] = match[i];
  }
  return ret;
}

function extract_url(str) {
  if (str.match(linkdata_obj_regex) !== null) {
    var match = str.match(urlgrabber_regex);
    if (match !== null) {
      return match[1];
    }
  }
  return null;
}

function convert_and_patch(url, jqobj, depth) {
  if (depth > 100) return;

  console.log('Resolving url: ' + url);

  GM_xmlhttpRequest({
    method: 'GET',
    url: url,
    onload: function(resp) {
      //Check xmlhttpRequest ends with t.co
      if (resp.finalUrl.match(tco_url_detect) !== null) {
        var url_arr = resp.response.match(tco_url_extract_regex);
        if (url_arr === null) return;

        convert_and_patch(url_arr[1].replace(/\\\//g, '/'), jqobj, depth + 1);
      }
      var jsblock_arr = get_jsblock(resp.response);
      var url = null;
      for (var i = 0; i < jsblock_arr.length; i++) {
        url = extract_url(jsblock_arr[i]);
        if (url !== null) break;
      }
      jqobj.attr('href', url);
      // Check `jqobj` is normal link or tweet card
      if (jqobj.hasClass('twitter-timeline-link')) {
        jqobj.text(url).attr('title', url);
      } else if (jqobj.hasClass('TwitterCard-container')) {
        jqobj.find('span.SummaryCard-destination').text(jqobj[0].hostname);
      }
    },
    onerror: function(err) {
      console.log(err);
    }
  });
}

function tweet_handler(elem) {
  if (elem.tagName == 'IFRAME' && card_iframe_regex.test(elem.id)) {
    $(elem).on('load', function (event) {
      var link = elem.contentWindow.document.querySelector('a.js-openLink');
      convert_and_patch(link.href, $(link), 0);
    });
  } else {
    var links = $(elem).find('a.twitter-timeline-link');
    for (var i = 0; i < links.length; i++) {
      var match = $(links[i]).text().match(linkis_detect);

      if (match !== null) {
        convert_and_patch(links[i].href, $(links[i]), 0);
      }
    }
  }
}

function get_tweets() {
  var matches = $('li').filter(function() {
    return this.id.match(/stream-item-tweet-*/);
  });

  for (var i = 0; i < matches.length; i++) {
    tweet_handler(matches[i]);
  }
}

var obs_config = {
  childList: true,
  characterData: true,
  subtree: true
};

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var added_nodes = mutation.addedNodes;
    for (var i = 0; i < added_nodes.length; i++) {
      tweet_handler(added_nodes[i]);
    }
  });
});

observer.observe($('#doc')[0], obs_config);
get_tweets();

console.log('Unlink.is ready!');
<commit_msg>Don't handle non-linkis card<commit_after>// ==UserScript==
// @name        unlink.is
// @namespace   http://gmscript.gentoo.moe
// @include     https://twitter.com/*
// @version     0.2
// @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @downloadURL https://raw.githubusercontent.com/perillamint/unlink.is/master/unlinkis.js
// @updateURL   https://raw.githubusercontent.com/perillamint/unlink.is/master/unlinkis.meta.js
// @grant       GM_xmlhttpRequest
// @license     GPLv3 or later
// ==/UserScript==

//Caution: This parsing method is not code-change resist.
var jsblock_regex = /<script[^>]*>[\s\S]([.\s\S]*?)<\/script>/g;
var urlgrabber_regex = /longUrl:[ ]*"(.+?)"/;
var linkdata_obj_regex = /var LinkData/;

var linkis_detect = /(?:ln\.is|linkis\.com)\/\w+/;
var linkis_card_detect = /(?:ln\.is|linkis\.com)/;
var card_iframe_regex = /xdm_default\d+?_provider/;

//Caution: This url extractor WILL CRASH when twitter changes working method of t.co
var tco_url_extract_regex = /location\.replace\("(.*?)"\)/;
var tco_url_detect = /http(|s):\/\/t.co\/[^\/]*$/;

function get_jsblock(str) {
  var match = str.match(jsblock_regex);
  var ret = [];
  for (var i = 1; i < match.length; i++) {
    ret[i - 1] = match[i];
  }
  return ret;
}

function extract_url(str) {
  if (str.match(linkdata_obj_regex) !== null) {
    var match = str.match(urlgrabber_regex);
    if (match !== null) {
      return match[1];
    }
  }
  return null;
}

function convert_and_patch(url, jqobj, depth) {
  if (depth > 100) return;

  console.log('Resolving url: ' + url);

  GM_xmlhttpRequest({
    method: 'GET',
    url: url,
    onload: function(resp) {
      //Check xmlhttpRequest ends with t.co
      if (resp.finalUrl.match(tco_url_detect) !== null) {
        var url_arr = resp.response.match(tco_url_extract_regex);
        if (url_arr === null) return;

        convert_and_patch(url_arr[1].replace(/\\\//g, '/'), jqobj, depth + 1);
      }
      var jsblock_arr = get_jsblock(resp.response);
      var url = null;
      for (var i = 0; i < jsblock_arr.length; i++) {
        url = extract_url(jsblock_arr[i]);
        if (url !== null) break;
      }
      jqobj.attr('href', url);
      // Check `jqobj` is normal link or tweet card
      if (jqobj.hasClass('twitter-timeline-link')) {
        jqobj.text(url).attr('title', url);
      } else if (jqobj.hasClass('TwitterCard-container')) {
        jqobj.find('span.SummaryCard-destination').text(jqobj[0].hostname);
      }
    },
    onerror: function(err) {
      console.log(err);
    }
  });
}

function tweet_handler(elem) {
  if (elem.tagName == 'IFRAME' && card_iframe_regex.test(elem.id)) {
    $(elem).on('load', function (event) {
      var card_hostname = elem.contentWindow.document.querySelector('span.SummaryCard-destination');
      if (card_hostname !== null && linkis_card_detect.test(card_hostname.textContent)) {
        var link = elem.contentWindow.document.querySelector('a.js-openLink');
        convert_and_patch(link.href, $(link), 0);
      }
    });
  } else {
    var links = $(elem).find('a.twitter-timeline-link');
    for (var i = 0; i < links.length; i++) {
      var match = $(links[i]).text().match(linkis_detect);

      if (match !== null) {
        convert_and_patch(links[i].href, $(links[i]), 0);
      }
    }
  }
}

function get_tweets() {
  var matches = $('li').filter(function() {
    return this.id.match(/stream-item-tweet-*/);
  });

  for (var i = 0; i < matches.length; i++) {
    tweet_handler(matches[i]);
  }
}

var obs_config = {
  childList: true,
  characterData: true,
  subtree: true
};

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var added_nodes = mutation.addedNodes;
    for (var i = 0; i < added_nodes.length; i++) {
      tweet_handler(added_nodes[i]);
    }
  });
});

observer.observe($('#doc')[0], obs_config);
get_tweets();

console.log('Unlink.is ready!');
<|endoftext|>


<commit_before>
<commit_msg>Update StringCalculator.js<commit_after>var test = require('mocha').it,
  expect = require('chai').expect;

test('fromEnglish: "zero" through "nine"', function(){
  expect(fromEnglish).to.exist;
  expect(fromEnglish("zero")).to.equal(0);
  expect(fromEnglish("one")).to.equal(1);
  // more tests here, please...
}); // END test(fromEnglish)

/**
 * @param {String} word representing an English number
 * @return {Number} value corresponding to `word`
 */
function fromEnglish(word){
  // fill this in after writing tests...
} // END fromEnglish

test('plus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(plus).to.exist;
  expect(plus("zero", "zero")).to.equal(0);
  expect(plus("zero", "one")).to.equal(1); // change just one thing!
  expect(plus("zero", "two")).to.equal(FILL_ME_IN); // ha!
  // write more tests like those...
}); // END test(plus)

/**
 * @param {String} A representing an English number word
 * @param {String} B representing an English number word
 * @return {Number} the value of `A` added to `B`
function plus(A, B){
  // write those tests first, please...
} // END plus

test('minus: ("zero", "zero") through ("zero", "nine")', function(){
  expect(minus).to.exist;
  expect(minus("zero", "zero").to.equal(0);
  expect(minus("zero", "one").to.equal(-1);
  // etc, etc, etc
}); // END test(minus)

// What about multiplication? Division? Exponents?
<|endoftext|>


<commit_before>var example = require("washington")

var ArrayElement = require("../object-pattern").ArrayElement
var ArrayEllipsis = require("../object-pattern").ArrayEllipsis
var ArrayPattern = require("../object-pattern").ArrayPattern
var ArrayWildcard = require("../object-pattern").ArrayWildcard
var ExactProperty = require("../object-pattern").ExactProperty
var Negator = require("../object-pattern").Negator
var ObjectPattern = require("../object-pattern").ObjectPattern
var TypedValue = require("../object-pattern").TypedValue
var WildcardProperty = require("../object-pattern").WildcardProperty
var WildcardValue = require("../object-pattern").WildcardValue

var Interpreter = function (source) {
  this.pattern = this.object(source)
}

Interpreter.prototype.object = function (source) {
  var buffer = ""
  var deepness = 0
  var object = new ObjectPattern

  source.split("").forEach(function (character, index) {
    if (character === "," && deepness === 0) {
      object.properties.push(this.property(buffer))
      buffer = ""
    }

    else
      buffer += character

    if (character === "(") deepness ++
    if (character === ")") {
      deepness --
      if (deepness === 0) {
        object.properties.push(this.property(buffer))
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      object.properties.push(this.property(buffer))
  }.bind(this))

  return object
}

Interpreter.prototype.property = function (source) {
  var buffer        = ""
  var deepness      = 0
  var propertyName  = source.substring(0, source.indexOf(":"))
  var propertyValue = this.value(source.substring(source.indexOf(":") + 1))

  if (propertyName === "*")
    return new WildcardProperty(propertyValue)

  else if (propertyName.substring(0, 1) === "!")
    return new Negator( propertyName.substring(1) === "*" ?
      new WildcardProperty(propertyValue) :
      new ExactProperty(
        propertyName.substring(1),
        propertyValue ) )

  else
    return new ExactProperty(propertyName, propertyValue)
}

Interpreter.prototype.value = function (source) {
  if (source === "*")
    return new WildcardValue

  if (source.substring(0, 1) === "<" &&
      source.substring(source.length - 1, source.length) === ">")
    return new TypedValue(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "(" &&
      source.substring(source.length - 1, source.length) === ")")
    return this.object(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "/")
    return this.array(source)

  return source
}

Interpreter.prototype.array = function (source) {
  var pattern = new ArrayPattern
  var termination = false
  var deepness = []
  var buffer = ""
  var list = []

  source.split("").forEach(function (character, index) {
    if (character === "/" && deepness.length === 0) {
      list.push(buffer)
      buffer = ""
    }

    else
      buffer += character

    if (character === "(")
      deepness.push({character: "("})

    if (character === "[")
      deepness.push({character: "["})

    if (character === ")") {
      if (deepness[deepness.length - 1].character === "(")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (character === "]") {
      if (deepness.length > 0 &&
          deepness[deepness.length - 1].character === "[")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      list.push(buffer)
  })

  list.forEach(function (chunk, index, list) {
    if (termination)
      termination = false

    else {
      if (chunk === "*")
        pattern.matchables.push(new ArrayWildcard)

      else if (chunk === "**") {
        pattern.matchables.push(new ArrayEllipsis(
          index + 1 < list.length ? list[index + 1] : undefined ))
        termination = true
      }

      else if (chunk.substring(0, 1) === "[" &&
          chunk.substring(chunk.length - 1, chunk.length) === "]")
        pattern.matchables.push(
          new ArrayElement(
            this.array(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk.substring(0, 1) === "(" &&
          chunk.substring(chunk.length - 1, chunk.length) === ")")
        pattern.matchables.push(
          new ArrayElement(
            this.object(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk !== "")
        pattern.matchables.push(chunk)
    }
  }.bind(this))

  return pattern
}

example("Interpreter: '' > OP", function () {
  return new Interpreter("")
    .pattern instanceof ObjectPattern
})

example("Interpreter: 'key:value' > OP[EP]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'key:value' > OP[EP[key]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .name === "key"
})

example("Interpreter: 'key:value' > OP[EP[,value]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .value === "value"
})

example("Interpreter: '*:value' > OP[WP]", function () {
  return new Interpreter("*:value")
    .pattern
    .properties[0] instanceof WildcardProperty
})

example("Interpreter: '*:value,other:23' > OP[WP,EP]", function () {
  var properties = new Interpreter("*:value,other:23").pattern.properties

  return  properties[0] instanceof WildcardProperty &&
          properties[1] instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP[prop]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .name === "prop"
})

example("Interpreter: '!prop:value' > OP[N[EP[,value]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: '!*:value' > OP[N[WP]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable instanceof WildcardProperty
})

example("Interpreter: '!*:value' > OP[N[WP[value]]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: 'something:*' > OP[EP[WV]]", function () {
  return  new Interpreter("something:*")
    .pattern
    .properties[0]
    .value instanceof WildcardValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value instanceof TypedValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV[string]]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value
    .type === "string"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value instanceof ObjectPattern
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[object]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .name === "object"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[,inside]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .value === "inside"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value instanceof ArrayPattern
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[some]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] === "some"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[/array]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[1] === "array"
})

example("Interpreter: 'type:/*/array' > OP[EP[AP[AW]]]", function () {
  return  new Interpreter("type:/*/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE[array]]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === "array"
})

example("Interpreter: 'type:/**' > OP[EP[AP[AE[undefined]]]]", function () {
  return  new Interpreter("type:/**")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === undefined
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[AW]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE[a]]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1]
    .termination === "a"
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,,b]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[2] === "b"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ArrayPattern
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[sub]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[0] === "sub"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[,array]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] === "array"
})

example("Interpreter: 'a:/[/sub/[/sub]/array]/b' > OP[EP[AP[AE[AP[,AE]]]]]", function () {
  return  new Interpreter("a:/[/sub/[/sub]/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ObjectPattern
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[sub]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .name === "sub"
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[,object]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .value === "object"
})

example("Interpreter: 'a:true' > OP[EP[,true]]")

example("Interpreter: 'a:24' > OP[EP[,24]]")

example("Interpreter: 'a:\"true\"' > OP[EP[,\"true\"]]")

example("Interpreter: 'a:\"/true/(a:b)\"' > OP[EP[,\"/true/(a:b)\"]]")
<commit_msg>Support true and false literals<commit_after>var example = require("washington")

var ArrayElement = require("../object-pattern").ArrayElement
var ArrayEllipsis = require("../object-pattern").ArrayEllipsis
var ArrayPattern = require("../object-pattern").ArrayPattern
var ArrayWildcard = require("../object-pattern").ArrayWildcard
var ExactProperty = require("../object-pattern").ExactProperty
var Negator = require("../object-pattern").Negator
var ObjectPattern = require("../object-pattern").ObjectPattern
var TypedValue = require("../object-pattern").TypedValue
var WildcardProperty = require("../object-pattern").WildcardProperty
var WildcardValue = require("../object-pattern").WildcardValue

var Interpreter = function (source) {
  this.pattern = this.object(source)
}

Interpreter.prototype.object = function (source) {
  var buffer = ""
  var deepness = 0
  var object = new ObjectPattern

  source.split("").forEach(function (character, index) {
    if (character === "," && deepness === 0) {
      object.properties.push(this.property(buffer))
      buffer = ""
    }

    else
      buffer += character

    if (character === "(") deepness ++
    if (character === ")") {
      deepness --
      if (deepness === 0) {
        object.properties.push(this.property(buffer))
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      object.properties.push(this.property(buffer))
  }.bind(this))

  return object
}

Interpreter.prototype.property = function (source) {
  var buffer        = ""
  var deepness      = 0
  var propertyName  = source.substring(0, source.indexOf(":"))
  var propertyValue = this.value(source.substring(source.indexOf(":") + 1))

  if (propertyName === "*")
    return new WildcardProperty(propertyValue)

  else if (propertyName.substring(0, 1) === "!")
    return new Negator( propertyName.substring(1) === "*" ?
      new WildcardProperty(propertyValue) :
      new ExactProperty(
        propertyName.substring(1),
        propertyValue ) )

  else
    return new ExactProperty(propertyName, propertyValue)
}

Interpreter.prototype.value = function (source) {
  if (source === "*")
    return new WildcardValue

  if (source.substring(0, 1) === "<" &&
      source.substring(source.length - 1, source.length) === ">")
    return new TypedValue(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "(" &&
      source.substring(source.length - 1, source.length) === ")")
    return this.object(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "/")
    return this.array(source)

  if (source === "true")
    return true

  if (source === "false")
    return false

  return source
}

Interpreter.prototype.array = function (source) {
  var pattern = new ArrayPattern
  var termination = false
  var deepness = []
  var buffer = ""
  var list = []

  source.split("").forEach(function (character, index) {
    if (character === "/" && deepness.length === 0) {
      list.push(buffer)
      buffer = ""
    }

    else
      buffer += character

    if (character === "(")
      deepness.push({character: "("})

    if (character === "[")
      deepness.push({character: "["})

    if (character === ")") {
      if (deepness[deepness.length - 1].character === "(")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (character === "]") {
      if (deepness.length > 0 &&
          deepness[deepness.length - 1].character === "[")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      list.push(buffer)
  })

  list.forEach(function (chunk, index, list) {
    if (termination)
      termination = false

    else {
      if (chunk === "*")
        pattern.matchables.push(new ArrayWildcard)

      else if (chunk === "**") {
        pattern.matchables.push(new ArrayEllipsis(
          index + 1 < list.length ? list[index + 1] : undefined ))
        termination = true
      }

      else if (chunk.substring(0, 1) === "[" &&
          chunk.substring(chunk.length - 1, chunk.length) === "]")
        pattern.matchables.push(
          new ArrayElement(
            this.array(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk.substring(0, 1) === "(" &&
          chunk.substring(chunk.length - 1, chunk.length) === ")")
        pattern.matchables.push(
          new ArrayElement(
            this.object(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk === "true")
        pattern.matchables.push(true)

      else if (chunk === "false")
        pattern.matchables.push(false)

      else if (chunk !== "")
        pattern.matchables.push(chunk)
    }
  }.bind(this))

  return pattern
}

example("Interpreter: '' > OP", function () {
  return new Interpreter("")
    .pattern instanceof ObjectPattern
})

example("Interpreter: 'key:value' > OP[EP]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'key:value' > OP[EP[key]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .name === "key"
})

example("Interpreter: 'key:value' > OP[EP[,value]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .value === "value"
})

example("Interpreter: '*:value' > OP[WP]", function () {
  return new Interpreter("*:value")
    .pattern
    .properties[0] instanceof WildcardProperty
})

example("Interpreter: '*:value,other:23' > OP[WP,EP]", function () {
  var properties = new Interpreter("*:value,other:23").pattern.properties

  return  properties[0] instanceof WildcardProperty &&
          properties[1] instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP[prop]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .name === "prop"
})

example("Interpreter: '!prop:value' > OP[N[EP[,value]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: '!*:value' > OP[N[WP]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable instanceof WildcardProperty
})

example("Interpreter: '!*:value' > OP[N[WP[value]]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: 'something:*' > OP[EP[WV]]", function () {
  return  new Interpreter("something:*")
    .pattern
    .properties[0]
    .value instanceof WildcardValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value instanceof TypedValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV[string]]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value
    .type === "string"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value instanceof ObjectPattern
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[object]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .name === "object"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[,inside]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .value === "inside"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value instanceof ArrayPattern
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[some]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] === "some"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[/array]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[1] === "array"
})

example("Interpreter: 'type:/*/array' > OP[EP[AP[AW]]]", function () {
  return  new Interpreter("type:/*/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE[array]]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === "array"
})

example("Interpreter: 'type:/**' > OP[EP[AP[AE[undefined]]]]", function () {
  return  new Interpreter("type:/**")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === undefined
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[AW]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE[a]]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1]
    .termination === "a"
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,,b]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[2] === "b"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ArrayPattern
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[sub]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[0] === "sub"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[,array]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] === "array"
})

example("Interpreter: 'a:/[/sub/[/sub]/array]/b' > OP[EP[AP[AE[AP[,AE]]]]]", function () {
  return  new Interpreter("a:/[/sub/[/sub]/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ObjectPattern
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[sub]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .name === "sub"
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[,object]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .value === "object"
})

example("Interpreter: 'a:true' > OP[EP[,true]]", function () {
  return  new Interpreter("a:true")
    .pattern
    .properties[0]
    .value === true
})

example("Interpreter: 'a:false' > OP[EP[,false]]", function () {
  return  new Interpreter("a:false")
    .pattern
    .properties[0]
    .value === false
})

example("Interpreter: 'a:24' > OP[EP[,24]]")

example("Interpreter: 'a:\"true\"' > OP[EP[,\"true\"]]")

example("Interpreter: 'a:\"/true/(a:b)\"' > OP[EP[,\"/true/(a:b)\"]]")

example("Interpreter: 'a:/true' > OP[AP[true]]", function () {
  return  new Interpreter("a:/true")
    .pattern
    .properties[0]
    .value
    .matchables[0] === true
})

example("Interpreter: 'a:/false' > OP[AP[false]]", function () {
  return  new Interpreter("a:/false")
    .pattern
    .properties[0]
    .value
    .matchables[0] === false
})

example("Interpreter: 'a:/23' > OP[AP[23]]")

example("Interpreter: 'a:/\"23\"' > OP[AP[\"23\"]]")

example("Interpreter: 'a:/\"true\"' > OP[AP[true]]")
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com
 * Based on @tojiro's vr-samples-utils.js
 */

var WEBVR = {

	isLatestAvailable: function () {

		console.warn( 'WEBVR: isLatestAvailable() is being deprecated. Use .isAvailable() instead.' );
		return this.isAvailable();

	},

	isAvailable: function () {

		return navigator.getVRDisplays !== undefined;

	},

	getVRDisplay: function ( onDisplay ) {

		if ( 'getVRDisplays' in navigator ) {

			navigator.getVRDisplays()
				.then( function ( displays ) {

					onDisplay( displays[ 0 ] );

				} )
				.catch( function () {
					// no displays
				} );

		}

	},

	getMessage: function () {

		var message;

		if ( navigator.getVRDisplays ) {

			navigator.getVRDisplays().then( function ( displays ) {

				if ( displays.length === 0 ) message = 'WebVR supported, but no VRDisplays found.';

			} );

		} else {

			message = 'Your browser does not support WebVR. See webvr.info for assistance.';

		}

		if ( message !== undefined ) {

			var container = document.createElement( 'div' );
			container.style.position = 'absolute';
			container.style.left = '0';
			container.style.top = '0';
			container.style.right = '0';
			container.style.zIndex = '999';
			container.align = 'center';

			var error = document.createElement( 'div' );
			error.style.fontFamily = 'sans-serif';
			error.style.fontSize = '16px';
			error.style.fontStyle = 'normal';
			error.style.lineHeight = '26px';
			error.style.backgroundColor = '#fff';
			error.style.color = '#000';
			error.style.padding = '10px 20px';
			error.style.margin = '50px';
			error.style.display = 'inline-block';
			error.innerHTML = message;
			container.appendChild( error );

			return container;

		}

	},

	getButton: function ( effect, canvas ) {

		var button = document.createElement( 'button' );
		button.style.position = 'absolute';
		button.style.left = 'calc(50% - 50px)';
		button.style.bottom = '20px';
		button.style.width = '100px';
		button.style.border = '0';
		button.style.padding = '8px';
		button.style.cursor = 'pointer';
		button.style.backgroundColor = '#000';
		button.style.color = '#fff';
		button.style.fontFamily = 'sans-serif';
		button.style.fontSize = '13px';
		button.style.fontStyle = 'normal';
		button.style.textAlign = 'center';
		button.style.zIndex = '999';

		if ( effect.getVRDisplay() ) {

			button.textContent = 'ENTER VR';
			button.onclick = function () {

				effect.isPresenting ? effect.exitPresent() : effect.requestPresent( [ { source: canvas } ] );

			};

			window.addEventListener( 'vrdisplaypresentchange', function () {

				button.textContent = effect.isPresenting ? 'EXIT VR' : 'ENTER VR';

			}, false );

		} else {

			button.textContent = 'NO VR DISPLAY';

		}

		return button;

	}

};
<commit_msg>Clean up.<commit_after>/**
 * @author mrdoob / http://mrdoob.com
 * Based on @tojiro's vr-samples-utils.js
 */

var WEBVR = {

	isLatestAvailable: function () {

		console.warn( 'WEBVR: isLatestAvailable() is being deprecated. Use .isAvailable() instead.' );
		return this.isAvailable();

	},

	isAvailable: function () {

		return navigator.getVRDisplays !== undefined;

	},

	getVRDisplay: function ( onDisplay ) {

		if ( 'getVRDisplays' in navigator ) {

			navigator.getVRDisplays()
				.then( function ( displays ) {

					onDisplay( displays[ 0 ] );

				} )
				.catch( function () {
					// no displays
				} );

		}

	},

	getMessage: function () {

		var message;

		if ( navigator.getVRDisplays ) {

			navigator.getVRDisplays().then( function ( displays ) {

				if ( displays.length === 0 ) message = 'WebVR supported, but no VRDisplays found.';

			} );

		} else {

			message = 'Your browser does not support WebVR. See webvr.info for assistance.';

		}

		if ( message !== undefined ) {

			var container = document.createElement( 'div' );
			container.style.position = 'absolute';
			container.style.left = '0';
			container.style.top = '0';
			container.style.right = '0';
			container.style.zIndex = '999';
			container.align = 'center';

			var error = document.createElement( 'div' );
			error.style.fontFamily = 'sans-serif';
			error.style.fontSize = '16px';
			error.style.fontStyle = 'normal';
			error.style.lineHeight = '26px';
			error.style.backgroundColor = '#fff';
			error.style.color = '#000';
			error.style.padding = '10px 20px';
			error.style.margin = '50px';
			error.style.display = 'inline-block';
			error.innerHTML = message;
			container.appendChild( error );

			return container;

		}

	},

	getButton: function ( effect, canvas ) {

		var button = document.createElement( 'button' );
		button.style.position = 'absolute';
		button.style.left = 'calc(50% - 50px)';
		button.style.bottom = '20px';
		button.style.border = '0';
		button.style.padding = '8px';
		button.style.cursor = 'pointer';
		button.style.backgroundColor = '#000';
		button.style.color = '#fff';
		button.style.fontFamily = 'sans-serif';
		button.style.fontSize = '13px';
		button.style.fontStyle = 'normal';
		button.style.textAlign = 'center';
		button.style.zIndex = '999';

		if ( effect.getVRDisplay() ) {

			button.textContent = 'ENTER VR';
			button.onclick = function () {

				effect.isPresenting ? effect.exitPresent() : effect.requestPresent( [ { source: canvas } ] );

			};

			window.addEventListener( 'vrdisplaypresentchange', function () {

				button.textContent = effect.isPresenting ? 'EXIT VR' : 'ENTER VR';

			}, false );

		} else {

			button.textContent = 'NO VR DISPLAY';

		}

		return button;

	}

};
<|endoftext|>


<commit_before>// PORTAL DETAILS MAIN ///////////////////////////////////////////////
// main code block that renders the portal details in the sidebar and
// methods that highlight the portal in the map view.

window.renderPortalDetails = function(guid) {
  selectPortal(window.portals[guid] ? guid : null);

  if(!window.portals[guid]) {
    urlPortal = guid;
    $('#portaldetails').html('');
    if(isSmartphone()) {
      $('.fullimg').remove();
      $('#mobileinfo').html('');
    }
    return;
  }

  var d = window.portals[guid].options.details;

  // collect some random data that’s not worth to put in an own method
  var links = {incoming: 0, outgoing: 0};
  if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) {
    links[link.isOrigin ? 'outgoing' : 'incoming']++;
  });
  function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
  var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'  •  '+links.outgoing+' ↴')];

  var player = d.captured && d.captured.capturingPlayerId
    ? '' + getPlayerName(d.captured.capturingPlayerId) + ''
    : null;
  var playerText = player ? ['owner', player] : null;

  var time = d.captured
    ? ''
      +  unixTimeToString(d.captured.capturedTime) + ''
    : null;
  var sinceText  = time ? ['since', time] : null;

  var linkedFields = ['fields', d.portalV2.linkedFields ? d.portalV2.linkedFields.length : 0];

  // collect and html-ify random data
  var randDetails = [
    playerText, sinceText,
    getRangeText(d), getEnergyText(d),
    linksText, getAvgResoDistText(d),
    linkedFields, getAttackApGainText(d),
    getHackDetailsText(d), getMitigationText(d)
  ];
  randDetails = '
' + genFourColumnTable(randDetails) + '
';

  var resoDetails = '
' + getResonatorDetails(d) + '
';

  var img = getPortalImageUrl(d);
  var lat = d.locationE6.latE6/1E6;
  var lng = d.locationE6.lngE6/1E6;
  var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
  var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
  var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')';
  var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d);

  var portalDetailedDescription = '';

  if(portalDetailObj) {
    portalDetailedDescription = '
';

    // TODO (once the data supports it) - portals can have multiple photos. display all, with navigation between them
    // (at this time the data isn't returned from the server - although a count of images IS returned!)

    if(portalDetailObj.submitter.name.length > 0) {
      if(portalDetailObj.submitter.team) {
        submitterSpan = '';
      } else {
        submitterSpan = '';
      }
      portalDetailedDescription += '
Photo by:	' + submitterSpan
                                + escapeHtmlSpecialChars(portalDetailObj.submitter.name) + ''+(portalDetailObj.submitter.voteCount !== undefined ? ' (' + portalDetailObj.submitter.voteCount + ' votes)' : '')+'
';
    }
    if(portalDetailObj.submitter.link.length > 0) {
      portalDetailedDescription += '
Photo from:	' + escapeHtmlSpecialChars(portalDetailObj.submitter.link) + '
';
    }

    if(portalDetailObj.description) {
      portalDetailedDescription += '
Description:	' + escapeHtmlSpecialChars(portalDetailObj.description) + '
';
    }
//    if(d.portalV2.descriptiveText.ADDRESS) {
//      portalDetailedDescription += '
Address:	' + escapeHtmlSpecialChars(d.portalV2.descriptiveText.ADDRESS) + '
';
//    }

    portalDetailedDescription += '
';
  }

  $('#portaldetails')
    .attr('class', TEAM_TO_CSS[getTeam(d)])
    .html(''
      + '
'+escapeHtmlSpecialChars(d.portalV2.descriptiveText.TITLE)+'
'
      + 'X'
      // help cursor via ".imgpreview img"
      + '
'
      + ''+Math.floor(getPortalLevel(d))+''
      + '
'+ portalDetailedDescription + '
'
      + '
'
      + '
'
      + '
'+getModDetails(d)+'
'
      + randDetails
      + resoDetails
      + '
'
      + (
        typeof android !== 'undefined' && android && android.intentPosLink // Android handles both links via a dialog
        ? 'Portal link'
        : 'Portal link'
        + 'Map links'
        )
      + '
'
    );

  // try to resolve names that were required for above functions, but
  // weren't available yet.
  resolvePlayerNames();

  runHooks('portalDetailsUpdated', {portalDetails: d});
}

// draws link-range and hack-range circles around the portal with the
// given details. Clear them if parameter 'd' is null.
window.setPortalIndicators = function(d) {
  if(portalRangeIndicator) map.removeLayer(portalRangeIndicator);
  portalRangeIndicator = null;
  if(portalAccessIndicator) map.removeLayer(portalAccessIndicator);
  portalAccessIndicator = null;

  if(d === null) return;

  var range = getPortalRange(d);
  var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
  portalRangeIndicator = (range > 0
      ? L.geodesicCircle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false })
      : L.circle(coord, range, { fill: false, stroke: false, clickable: false })
    ).addTo(map);

  portalAccessIndicator = L.circle(coord, HACK_RANGE,
    { fill: false, color: ACCESS_INDICATOR_COLOR, weight: 2, clickable: false }
  ).addTo(map);
}

// highlights portal with given GUID. Automatically clears highlights
// on old selection. Returns false if the selected portal changed.
// Returns true if it's still the same portal that just needs an
// update.
window.selectPortal = function(guid) {
  var update = selectedPortal === guid;
  var oldPortalGuid = selectedPortal;
  selectedPortal = guid;

  var oldPortal = portals[oldPortalGuid];
  var newPortal = portals[guid];

  // Restore style of unselected portal
  if(!update && oldPortal) setMarkerStyle(oldPortal,false);

  // Change style of selected portal
  if(newPortal) {
    setMarkerStyle(newPortal, true);

    if (map.hasLayer(newPortal)) {
      newPortal.bringToFront();
    }
  }

  setPortalIndicators(newPortal ? newPortal.options.details : null);

  runHooks('portalSelected', {selectedPortalGuid: guid, unselectedPortalGuid: oldPortalGuid});
  return update;
}
<commit_msg>make the portal details close button switch back to the map on mobile<commit_after>// PORTAL DETAILS MAIN ///////////////////////////////////////////////
// main code block that renders the portal details in the sidebar and
// methods that highlight the portal in the map view.

window.renderPortalDetails = function(guid) {
  selectPortal(window.portals[guid] ? guid : null);

  if(!window.portals[guid]) {
    urlPortal = guid;
    $('#portaldetails').html('');
    if(isSmartphone()) {
      $('.fullimg').remove();
      $('#mobileinfo').html('');
    }
    return;
  }

  var d = window.portals[guid].options.details;

  // collect some random data that’s not worth to put in an own method
  var links = {incoming: 0, outgoing: 0};
  if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) {
    links[link.isOrigin ? 'outgoing' : 'incoming']++;
  });
  function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
  var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'  •  '+links.outgoing+' ↴')];

  var player = d.captured && d.captured.capturingPlayerId
    ? '' + getPlayerName(d.captured.capturingPlayerId) + ''
    : null;
  var playerText = player ? ['owner', player] : null;

  var time = d.captured
    ? ''
      +  unixTimeToString(d.captured.capturedTime) + ''
    : null;
  var sinceText  = time ? ['since', time] : null;

  var linkedFields = ['fields', d.portalV2.linkedFields ? d.portalV2.linkedFields.length : 0];

  // collect and html-ify random data
  var randDetails = [
    playerText, sinceText,
    getRangeText(d), getEnergyText(d),
    linksText, getAvgResoDistText(d),
    linkedFields, getAttackApGainText(d),
    getHackDetailsText(d), getMitigationText(d)
  ];
  randDetails = '
' + genFourColumnTable(randDetails) + '
';

  var resoDetails = '
' + getResonatorDetails(d) + '
';

  var img = getPortalImageUrl(d);
  var lat = d.locationE6.latE6/1E6;
  var lng = d.locationE6.lngE6/1E6;
  var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
  var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
  var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')';
  var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d);

  var portalDetailedDescription = '';

  if(portalDetailObj) {
    portalDetailedDescription = '
';

    // TODO (once the data supports it) - portals can have multiple photos. display all, with navigation between them
    // (at this time the data isn't returned from the server - although a count of images IS returned!)

    if(portalDetailObj.submitter.name.length > 0) {
      if(portalDetailObj.submitter.team) {
        submitterSpan = '';
      } else {
        submitterSpan = '';
      }
      portalDetailedDescription += '
Photo by:	' + submitterSpan
                                + escapeHtmlSpecialChars(portalDetailObj.submitter.name) + ''+(portalDetailObj.submitter.voteCount !== undefined ? ' (' + portalDetailObj.submitter.voteCount + ' votes)' : '')+'
';
    }
    if(portalDetailObj.submitter.link.length > 0) {
      portalDetailedDescription += '
Photo from:	' + escapeHtmlSpecialChars(portalDetailObj.submitter.link) + '
';
    }

    if(portalDetailObj.description) {
      portalDetailedDescription += '
Description:	' + escapeHtmlSpecialChars(portalDetailObj.description) + '
';
    }
//    if(d.portalV2.descriptiveText.ADDRESS) {
//      portalDetailedDescription += '
Address:	' + escapeHtmlSpecialChars(d.portalV2.descriptiveText.ADDRESS) + '
';
//    }

    portalDetailedDescription += '
';
  }

  $('#portaldetails')
    .attr('class', TEAM_TO_CSS[getTeam(d)])
    .html(''
      + '
'+escapeHtmlSpecialChars(d.portalV2.descriptiveText.TITLE)+'
'
      + 'X'
      // help cursor via ".imgpreview img"
      + '
'
      + ''+Math.floor(getPortalLevel(d))+''
      + '
'+ portalDetailedDescription + '
'
      + '
'
      + '
'
      + '
'+getModDetails(d)+'
'
      + randDetails
      + resoDetails
      + '
'
      + (
        typeof android !== 'undefined' && android && android.intentPosLink // Android handles both links via a dialog
        ? 'Portal link'
        : 'Portal link'
        + 'Map links'
        )
      + '
'
    );

  // try to resolve names that were required for above functions, but
  // weren't available yet.
  resolvePlayerNames();

  runHooks('portalDetailsUpdated', {portalDetails: d});
}

// draws link-range and hack-range circles around the portal with the
// given details. Clear them if parameter 'd' is null.
window.setPortalIndicators = function(d) {
  if(portalRangeIndicator) map.removeLayer(portalRangeIndicator);
  portalRangeIndicator = null;
  if(portalAccessIndicator) map.removeLayer(portalAccessIndicator);
  portalAccessIndicator = null;

  if(d === null) return;

  var range = getPortalRange(d);
  var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
  portalRangeIndicator = (range > 0
      ? L.geodesicCircle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false })
      : L.circle(coord, range, { fill: false, stroke: false, clickable: false })
    ).addTo(map);

  portalAccessIndicator = L.circle(coord, HACK_RANGE,
    { fill: false, color: ACCESS_INDICATOR_COLOR, weight: 2, clickable: false }
  ).addTo(map);
}

// highlights portal with given GUID. Automatically clears highlights
// on old selection. Returns false if the selected portal changed.
// Returns true if it's still the same portal that just needs an
// update.
window.selectPortal = function(guid) {
  var update = selectedPortal === guid;
  var oldPortalGuid = selectedPortal;
  selectedPortal = guid;

  var oldPortal = portals[oldPortalGuid];
  var newPortal = portals[guid];

  // Restore style of unselected portal
  if(!update && oldPortal) setMarkerStyle(oldPortal,false);

  // Change style of selected portal
  if(newPortal) {
    setMarkerStyle(newPortal, true);

    if (map.hasLayer(newPortal)) {
      newPortal.bringToFront();
    }
  }

  setPortalIndicators(newPortal ? newPortal.options.details : null);

  runHooks('portalSelected', {selectedPortalGuid: guid, unselectedPortalGuid: oldPortalGuid});
  return update;
}
<|endoftext|>


<commit_before>var libassert   = require('assert'),
    libfs       = require('fs'),
    libpath     = require('path'),
    modulepath  = libpath.join(process.cwd(), 'lib', 'yrb2json'),
    prespath    = libpath.join(process.cwd(), 'tests', 'fixtures', 'example.pres'),
    jsonpath    = libpath.join(process.cwd(), 'tests', 'fixtures', 'example.json');

describe('yrb2json', function () {

    it('output looks as expected', function () {
        var yrb2json    = require(modulepath),
            pres        = libfs.readFileSync(prespath, 'utf8').toString(),
            json        = libfs.readFileSync(jsonpath, 'utf8').toString();

        // remove formatting
        json = JSON.stringify(JSON.parse(json));

        libassert.equal(yrb2json(pres), json);
    });

    it('invalid inputs', function () {
        var yrb2json = require(modulepath),
            item,
            invalidInput = {
                "&": "Missing '=' in line &.",
                "=": "Empty key not allowed.",
                "= value": "Empty key not allowed.",
                "key = <<<": "Incomplete heredoc with id .",
                "key = value\\": "Illegal escape sequence: unaccompanied \\",
                "key = v\\u0061lue": "Illegal escape sequence: \\u",
                "key = value\\\"": "Illegal escape sequence: \\\"",
                "k\\#ey = value": "Backslash not allowed in key: k\\#ey",
                "key = <<< end\nend ": "Incomplete heredoc with id end.",
                "key = <<< end": "Incomplete heredoc with id end.",
                "key = <<< end\n": "Incomplete heredoc with id end.",
                "key = <<< end\nend; ": "Incomplete heredoc with id end."
            };
        for (item in invalidInput) {
            if (invalidInput.hasOwnProperty(item)) {
                try {
                    yrb2json(item);
                } catch (e) {
                    libassert.equal(e.message, invalidInput[item]);
                }
            }
        }
    });

});
<commit_msg>count tests throw exception<commit_after>var libassert   = require('assert'),
    libfs       = require('fs'),
    libpath     = require('path'),
    modulepath  = libpath.join(process.cwd(), 'lib', 'yrb2json'),
    prespath    = libpath.join(process.cwd(), 'tests', 'fixtures', 'example.pres'),
    jsonpath    = libpath.join(process.cwd(), 'tests', 'fixtures', 'example.json');

describe('yrb2json', function () {

    it('output looks as expected', function () {
        var yrb2json    = require(modulepath),
            pres        = libfs.readFileSync(prespath, 'utf8').toString(),
            json        = libfs.readFileSync(jsonpath, 'utf8').toString();

        // remove formatting
        json = JSON.stringify(JSON.parse(json));

        libassert.equal(yrb2json(pres), json);
    });

    it('invalid inputs', function () {
        var yrb2json = require(modulepath),
            item,
            num_tests = 0,
            invalidInput = {
                "&": "Missing '=' in line &.",
                "=": "Empty key not allowed.",
                "= value": "Empty key not allowed.",
                "key = <<<": "Incomplete heredoc with id .",
                "key = value\\": "Illegal escape sequence: unaccompanied \\",
                "key = v\\u0061lue": "Illegal escape sequence: \\u",
                "key = value\\\"": "Illegal escape sequence: \\\"",
                "k\\#ey = value": "Backslash not allowed in key: k\\#ey",
                "key = <<< end\nend ": "Incomplete heredoc with id end.",
                "key = <<< end": "Incomplete heredoc with id end.",
                "key = <<< end\n": "Incomplete heredoc with id end.",
                "key = <<< end\nend; ": "Incomplete heredoc with id end."
            };
        for (item in invalidInput) {
            if (invalidInput.hasOwnProperty(item)) {
                try {
                    yrb2json(item);
                } catch (e) {
                    libassert.equal(e.message, invalidInput[item]);
                    num_tests++;
                }
            }
        }
        libassert.equal(num_tests, 12);
    });

});
<|endoftext|>


<commit_before>import AdminRoute from 'ghost-admin/routes/admin';

export default class MembersActivityRoute extends AdminRoute {
}
<commit_msg>Updated activity feed to use full width<commit_after>import AdminRoute from 'ghost-admin/routes/admin';

export default class MembersActivityRoute extends AdminRoute {
    buildRouteInfoMetadata() {
        return {
            titleToken: 'Activity',
            mainClasses: ['gh-main-fullwidth']
        };
    }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @id             iitc-plugin-reload-portal-details@randomizax
// @name           IITC plugin: add a button to refresh portal details
// @category       Info
// @version        0.1.0.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Add a button so that quickly refresh portal details data.
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.reloadDetails = function() {};

window.plugin.reloadDetails.setupCallback = function() {
    addHook('portalDetailsUpdated', window.plugin.reloadDetails.addLink);
}

window.plugin.reloadDetails.addLink = function(d) {
  $('.linkdetails').append('Refresh');
}

window.plugin.reloadDetails.reloadPortalDetails = function(guid) {
  window.portalDetail.request(guid);
}

var setup = function () {
  window.plugin.reloadDetails.setupCallback();
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<commit_msg>adapt for intel.ingress.com<commit_after>// ==UserScript==
// @id             iitc-plugin-reload-portal-details@randomizax
// @name           IITC plugin: add a button to refresh portal details
// @category       Info
// @version        1.0.0.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Add a button so that quickly refresh portal details data.
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @include        https://intel.ingress.com/intel*
// @include        http://intel.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @match          https://intel.ingress.com/intel*
// @match          http://intel.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.reloadDetails = function() {};

window.plugin.reloadDetails.setupCallback = function() {
    addHook('portalDetailsUpdated', window.plugin.reloadDetails.addLink);
}

window.plugin.reloadDetails.addLink = function(d) {
  $('.linkdetails').append('Refresh');
}

window.plugin.reloadDetails.reloadPortalDetails = function(guid) {
  window.portalDetail.request(guid);
}

var setup = function () {
  window.plugin.reloadDetails.setupCallback();
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<|endoftext|>