diff options
| author | Ed Tanous <ed.tanous@intel.com> | 2017-03-07 15:17:13 -0800 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2017-03-07 15:17:13 -0800 |
| commit | 9b65f1fdcfcaaa22719a83be26dbcb5dbe855b0c (patch) | |
| tree | e4eddadebad9695a04b451be41ca1e458113a421 /static/js | |
| parent | 9992332be956c173199257b55e592ec2d2331e3a (diff) | |
| download | bmcweb-9b65f1fdcfcaaa22719a83be26dbcb5dbe855b0c.tar.gz bmcweb-9b65f1fdcfcaaa22719a83be26dbcb5dbe855b0c.zip | |
incremental
Diffstat (limited to 'static/js')
| -rw-r--r-- | static/js/bmcApp.js | 109 | ||||
| -rw-r--r-- | static/js/logincontroller.js | 2 | ||||
| -rw-r--r-- | static/js/restangular.js | 1452 | ||||
| -rw-r--r-- | static/js/run_prettify.js | 2045 | ||||
| -rw-r--r-- | static/js/selController.js | 2 | ||||
| -rw-r--r-- | static/js/versionController.js | 2 |
6 files changed, 2042 insertions, 1570 deletions
diff --git a/static/js/bmcApp.js b/static/js/bmcApp.js index 7392c47..1c91e8f 100644 --- a/static/js/bmcApp.js +++ b/static/js/bmcApp.js @@ -1,17 +1,46 @@ 'use strict'; angular.module('Authentication', []); var app = angular.module('bmcApp', [ - 'Authentication', 'ngCookies', 'ui.bootstrap', 'ui.router', 'restangular', - 'ngSanitize', 'ngWebSocket' + 'Authentication', 'ngCookies', 'ui.bootstrap', 'ui.router', + 'ngSanitize', 'ngWebSocket', 'ngResource' ]); -app.controller('MainCtrl', function($scope, Restangular) { +app.controller('MainCtrl', function($scope) { }); -app.run(['$rootScope', '$cookieStore', '$state', 'Restangular', 'AuthenticationService', - function($rootScope, $cookieStore, $state, Restangular, AuthenticationService) { +app.service('loginInterceptor', function($q, $state) { + var service = this; + + service.responseError = function(response) { + if (response.status == 401){ + console.log("Login required... "); + + var invalidate_reason = "Your user was logged out."; + var continue_promise_chain = false; + + // if we're attempting to log in, we need to + // continue the promise chain to make sure the user is informed + if ($state.current.name === "login") { + invalidate_reason = "Your username and password was incorrect"; + continue_promise_chain = true + } else { + $state.after_login_state = $state.current.name; + $state.go('login'); + } + AuthenticationService.ClearCredentials(invalidate_reason); + } + //return $q.reject(response); + }; +}) + +app.config(['$httpProvider', function ($httpProvider) { + $httpProvider.interceptors.push('loginInterceptor'); +}]); + +app.run(['$rootScope', '$cookieStore', '$state', '$resource', 'AuthenticationService', + function($rootScope, $cookieStore, $state, $resource, AuthenticationService) { if ($rootScope.globals == undefined){ $rootScope.globals = {}; } @@ -29,49 +58,9 @@ app.run(['$rootScope', '$cookieStore', '$state', 'Restangular', 'AuthenticationS $state.go('login'); } }); - - // RestangularProvider.setDefaultHttpFields({cache: true}); - Restangular.setErrorInterceptor(function(response) { - if (response.status == 401) { - console.log("Login required... "); - - var invalidate_reason = "Your user was logged out."; - var continue_promise_chain = false; - - // if we're attempting to log in, we need to - // continue the promise chain to make sure the user is informed - if ($state.current.name === "login") { - invalidate_reason = "Your username and password was incorrect"; - continue_promise_chain = true - } else { - $state.after_login_state = $state.current.name; - $state.go('login'); - } - AuthenticationService.ClearCredentials(invalidate_reason); - - return continue_promise_chain; // stop the promise chain - } else if (response.status == 404) { - console.log("Resource not available..."); - } else { - console.log( - "Response received with HTTP error code: " + response.status); - } - - }); - } ]); -app.config(function(RestangularProvider) { - // set the base url for api calls on our RESTful services - var newBaseUrl = ""; - - var deployedAt = window.location.href.substring(0, window.location.href); - newBaseUrl = deployedAt + "/restui"; - - RestangularProvider.setBaseUrl(newBaseUrl); -}); - app.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/systeminfo'); @@ -80,30 +69,30 @@ app.config(function($stateProvider, $urlRouterProvider) { // nested list with just some random string data .state('login', { url: '/login', - templateUrl: 'login.html', + templateUrl: 'static/login.html', controller: 'LoginController', }) // systeminfo view ======================================== .state( 'systeminfo', - {url: '/systeminfo', templateUrl: 'partial-systeminfo.html'}) + {url: '/systeminfo', templateUrl: 'static/partial-systeminfo.html'}) // HOME STATES AND NESTED VIEWS ======================================== .state( - 'eventlog', {url: '/eventlog', templateUrl: 'partial-eventlog.html'}) + 'eventlog', {url: '/eventlog', templateUrl: 'static/partial-eventlog.html'}) .state( - 'kvm', {url: '/kvm', templateUrl: 'partial-kvm.html'}) + 'kvm', {url: '/kvm', templateUrl: 'static/partial-kvm.html'}) // ABOUT PAGE AND MULTIPLE NAMED VIEWS ================================= - .state('about', {url: '/about', templateUrl: 'partial-fruinfo.html'}) + .state('about', {url: '/about', templateUrl: 'static/partial-fruinfo.html'}) // nested list with custom controller .state('about.list', { url: '/list', - templateUrl: 'partial-home-list.html', + templateUrl: 'static/partial-home-list.html', controller: function($scope) { $scope.dogs = ['Bernese', 'Husky', 'Goldendoodle']; } @@ -127,22 +116,22 @@ app.controller('PaginationDemoCtrl', function($scope, $log) { $scope.bigCurrentPage = 1; }); -angular - .module('Authentication') +angular.module('Authentication') .factory( 'AuthenticationService', - [ - 'Restangular', '$cookieStore', '$rootScope', '$timeout', - function(Restangular, $cookieStore, $rootScope, $timeout) { + ['$cookieStore', '$rootScope', '$timeout', '$resource', '$log', + function($cookieStore, $rootScope, $timeout, $resource, $log) { var service = {}; - service.Login = function( - username, password, success_callback, fail_callback) { + service.Login = function(username, password, success_callback, fail_callback) { var user = {"username": username, "password": password}; - Restangular.all("login").post(user).then( - success_callback, fail_callback); + var UserLogin = $resource("/login"); + var this_login = new UserLogin(); + this_login.data = {"username": username, "password": password}; + UserLogin.save(user, success_callback, fail_callback); + }; service.SetCredentials = function(username, token) { diff --git a/static/js/logincontroller.js b/static/js/logincontroller.js index d0b7a7f..e83d8bc 100644 --- a/static/js/logincontroller.js +++ b/static/js/logincontroller.js @@ -29,4 +29,4 @@ angular.module('Authentication').controller('LoginController', [ }); }; } -]);
\ No newline at end of file +]); diff --git a/static/js/restangular.js b/static/js/restangular.js deleted file mode 100644 index b59b25f..0000000 --- a/static/js/restangular.js +++ /dev/null @@ -1,1452 +0,0 @@ -/** - * Restful Resources service for AngularJS apps - * @version v1.6.1 - 2017-01-06 * @link https://github.com/mgonto/restangular - * @author Martin Gontovnikas <martin@gon.to> - * @license MIT License, http://www.opensource.org/licenses/MIT - */(function(root, factory) { - /* global define, require */ - // https://github.com/umdjs/umd/blob/master/templates/returnExports.js - if (typeof define === 'function' && define.amd) { - define(['lodash', 'angular'], factory); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(require('lodash'), require('angular')); - } else { - // No global export, Restangular will register itself as Angular.js module - factory(root._, root.angular); - } -}(this, function(_, angular) { - - var restangular = angular.module('restangular', []); - - restangular.provider('Restangular', function() { - // Configuration - var Configurer = {}; - Configurer.init = function(object, config) { - object.configuration = config; - - /** - * Those are HTTP safe methods for which there is no need to pass any data with the request. - */ - var safeMethods = ['get', 'head', 'options', 'trace', 'getlist']; - config.isSafe = function(operation) { - return _.includes(safeMethods, operation.toLowerCase()); - }; - - var absolutePattern = /^https?:\/\//i; - config.isAbsoluteUrl = function(string) { - return _.isUndefined(config.absoluteUrl) || _.isNull(config.absoluteUrl) ? - string && absolutePattern.test(string) : - config.absoluteUrl; - }; - - config.absoluteUrl = _.isUndefined(config.absoluteUrl) ? true : config.absoluteUrl; - object.setSelfLinkAbsoluteUrl = function(value) { - config.absoluteUrl = value; - }; - /** - * This is the BaseURL to be used with Restangular - */ - config.baseUrl = _.isUndefined(config.baseUrl) ? '' : config.baseUrl; - object.setBaseUrl = function(newBaseUrl) { - config.baseUrl = /\/$/.test(newBaseUrl) ? - newBaseUrl.substring(0, newBaseUrl.length - 1) : - newBaseUrl; - return this; - }; - - /** - * Sets the extra fields to keep from the parents - */ - config.extraFields = config.extraFields || []; - object.setExtraFields = function(newExtraFields) { - config.extraFields = newExtraFields; - return this; - }; - - /** - * Some default $http parameter to be used in EVERY call - **/ - config.defaultHttpFields = config.defaultHttpFields || {}; - object.setDefaultHttpFields = function(values) { - config.defaultHttpFields = values; - return this; - }; - - /** - * Always return plain data, no restangularized object - **/ - config.plainByDefault = config.plainByDefault || false; - object.setPlainByDefault = function(value) { - config.plainByDefault = value === true ? true : false; - return this; - }; - - config.withHttpValues = function(httpLocalConfig, obj) { - return _.defaults(obj, httpLocalConfig, config.defaultHttpFields); - }; - - config.encodeIds = _.isUndefined(config.encodeIds) ? true : config.encodeIds; - object.setEncodeIds = function(encode) { - config.encodeIds = encode; - }; - - config.defaultRequestParams = config.defaultRequestParams || { - get: {}, - post: {}, - put: {}, - remove: {}, - common: {} - }; - - object.setDefaultRequestParams = function(param1, param2) { - var methods = [], - params = param2 || param1; - if (!_.isUndefined(param2)) { - if (_.isArray(param1)) { - methods = param1; - } else { - methods.push(param1); - } - } else { - methods.push('common'); - } - - _.each(methods, function(method) { - config.defaultRequestParams[method] = params; - }); - return this; - }; - - object.requestParams = config.defaultRequestParams; - - config.defaultHeaders = config.defaultHeaders || {}; - object.setDefaultHeaders = function(headers) { - config.defaultHeaders = headers; - object.defaultHeaders = config.defaultHeaders; - return this; - }; - - object.defaultHeaders = config.defaultHeaders; - - /** - * Method overriders will set which methods are sent via POST with an X-HTTP-Method-Override - **/ - config.methodOverriders = config.methodOverriders || []; - object.setMethodOverriders = function(values) { - var overriders = _.extend([], values); - if (config.isOverridenMethod('delete', overriders)) { - overriders.push('remove'); - } - config.methodOverriders = overriders; - return this; - }; - - config.jsonp = _.isUndefined(config.jsonp) ? false : config.jsonp; - object.setJsonp = function(active) { - config.jsonp = active; - }; - - config.isOverridenMethod = function(method, values) { - var search = values || config.methodOverriders; - return !_.isUndefined(_.find(search, function(one) { - return one.toLowerCase() === method.toLowerCase(); - })); - }; - - /** - * Sets the URL creator type. For now, only Path is created. In the future we'll have queryParams - **/ - config.urlCreator = config.urlCreator || 'path'; - object.setUrlCreator = function(name) { - if (!_.has(config.urlCreatorFactory, name)) { - throw new Error('URL Path selected isn\'t valid'); - } - - config.urlCreator = name; - return this; - }; - - /** - * You can set the restangular fields here. The 3 required fields for Restangular are: - * - * id: Id of the element - * route: name of the route of this element - * parentResource: the reference to the parent resource - * - * All of this fields except for id, are handled (and created) by Restangular. By default, - * the field values will be id, route and parentResource respectively - */ - config.restangularFields = config.restangularFields || { - id: 'id', - route: 'route', - parentResource: 'parentResource', - restangularCollection: 'restangularCollection', - cannonicalId: '__cannonicalId', - etag: 'restangularEtag', - selfLink: 'href', - get: 'get', - getList: 'getList', - put: 'put', - post: 'post', - remove: 'remove', - head: 'head', - trace: 'trace', - options: 'options', - patch: 'patch', - getRestangularUrl: 'getRestangularUrl', - getRequestedUrl: 'getRequestedUrl', - putElement: 'putElement', - addRestangularMethod: 'addRestangularMethod', - getParentList: 'getParentList', - clone: 'clone', - ids: 'ids', - httpConfig: '_$httpConfig', - reqParams: 'reqParams', - one: 'one', - all: 'all', - several: 'several', - oneUrl: 'oneUrl', - allUrl: 'allUrl', - customPUT: 'customPUT', - customPATCH: 'customPATCH', - customPOST: 'customPOST', - customDELETE: 'customDELETE', - customGET: 'customGET', - customGETLIST: 'customGETLIST', - customOperation: 'customOperation', - doPUT: 'doPUT', - doPATCH: 'doPATCH', - doPOST: 'doPOST', - doDELETE: 'doDELETE', - doGET: 'doGET', - doGETLIST: 'doGETLIST', - fromServer: 'fromServer', - withConfig: 'withConfig', - withHttpConfig: 'withHttpConfig', - singleOne: 'singleOne', - plain: 'plain', - save: 'save', - restangularized: 'restangularized' - }; - object.setRestangularFields = function(resFields) { - config.restangularFields = - _.extend(config.restangularFields, resFields); - return this; - }; - - config.isRestangularized = function(obj) { - return !!obj[config.restangularFields.restangularized]; - }; - - config.setFieldToElem = function(field, elem, value) { - var properties = field.split('.'); - var idValue = elem; - _.each(_.initial(properties), function(prop) { - idValue[prop] = {}; - idValue = idValue[prop]; - }); - idValue[_.last(properties)] = value; - return this; - }; - - config.getFieldFromElem = function(field, elem) { - var properties = field.split('.'); - var idValue = elem; - _.each(properties, function(prop) { - if (idValue) { - idValue = idValue[prop]; - } - }); - return angular.copy(idValue); - }; - - config.setIdToElem = function(elem, id /*, route */ ) { - config.setFieldToElem(config.restangularFields.id, elem, id); - return this; - }; - - config.getIdFromElem = function(elem) { - return config.getFieldFromElem(config.restangularFields.id, elem); - }; - - config.isValidId = function(elemId) { - return '' !== elemId && !_.isUndefined(elemId) && !_.isNull(elemId); - }; - - config.setUrlToElem = function(elem, url /*, route */ ) { - config.setFieldToElem(config.restangularFields.selfLink, elem, url); - return this; - }; - - config.getUrlFromElem = function(elem) { - return config.getFieldFromElem(config.restangularFields.selfLink, elem); - }; - - config.useCannonicalId = _.isUndefined(config.useCannonicalId) ? false : config.useCannonicalId; - object.setUseCannonicalId = function(value) { - config.useCannonicalId = value; - return this; - }; - - config.getCannonicalIdFromElem = function(elem) { - var cannonicalId = elem[config.restangularFields.cannonicalId]; - var actualId = config.isValidId(cannonicalId) ? cannonicalId : config.getIdFromElem(elem); - return actualId; - }; - - /** - * Sets the Response parser. This is used in case your response isn't directly the data. - * For example if you have a response like {meta: {'meta'}, data: {name: 'Gonto'}} - * you can extract this data which is the one that needs wrapping - * - * The ResponseExtractor is a function that receives the response and the method executed. - */ - - config.responseInterceptors = config.responseInterceptors || []; - - config.defaultResponseInterceptor = function(data /*, operation, what, url, response, deferred */ ) { - return data; - }; - - config.responseExtractor = function(data, operation, what, url, response, deferred) { - var interceptors = angular.copy(config.responseInterceptors); - interceptors.push(config.defaultResponseInterceptor); - var theData = data; - _.each(interceptors, function(interceptor) { - theData = interceptor(theData, operation, - what, url, response, deferred); - }); - return theData; - }; - - object.addResponseInterceptor = function(extractor) { - config.responseInterceptors.push(extractor); - return this; - }; - - config.errorInterceptors = config.errorInterceptors || []; - object.addErrorInterceptor = function(interceptor) { - config.errorInterceptors.push(interceptor); - return this; - }; - - object.setResponseInterceptor = object.addResponseInterceptor; - object.setResponseExtractor = object.addResponseInterceptor; - object.setErrorInterceptor = object.addErrorInterceptor; - - /** - * Response interceptor is called just before resolving promises. - */ - - - /** - * Request interceptor is called before sending an object to the server. - */ - config.requestInterceptors = config.requestInterceptors || []; - - config.defaultInterceptor = function(element, operation, path, url, headers, params, httpConfig) { - return { - element: element, - headers: headers, - params: params, - httpConfig: httpConfig - }; - }; - - config.fullRequestInterceptor = function(element, operation, path, url, headers, params, httpConfig) { - var interceptors = angular.copy(config.requestInterceptors); - var defaultRequest = config.defaultInterceptor(element, operation, path, url, headers, params, httpConfig); - return _.reduce(interceptors, function(request, interceptor) { - return _.extend(request, interceptor(request.element, operation, - path, url, request.headers, request.params, request.httpConfig)); - }, defaultRequest); - }; - - object.addRequestInterceptor = function(interceptor) { - config.requestInterceptors.push(function(elem, operation, path, url, headers, params, httpConfig) { - return { - headers: headers, - params: params, - element: interceptor(elem, operation, path, url), - httpConfig: httpConfig - }; - }); - return this; - }; - - object.setRequestInterceptor = object.addRequestInterceptor; - - object.addFullRequestInterceptor = function(interceptor) { - config.requestInterceptors.push(interceptor); - return this; - }; - - object.setFullRequestInterceptor = object.addFullRequestInterceptor; - - config.onBeforeElemRestangularized = config.onBeforeElemRestangularized || function(elem) { - return elem; - }; - object.setOnBeforeElemRestangularized = function(post) { - config.onBeforeElemRestangularized = post; - return this; - }; - - object.setRestangularizePromiseInterceptor = function(interceptor) { - config.restangularizePromiseInterceptor = interceptor; - return this; - }; - - /** - * This method is called after an element has been "Restangularized". - * - * It receives the element, a boolean indicating if it's an element or a collection - * and the name of the model - * - */ - config.onElemRestangularized = config.onElemRestangularized || function(elem) { - return elem; - }; - object.setOnElemRestangularized = function(post) { - config.onElemRestangularized = post; - return this; - }; - - config.shouldSaveParent = config.shouldSaveParent || function() { - return true; - }; - object.setParentless = function(values) { - if (_.isArray(values)) { - config.shouldSaveParent = function(route) { - return !_.includes(values, route); - }; - } else if (_.isBoolean(values)) { - config.shouldSaveParent = function() { - return !values; - }; - } - return this; - }; - - /** - * This lets you set a suffix to every request. - * - * For example, if your api requires that for JSon requests you do /users/123.json, you can set that - * in here. - * - * - * By default, the suffix is null - */ - config.suffix = _.isUndefined(config.suffix) ? null : config.suffix; - object.setRequestSuffix = function(newSuffix) { - config.suffix = newSuffix; - return this; - }; - - /** - * Add element transformers for certain routes. - */ - config.transformers = config.transformers || {}; - config.matchTransformers = config.matchTransformers || []; - object.addElementTransformer = function(type, secondArg, thirdArg) { - var isCollection = null; - var transformer = null; - if (arguments.length === 2) { - transformer = secondArg; - } else { - transformer = thirdArg; - isCollection = secondArg; - } - - var transformerFn = function(coll, elem) { - if (_.isNull(isCollection) || (coll === isCollection)) { - return transformer(elem); - } - return elem; - }; - - if (_.isRegExp(type)) { - config.matchTransformers.push({ - regexp: type, - transformer: transformerFn - }); - } else { - if (!config.transformers[type]) { - config.transformers[type] = []; - } - config.transformers[type].push(transformerFn); - } - - return object; - }; - - object.extendCollection = function(route, fn) { - return object.addElementTransformer(route, true, fn); - }; - - object.extendModel = function(route, fn) { - return object.addElementTransformer(route, false, fn); - }; - - config.transformElem = function(elem, isCollection, route, Restangular, force) { - if (!force && !config.transformLocalElements && !elem[config.restangularFields.fromServer]) { - return elem; - } - - var changedElem = elem; - - var matchTransformers = config.matchTransformers; - if (matchTransformers) { - _.each(matchTransformers, function(transformer) { - if (transformer.regexp.test(route)) { - changedElem = transformer.transformer(isCollection, changedElem); - } - }); - } - - var typeTransformers = config.transformers[route]; - if (typeTransformers) { - _.each(typeTransformers, function(transformer) { - changedElem = transformer(isCollection, changedElem); - }); - } - return config.onElemRestangularized(changedElem, isCollection, route, Restangular); - }; - - config.transformLocalElements = _.isUndefined(config.transformLocalElements) ? - false : - config.transformLocalElements; - - object.setTransformOnlyServerElements = function(active) { - config.transformLocalElements = !active; - }; - - config.fullResponse = _.isUndefined(config.fullResponse) ? false : config.fullResponse; - object.setFullResponse = function(full) { - config.fullResponse = full; - return this; - }; - - - //Internal values and functions - config.urlCreatorFactory = {}; - - /** - * Base URL Creator. Base prototype for everything related to it - **/ - - var BaseCreator = function() {}; - - BaseCreator.prototype.setConfig = function(config) { - this.config = config; - return this; - }; - - BaseCreator.prototype.parentsArray = function(current) { - var parents = []; - while (current) { - parents.push(current); - current = current[this.config.restangularFields.parentResource]; - } - return parents.reverse(); - }; - - function RestangularResource(config, $http, url, configurer) { - var resource = {}; - _.each(_.keys(configurer), function(key) { - var value = configurer[key]; - - // Add default parameters - value.params = _.extend({}, value.params, config.defaultRequestParams[value.method.toLowerCase()]); - // We don't want the ? if no params are there - if (_.isEmpty(value.params)) { - delete value.params; - } - - if (config.isSafe(value.method)) { - - resource[key] = function() { - return $http(_.extend(value, { - url: url - })); - }; - - } else { - - resource[key] = function(data) { - return $http(_.extend(value, { - url: url, - data: data - })); - }; - - } - }); - - return resource; - } - - BaseCreator.prototype.resource = function(current, $http, localHttpConfig, callHeaders, callParams, what, etag, operation) { - - var params = _.defaults(callParams || {}, this.config.defaultRequestParams.common); - var headers = _.defaults(callHeaders || {}, this.config.defaultHeaders); - - if (etag) { - if (!config.isSafe(operation)) { - headers['If-Match'] = etag; - } else { - headers['If-None-Match'] = etag; - } - } - - var url = this.base(current); - - if (what || what === 0) { - var add = ''; - if (!/\/$/.test(url)) { - add += '/'; - } - add += what; - url += add; - } - - if (this.config.suffix && - url.indexOf(this.config.suffix, url.length - this.config.suffix.length) === -1 && - !this.config.getUrlFromElem(current)) { - url += this.config.suffix; - } - - current[this.config.restangularFields.httpConfig] = undefined; - - return RestangularResource(this.config, $http, url, { - getList: this.config.withHttpValues(localHttpConfig, { - method: 'GET', - params: params, - headers: headers - }), - - get: this.config.withHttpValues(localHttpConfig, { - method: 'GET', - params: params, - headers: headers - }), - - jsonp: this.config.withHttpValues(localHttpConfig, { - method: 'jsonp', - params: params, - headers: headers - }), - - put: this.config.withHttpValues(localHttpConfig, { - method: 'PUT', - params: params, - headers: headers - }), - - post: this.config.withHttpValues(localHttpConfig, { - method: 'POST', - params: params, - headers: headers - }), - - remove: this.config.withHttpValues(localHttpConfig, { - method: 'DELETE', - params: params, - headers: headers - }), - - head: this.config.withHttpValues(localHttpConfig, { - method: 'HEAD', - params: params, - headers: headers - }), - - trace: this.config.withHttpValues(localHttpConfig, { - method: 'TRACE', - params: params, - headers: headers - }), - - options: this.config.withHttpValues(localHttpConfig, { - method: 'OPTIONS', - params: params, - headers: headers - }), - - patch: this.config.withHttpValues(localHttpConfig, { - method: 'PATCH', - params: params, - headers: headers - }) - }); - }; - - /** - * This is the Path URL creator. It uses Path to show Hierarchy in the Rest API. - * This means that if you have an Account that then has a set of Buildings, a URL to a building - * would be /accounts/123/buildings/456 - **/ - var Path = function() {}; - - Path.prototype = new BaseCreator(); - - Path.prototype.normalizeUrl = function(url) { - var parts = /((?:http[s]?:)?\/\/)?(.*)?/.exec(url); - parts[2] = parts[2].replace(/[\\\/]+/g, '/'); - return (typeof parts[1] !== 'undefined') ? parts[1] + parts[2] : parts[2]; - }; - - Path.prototype.base = function(current) { - var __this = this; - return _.reduce(this.parentsArray(current), function(acum, elem) { - var elemUrl; - var elemSelfLink = __this.config.getUrlFromElem(elem); - if (elemSelfLink) { - if (__this.config.isAbsoluteUrl(elemSelfLink)) { - return elemSelfLink; - } else { - elemUrl = elemSelfLink; - } - } else { - elemUrl = elem[__this.config.restangularFields.route]; - - if (elem[__this.config.restangularFields.restangularCollection]) { - var ids = elem[__this.config.restangularFields.ids]; - if (ids) { - elemUrl += '/' + ids.join(','); - } - } else { - var elemId; - if (__this.config.useCannonicalId) { - elemId = __this.config.getCannonicalIdFromElem(elem); - } else { - elemId = __this.config.getIdFromElem(elem); - } - - if (config.isValidId(elemId) && !elem.singleOne) { - elemUrl += '/' + (__this.config.encodeIds ? encodeURIComponent(elemId) : elemId); - } - } - } - acum = acum.replace(/\/$/, '') + '/' + elemUrl; - return __this.normalizeUrl(acum); - - }, this.config.baseUrl); - }; - - - - Path.prototype.fetchUrl = function(current, what) { - var baseUrl = this.base(current); - if (what) { - baseUrl += '/' + what; - } - return baseUrl; - }; - - Path.prototype.fetchRequestedUrl = function(current, what) { - var url = this.fetchUrl(current, what); - var params = current[config.restangularFields.reqParams]; - - // From here on and until the end of fetchRequestedUrl, - // the code has been kindly borrowed from angular.js - // The reason for such code bloating is coherence: - // If the user were to use this for cache management, the - // serialization of parameters would need to be identical - // to the one done by angular for cache keys to match. - function sortedKeys(obj) { - var keys = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - keys.push(key); - } - } - return keys.sort(); - } - - function forEachSorted(obj, iterator, context) { - var keys = sortedKeys(obj); - for (var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); - } - return keys; - } - - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); - } - - if (!params) { - return url + (this.config.suffix || ''); - } - - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || value === undefined) { - return; - } - if (!angular.isArray(value)) { - value = [value]; - } - - angular.forEach(value, function(v) { - if (angular.isObject(v)) { - v = angular.toJson(v); - } - parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(v)); - }); - }); - - return url + (this.config.suffix || '') + ((url.indexOf('?') === -1) ? '?' : '&') + parts.join('&'); - }; - - config.urlCreatorFactory.path = Path; - }; - - var globalConfiguration = {}; - - Configurer.init(this, globalConfiguration); - - - - this.$get = ['$http', '$q', function($http, $q) { - - function createServiceForConfiguration(config) { - var service = {}; - - var urlHandler = new config.urlCreatorFactory[config.urlCreator](); - urlHandler.setConfig(config); - - function restangularizeBase(parent, elem, route, reqParams, fromServer) { - elem[config.restangularFields.route] = route; - elem[config.restangularFields.getRestangularUrl] = _.bind(urlHandler.fetchUrl, urlHandler, elem); - elem[config.restangularFields.getRequestedUrl] = _.bind(urlHandler.fetchRequestedUrl, urlHandler, elem); - elem[config.restangularFields.addRestangularMethod] = _.bind(addRestangularMethodFunction, elem); - elem[config.restangularFields.clone] = _.bind(copyRestangularizedElement, elem, elem); - elem[config.restangularFields.reqParams] = _.isEmpty(reqParams) ? null : reqParams; - elem[config.restangularFields.withHttpConfig] = _.bind(withHttpConfig, elem); - elem[config.restangularFields.plain] = _.bind(stripRestangular, elem, elem); - - // Tag element as restangularized - elem[config.restangularFields.restangularized] = true; - - // RequestLess connection - elem[config.restangularFields.one] = _.bind(one, elem, elem); - elem[config.restangularFields.all] = _.bind(all, elem, elem); - elem[config.restangularFields.several] = _.bind(several, elem, elem); - elem[config.restangularFields.oneUrl] = _.bind(oneUrl, elem, elem); - elem[config.restangularFields.allUrl] = _.bind(allUrl, elem, elem); - - elem[config.restangularFields.fromServer] = !!fromServer; - - if (parent && config.shouldSaveParent(route)) { - var parentId = config.getIdFromElem(parent); - var parentUrl = config.getUrlFromElem(parent); - - var restangularFieldsForParent = _.union( - _.values(_.pick(config.restangularFields, ['route', 'singleOne', 'parentResource'])), - config.extraFields - ); - var parentResource = _.pick(parent, restangularFieldsForParent); - - if (config.isValidId(parentId)) { - config.setIdToElem(parentResource, parentId, route); - } - if (config.isValidId(parentUrl)) { - config.setUrlToElem(parentResource, parentUrl, route); - } - - elem[config.restangularFields.parentResource] = parentResource; - } else { - elem[config.restangularFields.parentResource] = null; - } - return elem; - } - - function one(parent, route, id, singleOne) { - var error; - if (_.isNumber(route) || _.isNumber(parent)) { - error = 'You\'re creating a Restangular entity with the number '; - error += 'instead of the route or the parent. For example, you can\'t call .one(12).'; - throw new Error(error); - } - if (_.isUndefined(route)) { - error = 'You\'re creating a Restangular entity either without the path. '; - error += 'For example you can\'t call .one(). Please check if your arguments are valid.'; - throw new Error(error); - } - var elem = {}; - config.setIdToElem(elem, id, route); - config.setFieldToElem(config.restangularFields.singleOne, elem, singleOne); - return restangularizeElem(parent, elem, route, false); - } - - - function all(parent, route) { - return restangularizeCollection(parent, [], route, false); - } - - function several(parent, route /*, ids */ ) { - var collection = []; - collection[config.restangularFields.ids] = Array.prototype.splice.call(arguments, 2); - return restangularizeCollection(parent, collection, route, false); - } - - function oneUrl(parent, route, url) { - if (!route) { - throw new Error('Route is mandatory when creating new Restangular objects.'); - } - var elem = {}; - config.setUrlToElem(elem, url, route); - return restangularizeElem(parent, elem, route, false); - } - - - function allUrl(parent, route, url) { - if (!route) { - throw new Error('Route is mandatory when creating new Restangular objects.'); - } - var elem = {}; - config.setUrlToElem(elem, url, route); - return restangularizeCollection(parent, elem, route, false); - } - // Promises - function restangularizePromise(promise, isCollection, valueToFill) { - promise.call = _.bind(promiseCall, promise); - promise.get = _.bind(promiseGet, promise); - promise[config.restangularFields.restangularCollection] = isCollection; - if (isCollection) { - promise.push = _.bind(promiseCall, promise, 'push'); - } - promise.$object = valueToFill; - if (config.restangularizePromiseInterceptor) { - config.restangularizePromiseInterceptor(promise); - } - return promise; - } - - function promiseCall(method) { - var deferred = $q.defer(); - var callArgs = arguments; - var filledValue = {}; - this.then(function(val) { - var params = Array.prototype.slice.call(callArgs, 1); - var func = val[method]; - func.apply(val, params); - filledValue = val; - deferred.resolve(val); - }); - return restangularizePromise(deferred.promise, this[config.restangularFields.restangularCollection], filledValue); - } - - function promiseGet(what) { - var deferred = $q.defer(); - var filledValue = {}; - this.then(function(val) { - filledValue = val[what]; - deferred.resolve(filledValue); - }); - return restangularizePromise(deferred.promise, this[config.restangularFields.restangularCollection], filledValue); - } - - function resolvePromise(deferred, response, data, filledValue) { - _.extend(filledValue, data); - - // Trigger the full response interceptor. - if (config.fullResponse) { - return deferred.resolve(_.extend(response, { - data: data - })); - } else { - deferred.resolve(data); - } - } - - - // Elements - function stripRestangular(elem) { - if (_.isArray(elem)) { - var array = []; - _.each(elem, function(value) { - array.push(config.isRestangularized(value) ? stripRestangular(value) : value); - }); - return array; - } else { - return _.omit(elem, _.values(_.omit(config.restangularFields, 'id'))); - } - } - - function addCustomOperation(elem) { - elem[config.restangularFields.customOperation] = _.bind(customFunction, elem); - var requestMethods = { - get: customFunction, - delete: customFunction - }; - _.each(['put', 'patch', 'post'], function(name) { - requestMethods[name] = function(operation, elem, path, params, headers) { - return _.bind(customFunction, this)(operation, path, params, headers, elem); - }; - }); - _.each(requestMethods, function(requestFunc, name) { - var callOperation = name === 'delete' ? 'remove' : name; - _.each(['do', 'custom'], function(alias) { - elem[alias + name.toUpperCase()] = _.bind(requestFunc, elem, callOperation); - }); - }); - elem[config.restangularFields.customGETLIST] = _.bind(fetchFunction, elem); - elem[config.restangularFields.doGETLIST] = elem[config.restangularFields.customGETLIST]; - } - - function copyRestangularizedElement(element) { - var copiedElement = angular.copy(element); - - // check if we're dealing with a collection (i.e. an array) - // and restangularize the element using the proper restangularizer, - // element / collection - if (_.isArray(element)) { - return restangularizeCollection( - element[config.restangularFields.parentResource], - copiedElement, - element[config.restangularFields.route], - element[config.restangularFields.fromServer], - element[config.restangularFields.reqParams] - ); - } - - // not a collection, restangularize it as an element - return restangularizeElem( - element[config.restangularFields.parentResource], - copiedElement, - element[config.restangularFields.route], - element[config.restangularFields.fromServer], - element[config.restangularFields.restangularCollection], - element[config.restangularFields.reqParams] - ); - } - - function restangularizeElem(parent, element, route, fromServer, collection, reqParams) { - var elem = config.onBeforeElemRestangularized(element, false, route); - - var localElem = restangularizeBase(parent, elem, route, reqParams, fromServer); - - if (config.useCannonicalId) { - localElem[config.restangularFields.cannonicalId] = config.getIdFromElem(localElem); - } - - if (collection) { - localElem[config.restangularFields.getParentList] = function() { - return collection; - }; - } - - localElem[config.restangularFields.restangularCollection] = false; - localElem[config.restangularFields.get] = _.bind(getFunction, localElem); - localElem[config.restangularFields.getList] = _.bind(fetchFunction, localElem); - localElem[config.restangularFields.put] = _.bind(putFunction, localElem); - localElem[config.restangularFields.post] = _.bind(postFunction, localElem); - localElem[config.restangularFields.remove] = _.bind(deleteFunction, localElem); - localElem[config.restangularFields.head] = _.bind(headFunction, localElem); - localElem[config.restangularFields.trace] = _.bind(traceFunction, localElem); - localElem[config.restangularFields.options] = _.bind(optionsFunction, localElem); - localElem[config.restangularFields.patch] = _.bind(patchFunction, localElem); - localElem[config.restangularFields.save] = _.bind(save, localElem); - - addCustomOperation(localElem); - return config.transformElem(localElem, false, route, service, true); - } - - function restangularizeCollection(parent, element, route, fromServer, reqParams) { - var elem = config.onBeforeElemRestangularized(element, true, route); - - var localElem = restangularizeBase(parent, elem, route, reqParams, fromServer); - localElem[config.restangularFields.restangularCollection] = true; - localElem[config.restangularFields.post] = _.bind(postFunction, localElem, null); - localElem[config.restangularFields.remove] = _.bind(deleteFunction, localElem); - localElem[config.restangularFields.head] = _.bind(headFunction, localElem); - localElem[config.restangularFields.trace] = _.bind(traceFunction, localElem); - localElem[config.restangularFields.putElement] = _.bind(putElementFunction, localElem); - localElem[config.restangularFields.options] = _.bind(optionsFunction, localElem); - localElem[config.restangularFields.patch] = _.bind(patchFunction, localElem); - localElem[config.restangularFields.get] = _.bind(getById, localElem); - localElem[config.restangularFields.getList] = _.bind(fetchFunction, localElem, null); - - addCustomOperation(localElem); - return config.transformElem(localElem, true, route, service, true); - } - - function restangularizeCollectionAndElements(parent, element, route, fromServer) { - var collection = restangularizeCollection(parent, element, route, fromServer); - _.each(collection, function(elem) { - if (elem) { - restangularizeElem(parent, elem, route, fromServer); - } - }); - return collection; - } - - function getById(id, reqParams, headers) { - return this.customGET(id.toString(), reqParams, headers); - } - - function putElementFunction(idx, params, headers) { - var __this = this; - var elemToPut = this[idx]; - var deferred = $q.defer(); - var filledArray = []; - filledArray = config.transformElem(filledArray, true, elemToPut[config.restangularFields.route], service); - elemToPut.put(params, headers).then(function(serverElem) { - var newArray = copyRestangularizedElement(__this); - newArray[idx] = serverElem; - filledArray = newArray; - deferred.resolve(newArray); - }, function(response) { - deferred.reject(response); - }); - - return restangularizePromise(deferred.promise, true, filledArray); - } - - function parseResponse(resData, operation, route, fetchUrl, response, deferred) { - var data = config.responseExtractor(resData, operation, route, fetchUrl, response, deferred); - var etag = response.headers('ETag'); - if (data && etag) { - data[config.restangularFields.etag] = etag; - } - return data; - } - - - function fetchFunction(what, reqParams, headers) { - var __this = this; - var deferred = $q.defer(); - var operation = 'getList'; - var url = urlHandler.fetchUrl(this, what); - var whatFetched = what || __this[config.restangularFields.route]; - - var request = config.fullRequestInterceptor(null, operation, - whatFetched, url, headers || {}, reqParams || {}, this[config.restangularFields.httpConfig] || {}); - - var filledArray = []; - filledArray = config.transformElem(filledArray, true, whatFetched, service); - - var method = 'getList'; - - if (config.jsonp) { - method = 'jsonp'; - } - - var okCallback = function(response) { - var resData = response.data; - var fullParams = response.config.params; - var data = parseResponse(resData, operation, whatFetched, url, response, deferred); - - // support empty response for getList() calls (some APIs respond with 204 and empty body) - if (_.isUndefined(data) || '' === data) { - data = []; - } - if (!_.isArray(data)) { - throw new Error('Response for getList SHOULD be an array and not an object or something else'); - } - - if (true === config.plainByDefault) { - return resolvePromise(deferred, response, data, filledArray); - } - - var processedData = _.map(data, function(elem) { - if (!__this[config.restangularFields.restangularCollection]) { - return restangularizeElem(__this, elem, what, true, data); - } else { - return restangularizeElem(__this[config.restangularFields.parentResource], - elem, __this[config.restangularFields.route], true, data); - } - }); - - processedData = _.extend(data, processedData); - - if (!__this[config.restangularFields.restangularCollection]) { - resolvePromise( - deferred, - response, - restangularizeCollection( - __this, - processedData, - what, - true, - fullParams - ), - filledArray - ); - } else { - resolvePromise( - deferred, - response, - restangularizeCollection( - __this[config.restangularFields.parentResource], - processedData, - __this[config.restangularFields.route], - true, - fullParams - ), - filledArray - ); - } - }; - - urlHandler.resource(this, $http, request.httpConfig, request.headers, request.params, what, - this[config.restangularFields.etag], operation)[method]().then(okCallback, function error(response) { - if (response.status === 304 && __this[config.restangularFields.restangularCollection]) { - resolvePromise(deferred, response, __this, filledArray); - } else if (_.every(config.errorInterceptors, function(cb) { - return cb(response, deferred, okCallback) !== false; - })) { - // triggered if no callback returns false - deferred.reject(response); - } - }); - - return restangularizePromise(deferred.promise, true, filledArray); - } - - function withHttpConfig(httpConfig) { - this[config.restangularFields.httpConfig] = httpConfig; - return this; - } - - function save(params, headers) { - if (this[config.restangularFields.fromServer]) { - return this[config.restangularFields.put](params, headers); - } else { - return _.bind(elemFunction, this)('post', undefined, params, undefined, headers); - } - } - - function elemFunction(operation, what, params, obj, headers) { - var __this = this; - var deferred = $q.defer(); - var resParams = params || {}; - var route = what || this[config.restangularFields.route]; - var fetchUrl = urlHandler.fetchUrl(this, what); - - var callObj = obj || this; - // fallback to etag on restangular object (since for custom methods we probably don't explicitly specify the etag field) - var etag = callObj[config.restangularFields.etag] || (operation !== 'post' ? this[config.restangularFields.etag] : null); - - if (_.isObject(callObj) && config.isRestangularized(callObj)) { - callObj = stripRestangular(callObj); - } - var request = config.fullRequestInterceptor(callObj, operation, route, fetchUrl, - headers || {}, resParams || {}, this[config.restangularFields.httpConfig] || {}); - - var filledObject = {}; - filledObject = config.transformElem(filledObject, false, route, service); - - var okCallback = function(response) { - var resData = response.data; - var fullParams = response.config.params; - var elem = parseResponse(resData, operation, route, fetchUrl, response, deferred); - - // accept 0 as response - if (elem !== null && elem !== undefined && elem !== '') { - var data; - - if (true === config.plainByDefault) { - return resolvePromise(deferred, response, elem, filledObject); - } - - if (operation === 'post' && !__this[config.restangularFields.restangularCollection]) { - data = restangularizeElem( - __this[config.restangularFields.parentResource], - elem, - route, - true, - null, - fullParams - ); - resolvePromise(deferred, response, data, filledObject); - } else { - data = restangularizeElem( - __this[config.restangularFields.parentResource], - elem, - __this[config.restangularFields.route], - true, - null, - fullParams - ); - - data[config.restangularFields.singleOne] = __this[config.restangularFields.singleOne]; - resolvePromise(deferred, response, data, filledObject); - } - - } else { - resolvePromise(deferred, response, undefined, filledObject); - } - }; - - var errorCallback = function(response) { - if (response.status === 304 && config.isSafe(operation)) { - resolvePromise(deferred, response, __this, filledObject); - } else if (_.every(config.errorInterceptors, function(cb) { - return cb(response, deferred, okCallback) !== false; - })) { - // triggered if no callback returns false - deferred.reject(response); - } - }; - // Overriding HTTP Method - var callOperation = operation; - var callHeaders = _.extend({}, request.headers); - var isOverrideOperation = config.isOverridenMethod(operation); - if (isOverrideOperation) { - callOperation = 'post'; - callHeaders = _.extend(callHeaders, { - 'X-HTTP-Method-Override': operation === 'remove' ? 'DELETE' : operation.toUpperCase() - }); - } else if (config.jsonp && callOperation === 'get') { - callOperation = 'jsonp'; - } - - if (config.isSafe(operation)) { - if (isOverrideOperation) { - urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params, - what, etag, callOperation)[callOperation]({}).then(okCallback, errorCallback); - } else { - urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params, - what, etag, callOperation)[callOperation]().then(okCallback, errorCallback); - } - } else { - urlHandler.resource(this, $http, request.httpConfig, callHeaders, request.params, - what, etag, callOperation)[callOperation](request.element).then(okCallback, errorCallback); - } - - return restangularizePromise(deferred.promise, false, filledObject); - } - - function getFunction(params, headers) { - return _.bind(elemFunction, this)('get', undefined, params, undefined, headers); - } - - function deleteFunction(params, headers) { - return _.bind(elemFunction, this)('remove', undefined, params, undefined, headers); - } - - function putFunction(params, headers) { - return _.bind(elemFunction, this)('put', undefined, params, undefined, headers); - } - - function postFunction(what, elem, params, headers) { - return _.bind(elemFunction, this)('post', what, params, elem, headers); - } - - function headFunction(params, headers) { - return _.bind(elemFunction, this)('head', undefined, params, undefined, headers); - } - - function traceFunction(params, headers) { - return _.bind(elemFunction, this)('trace', undefined, params, undefined, headers); - } - - function optionsFunction(params, headers) { - return _.bind(elemFunction, this)('options', undefined, params, undefined, headers); - } - - function patchFunction(elem, params, headers) { - return _.bind(elemFunction, this)('patch', undefined, params, elem, headers); - } - - function customFunction(operation, path, params, headers, elem) { - return _.bind(elemFunction, this)(operation, path, params, elem, headers); - } - - function addRestangularMethodFunction(name, operation, path, defaultParams, defaultHeaders, defaultElem) { - var bindedFunction; - if (operation === 'getList') { - bindedFunction = _.bind(fetchFunction, this, path); - } else { - bindedFunction = _.bind(customFunction, this, operation, path); - } - - var createdFunction = function(params, headers, elem) { - var callParams = _.defaults({ - params: params, - headers: headers, - elem: elem - }, { - params: defaultParams, - headers: defaultHeaders, - elem: defaultElem - }); - return bindedFunction(callParams.params, callParams.headers, callParams.elem); - }; - - if (config.isSafe(operation)) { - this[name] = createdFunction; - } else { - this[name] = function(elem, params, headers) { - return createdFunction(params, headers, elem); - }; - } - } - - function withConfigurationFunction(configurer) { - var newConfig = angular.copy(_.omit(config, 'configuration')); - Configurer.init(newConfig, newConfig); - configurer(newConfig); - return createServiceForConfiguration(newConfig); - } - - function toService(route, parent) { - var knownCollectionMethods = _.values(config.restangularFields); - var serv = {}; - var collection = (parent || service).all(route); - serv.one = _.bind(one, (parent || service), parent, route); - serv.post = _.bind(collection.post, collection); - serv.getList = _.bind(collection.getList, collection); - serv.withHttpConfig = _.bind(collection.withHttpConfig, collection); - serv.get = _.bind(collection.get, collection); - - for (var prop in collection) { - if (collection.hasOwnProperty(prop) && _.isFunction(collection[prop]) && !_.includes(knownCollectionMethods, prop)) { - serv[prop] = _.bind(collection[prop], collection); - } - } - - return serv; - } - - - Configurer.init(service, config); - - service.copy = _.bind(copyRestangularizedElement, service); - - service.service = _.bind(toService, service); - - service.withConfig = _.bind(withConfigurationFunction, service); - - service.one = _.bind(one, service, null); - - service.all = _.bind(all, service, null); - - service.several = _.bind(several, service, null); - - service.oneUrl = _.bind(oneUrl, service, null); - - service.allUrl = _.bind(allUrl, service, null); - - service.stripRestangular = _.bind(stripRestangular, service); - - service.restangularizeElement = _.bind(restangularizeElem, service); - - service.restangularizeCollection = _.bind(restangularizeCollectionAndElements, service); - - return service; - } - - return createServiceForConfiguration(globalConfiguration); - }]; - }); - return restangular.name; -})); diff --git a/static/js/run_prettify.js b/static/js/run_prettify.js index 8204930..427074a 100644 --- a/static/js/run_prettify.js +++ b/static/js/run_prettify.js @@ -1,63 +1,1998 @@ -!function(){/* +/** + * @license + * Copyright (C) 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - Copyright (C) 2013 Google Inc. +/** + * @fileoverview + * <div style="white-space: pre"> + * Looks at query parameters to decide which language handlers and style-sheets + * to load. + * + * Query Parameter Format Effect Default + * +------------------+---------------+------------------------------+--------+ + * | autorun= | true | false | If true then prettyPrint() | "true" | + * | | | is called on page load. | | + * +------------------+---------------+------------------------------+--------+ + * | lang= | language name | Loads the language handler | Can | + * | | | named "lang-<NAME>.js". | appear | + * | | | See available handlers at | many | + * | | | https://github.com/google/ | times. | + * | | | code-prettify/tree/master/ | | + * | | | src | | + * +------------------+---------------+------------------------------+--------+ + * | skin= | skin name | Loads the skin stylesheet | none. | + * | | | named "<NAME>.css". | | + * | | | https://cdn.rawgit.com/ | | + * | | | google/code-prettify/master/ | | + * | | | styles/index.html | | + * +------------------+---------------+------------------------------+--------+ + * | callback= | JS identifier | When "prettyPrint" finishes | none | + * | | | window.exports[js_ident] is | | + * | | | called. | | + * | | | The callback must be under | | + * | | | exports to reduce the risk | | + * | | | of XSS via query parameter | | + * | | | injection. | | + * +------------------+---------------+------------------------------+--------+ + * + * Exmaples + * .../run_prettify.js?lang=css&skin=sunburst + * 1. Loads the CSS language handler which can be used to prettify CSS + * stylesheets, HTML <style> element bodies and style="..." attributes + * values. + * 2. Loads the sunburst.css stylesheet instead of the default prettify.css + * stylesheet. + * A gallery of stylesheets is available at + * https://cdn.rawgit.com/google/code-prettify/master/styles/index.html + * 3. Since autorun=false is not specified, calls prettyPrint() on page load. + * </div> + */ - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +/** +* @typedef {!Array.<number|string>} +* Alternating indices and the decorations that should be inserted there. +* The indices are monotonically increasing. +*/ +var DecorationsT; + +/** +* @typedef {!{ +* sourceNode: !Element, +* pre: !(number|boolean), +* langExtension: ?string, +* numberLines: ?(number|boolean), +* sourceCode: ?string, +* spans: ?(Array.<number|Node>), +* basePos: ?number, +* decorations: ?DecorationsT +* }} +* <dl> +* <dt>sourceNode<dd>the element containing the source +* <dt>sourceCode<dd>source as plain text +* <dt>pre<dd>truthy if white-space in text nodes +* should be considered significant. +* <dt>spans<dd> alternating span start indices into source +* and the text node or element (e.g. {@code <BR>}) corresponding to that +* span. +* <dt>decorations<dd>an array of style classes preceded +* by the position at which they start in job.sourceCode in order +* <dt>basePos<dd>integer position of this.sourceCode in the larger chunk of +* source. +* </dl> +*/ +var JobT; - http://www.apache.org/licenses/LICENSE-2.0 +/** +* @typedef {!{ +* sourceCode: string, +* spans: !(Array.<number|Node>) +* }} +* <dl> +* <dt>sourceCode<dd>source as plain text +* <dt>spans<dd> alternating span start indices into source +* and the text node or element (e.g. {@code <BR>}) corresponding to that +* span. +* </dl> +*/ +var SourceSpansT; - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +/** @define {boolean} */ +var IN_GLOBAL_SCOPE = false; - Copyright (C) 2006 Google Inc. +(function () { + "use strict"; - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at + var win = window; + var doc = document; + var root = doc.documentElement; + var head = doc['head'] || doc.getElementsByTagName("head")[0] || root; - http://www.apache.org/licenses/LICENSE-2.0 + // From http://javascript.nwbox.com/ContentLoaded/contentloaded.js + // Author: Diego Perini (diego.perini at gmail.com) + // Summary: cross-browser wrapper for DOMContentLoaded + // Updated: 20101020 + // License: MIT + // Version: 1.2 + function contentLoaded(callback) { + var addEventListener = doc['addEventListener']; + var done = false, top = true, + add = addEventListener ? 'addEventListener' : 'attachEvent', + rem = addEventListener ? 'removeEventListener' : 'detachEvent', + pre = addEventListener ? '' : 'on', - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -(function(){function ba(g){function k(){try{M.doScroll("left")}catch(g){t.setTimeout(k,50);return}z("poll")}function z(k){if("readystatechange"!=k.type||"complete"==A.readyState)("load"==k.type?t:A)[B](p+k.type,z,!1),!q&&(q=!0)&&g.call(t,k.type||k)}var Y=A.addEventListener,q=!1,C=!0,x=Y?"addEventListener":"attachEvent",B=Y?"removeEventListener":"detachEvent",p=Y?"":"on";if("complete"==A.readyState)g.call(t,"lazy");else{if(A.createEventObject&&M.doScroll){try{C=!t.frameElement}catch(da){}C&&k()}A[x](p+ -"DOMContentLoaded",z,!1);A[x](p+"readystatechange",z,!1);t[x](p+"load",z,!1)}}function U(){V&&ba(function(){var g=N.length;ca(g?function(){for(var k=0;k<g;++k)(function(g){t.setTimeout(function(){t.exports[N[g]].apply(t,arguments)},0)})(k)}:void 0)})}for(var t=window,A=document,M=A.documentElement,O=A.head||A.getElementsByTagName("head")[0]||M,B="",F=A.getElementsByTagName("script"),q=F.length;0<=--q;){var P=F[q],Z=P.src.match(/^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(Z){B=Z[1]||"";P.parentNode.removeChild(P); -break}}var V=!0,H=[],Q=[],N=[];B.replace(/[?&]([^&=]+)=([^&]+)/g,function(g,k,z){z=decodeURIComponent(z);k=decodeURIComponent(k);"autorun"==k?V=!/^[0fn]/i.test(z):"lang"==k?H.push(z):"skin"==k?Q.push(z):"callback"==k&&N.push(z)});q=0;for(B=H.length;q<B;++q)(function(){var g=A.createElement("script");g.onload=g.onerror=g.onreadystatechange=function(){!g||g.readyState&&!/loaded|complete/.test(g.readyState)||(g.onerror=g.onload=g.onreadystatechange=null,--T,T||t.setTimeout(U,0),g.parentNode&&g.parentNode.removeChild(g), -g=null)};g.type="text/javascript";g.src="../css/loader/lang-"+encodeURIComponent(H[q])+".js";O.insertBefore(g,O.firstChild)})(H[q]);for(var T=H.length,F=[],q=0,B=Q.length;q<B;++q)F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/skins/"+encodeURIComponent(Q[q])+".css");F.push("../css/prettify.css");(function(g){function k(q){if(q!==z){var t=A.createElement("link");t.rel="stylesheet";t.type= -"text/css";q+1<z&&(t.error=t.onerror=function(){k(q+1)});t.href=g[q];O.appendChild(t)}}var z=g.length;k(0)})(F);var ca=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var g;(function(){function k(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=W[a])?b:"0"<=a&&"7">=a?parseInt(e.substring(1),8):"u"===a||"x"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"=== -e||"]"===e||"^"===e?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\s\S]|-|[^-\\]/g);e=[];var a="^"===b[0],c=["["];a&&c.push("^");for(var a=a?1:0,h=b.length;a<h;++a){var l=b[a];if(/\\[bdsw]/i.test(l))c.push(l);else{var l=d(l),n;a+2<h&&"-"===b[a+1]?(n=d(b[a+2]),a+=2):n=l;e.push([l,n]);65>n||122<l||(65>n||90<l||e.push([Math.max(65,l)|32,Math.min(n,90)|32]),97>n||122<l||e.push([Math.max(97,l)&-33,Math.min(n,122)&-33]))}}e.sort(function(e, -a){return e[0]-a[0]||a[1]-e[1]});b=[];h=[];for(a=0;a<e.length;++a)l=e[a],l[0]<=h[1]+1?h[1]=Math.max(h[1],l[1]):b.push(h=l);for(a=0;a<b.length;++a)l=b[a],c.push(f(l[0])),l[1]>l[0]&&(l[1]+1>l[0]&&c.push("-"),c.push(f(l[1])));c.push("]");return c.join("")}function g(e){for(var a=e.source.match(/(?:\[(?:[^\x5C\x5D]|\\[\s\S])*\]|\\u[A-Fa-f0-9]{4}|\\x[A-Fa-f0-9]{2}|\\[0-9]+|\\[^ux0-9]|\(\?[:!=]|[\(\)\^]|[^\x5B\x5C\(\)\^]+)/g),c=a.length,d=[],h=0,l=0;h<c;++h){var n=a[h];"("===n?++l:"\\"===n.charAt(0)&&(n= -+n.substring(1))&&(n<=l?d[n]=-1:a[h]=f(n))}for(h=1;h<d.length;++h)-1===d[h]&&(d[h]=++k);for(l=h=0;h<c;++h)n=a[h],"("===n?(++l,d[l]||(a[h]="(?:")):"\\"===n.charAt(0)&&(n=+n.substring(1))&&n<=l&&(a[h]="\\"+d[n]);for(h=0;h<c;++h)"^"===a[h]&&"^"!==a[h+1]&&(a[h]="");if(e.ignoreCase&&I)for(h=0;h<c;++h)n=a[h],e=n.charAt(0),2<=n.length&&"["===e?a[h]=b(n):"\\"!==e&&(a[h]=n.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var k=0,I=!1, -m=!1,J=0,c=a.length;J<c;++J){var r=a[J];if(r.ignoreCase)m=!0;else if(/[a-z]/i.test(r.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){I=!0;m=!1;break}}for(var W={b:8,t:9,n:10,v:11,f:12,r:13},u=[],J=0,c=a.length;J<c;++J){r=a[J];if(r.global||r.multiline)throw Error(""+r);u.push("(?:"+g(r)+")")}return new RegExp(u.join("|"),m?"gi":"g")}function q(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if("br"=== -c||"li"===c)g[m]="\n",I[m<<1]=k++,I[m++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[ \t\r\n]+/g," "),g[m]=c,I[m<<1]=k,k+=c.length,I[m++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,g=[],k=0,I=[],m=0;f(a);return{a:g.join("").replace(/\n$/,""),c:I}}function t(a,d,f,b,g){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),g.push.apply(g,a.g))}function A(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?T.test(f.nodeValue)? -a:d:d;return d===a?void 0:d}function C(a,d){function f(a){for(var m=a.i,k=a.h,c=[m,"pln"],r=0,W=a.a.match(g)||[],u={},e=0,q=W.length;e<q;++e){var D=W[e],w=u[D],h=void 0,l;if("string"===typeof w)l=!1;else{var n=b[D.charAt(0)];if(n)h=D.match(n[1]),w=n[0];else{for(l=0;l<p;++l)if(n=d[l],h=D.match(n[1])){w=n[0];break}h||(w="pln")}!(l=5<=w.length&&"lang-"===w.substring(0,5))||h&&"string"===typeof h[1]||(l=!1,w="src");l||(u[D]=w)}n=r;r+=D.length;if(l){l=h[1];var E=D.indexOf(l),G=E+l.length;h[2]&&(G=D.length- -h[2].length,E=G-l.length);w=w.substring(5);t(k,m+n,D.substring(0,E),f,c);t(k,m+n+E,l,F(w,l),c);t(k,m+n+G,D.substring(G),f,c)}else c.push(m+n,w)}a.g=c}var b={},g;(function(){for(var f=a.concat(d),m=[],p={},c=0,r=f.length;c<r;++c){var q=f[c],u=q[3];if(u)for(var e=u.length;0<=--e;)b[u.charAt(e)]=q;q=q[1];u=""+q;p.hasOwnProperty(u)||(m.push(q),p[u]=null)}m.push(/[\0-\uffff]/);g=k(m)})();var p=d.length;return f}function x(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, -null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/, -null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(b=a.regexLiterals){var g=(b=1<b?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+ -("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+g+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+g+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&f.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&f.push(["kwd",new RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i, -null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(b),null]);return C(d,f)}function B(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!k.test(a.className))if("br"===a.nodeName)g(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,p=d.match(q);p&&(c=d.substring(0,p.index),a.nodeValue=c,(d=d.substring(p.index+p[0].length))&& -a.parentNode.insertBefore(m.createTextNode(d),a.nextSibling),g(a),c||a.parentNode.removeChild(a))}}function g(a){function b(a,c){var d=c?a.cloneNode(!1):a,n=a.parentNode;if(n){var n=b(n,1),e=a.nextSibling;n.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,n.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var k=/(?:^|\s)nocode(?:\s|$)/,q=/\r\n?|\n/,m=a.ownerDocument,p=m.createElement("li");a.firstChild;)p.appendChild(a.firstChild); -for(var c=[p],r=0;r<c.length;++r)b(c[r]);d===(d|0)&&c[0].setAttribute("value",d);var t=m.createElement("ol");t.className="linenums";d=Math.max(0,d-1|0)||0;for(var r=0,u=c.length;r<u;++r)p=c[r],p.className="L"+(r+d)%10,p.firstChild||p.appendChild(m.createTextNode("\u00a0")),t.appendChild(p);a.appendChild(t)}function p(a,d){for(var f=d.length;0<=--f;){var b=d[f];X.hasOwnProperty(b)?R.console&&console.warn("cannot override language handler %s",b):X[b]=a}}function F(a,d){a&&X.hasOwnProperty(a)||(a=/^\s*</.test(d)? -"default-markup":"default-code");return X[a]}function H(a){var d=a.j;try{var f=q(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;F(d,b)(a);var g=/\bMSIE\s(\d+)/.exec(navigator.userAgent),g=g&&8>=+g[1],d=/\n/g,p=a.a,k=p.length,f=0,m=a.c,t=m.length,b=0,c=a.g,r=c.length,x=0;c[r]=k;var u,e;for(e=u=0;e<r;)c[e]!==c[e+2]?(c[u++]=c[e++],c[u++]=c[e++]):e+=2;r=u;for(e=u=0;e<r;){for(var A=c[e],D=c[e+1],w=e+2;w+2<=r&&c[w+1]===D;)w+=2;c[u++]=A;c[u++]=D;e=w}c.length=u;var h=a.h;a="";h&&(a=h.style.display,h.style.display="none"); -try{for(;b<t;){var l=m[b+2]||k,n=c[x+2]||k,w=Math.min(l,n),E=m[b+1],G;if(1!==E.nodeType&&(G=p.substring(f,w))){g&&(G=G.replace(d,"\r"));E.nodeValue=G;var aa=E.ownerDocument,v=aa.createElement("span");v.className=c[x+1];var B=E.parentNode;B.replaceChild(v,E);v.appendChild(E);f<l&&(m[b+1]=E=aa.createTextNode(p.substring(w,l)),B.insertBefore(E,v.nextSibling))}f=w;f>=l&&(b+=2);f>=n&&(x+=2)}}finally{h&&(h.style.display=a)}}catch(y){R.console&&console.log(y&&y.stack||y)}}var R=window,K=["break,continue,do,else,for,if,return,while"], -L=[[K,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],S=[L,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"], -M=[L,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],N=[L,"abstract,as,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],L=[L,"debugger,eval,export,function,get,instanceof,null,set,undefined,var,with,Infinity,NaN"], -O=[K,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],P=[K,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],K=[K,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, -T=/\S/,U=x({keywords:[S,N,M,L,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",O,P,K],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),X={};p(U,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", -/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));p(C([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/], -["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\s\S]+/]]),["uq.val"]);p(x({keywords:S,hashComments:!0,cStyleComments:!0,types:Q}),"c cc cpp cxx cyc m".split(" "));p(x({keywords:"null,true,false"}),["json"]);p(x({keywords:N,hashComments:!0,cStyleComments:!0, -verbatimStrings:!0,types:Q}),["cs"]);p(x({keywords:M,cStyleComments:!0}),["java"]);p(x({keywords:K,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(x({keywords:O,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(x({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}), -["perl","pl","pm"]);p(x({keywords:P,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(x({keywords:L,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(x({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(C([],[["str",/^[\s\S]+/]]),["regex"]); -var V=R.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,f){f=f||!1;d=d||null;var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;f&&B(b,f,!0);H({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML}, -prettyPrint:g=g=function(a,d){function f(){for(var b=R.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;r<p.length&&c.now()<b;r++){for(var d=p[r],k=h,q=d;q=q.previousSibling;){var m=q.nodeType,v=(7===m||8===m)&&q.nodeValue;if(v?!/^\??prettify\b/.test(v):3!==m||/\S/.test(q.nodeValue))break;if(v){k={};v.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){k[b]=c});break}}q=d.className;if((k!==h||u.test(q))&&!e.test(q)){m=!1;for(v=d.parentNode;v;v=v.parentNode)if(w.test(v.tagName)&&v.className&&u.test(v.className)){m= -!0;break}if(!m){d.className+=" prettyprinted";m=k.lang;if(!m){var m=q.match(t),C;!m&&(C=A(d))&&z.test(C.tagName)&&(m=C.className.match(t));m&&(m=m[1])}if(x.test(d.tagName))v=1;else var v=d.currentStyle,y=g.defaultView,v=(v=v?v.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===v.substring(0,3);y=k.linenums;(y="true"===y||+y)||(y=(y=q.match(/\blinenums\b(?::(\d+))?/))?y[1]&&y[1].length?+y[1]:!0:!1);y&&B(d,y,v);H({j:m,h:d,m:y,l:v,a:null,i:null,c:null, -g:null})}}}r<p.length?R.setTimeout(f,250):"function"===typeof a&&a()}for(var b=d||document.body,g=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],k=0;k<b.length;++k)for(var m=0,q=b[k].length;m<q;++m)p.push(b[k][m]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var r=0,t=/\blang(?:uage)?-([\w.]+)(?!\S)/,u=/\bprettyprint\b/,e=/\bprettyprinted\b/,x=/pre|xmp/i,z=/^code$/i,w=/^(?:pre|code|xmp)$/i,h={};f()}}, -S=R.define;"function"===typeof S&&S.amd&&S("google-code-prettify",[],function(){return V})})();return g}();T||t.setTimeout(U,0)})();}() + init = function(e) { + if (e.type == 'readystatechange' && doc.readyState != 'complete') { + return; + } + (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false); + if (!done && (done = true)) { callback.call(win, e.type || e); } + }, + + poll = function() { + try { + root.doScroll('left'); + } catch(e) { + win.setTimeout(poll, 50); + return; + } + init('poll'); + }; + + if (doc.readyState == 'complete') { + callback.call(win, 'lazy'); + } else { + if (doc.createEventObject && root.doScroll) { + try { top = !win.frameElement; } catch(e) { } + if (top) { poll(); } + } + doc[add](pre + 'DOMContentLoaded', init, false); + doc[add](pre + 'readystatechange', init, false); + win[add](pre + 'load', init, false); + } + } + + // Given a list of URLs to stylesheets, loads the first that loads without + // triggering an error event. + function loadStylesheetsFallingBack(stylesheets) { + var n = stylesheets.length; + function load(i) { + if (i === n) { return; } + var link = doc.createElement('link'); + link.rel = 'stylesheet'; + link.type = 'text/css'; + if (i + 1 < n) { + // http://pieisgood.org/test/script-link-events/ indicates that many + // versions of IE do not support onerror on <link>s, though + // http://msdn.microsoft.com/en-us/library/ie/ms535848(v=vs.85).aspx + // indicates that recent IEs do support error. + link.error = link.onerror = function () { load(i + 1); }; + } + link.href = stylesheets[i]; + head.appendChild(link); + } + load(0); + } + + var scriptQuery = ''; + // Look for the <script> node that loads this script to get its parameters. + // This starts looking at the end instead of just considering the last + // because deferred and async scripts run out of order. + // If the script is loaded twice, then this will run in reverse order. + var scripts = doc.getElementsByTagName('script'); + for (var i = scripts.length; --i >= 0;) { + var script = scripts[i]; + var match = script.src.match( + /^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/); + if (match) { + scriptQuery = match[1] || ''; + // Remove the script from the DOM so that multiple runs at least run + // multiple times even if parameter sets are interpreted in reverse + // order. + script.parentNode.removeChild(script); + break; + } + } + + // Pull parameters into local variables. + var autorun = true; + var langs = []; + var skins = []; + var callbacks = []; + scriptQuery.replace( + /[?&]([^&=]+)=([^&]+)/g, + function (_, name, value) { + value = decodeURIComponent(value); + name = decodeURIComponent(name); + if (name == 'autorun') { autorun = !/^[0fn]/i.test(value); } else + if (name == 'lang') { langs.push(value); } else + if (name == 'skin') { skins.push(value); } else + if (name == 'callback') { callbacks.push(value); } + }); + + // Use https to avoid mixed content warnings in client pages and to + // prevent a MITM from rewrite prettify mid-flight. + // This only works if this script is loaded via https : something + // over which we exercise no control. + var LOADER_BASE_URL = + 'https://cdn.rawgit.com/google/code-prettify/master/loader'; + + for (var i = 0, n = langs.length; i < n; ++i) (function (lang) { + var script = doc.createElement("script"); + + // Excerpted from jQuery.ajaxTransport("script") to fire events when + // a script is finished loading. + // Attach handlers for each script + script.onload = script.onerror = script.onreadystatechange = function () { + if (script && ( + !script.readyState || /loaded|complete/.test(script.readyState))) { + // Handle memory leak in IE + script.onerror = script.onload = script.onreadystatechange = null; + + --pendingLanguages; + checkPendingLanguages(); + + // Remove the script + if (script.parentNode) { + script.parentNode.removeChild(script); + } + + script = null; + } + }; + + script.type = 'text/javascript'; + script.src = LOADER_BASE_URL + + '/lang-' + encodeURIComponent(langs[i]) + '.js'; + + // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending + head.insertBefore(script, head.firstChild); + })(langs[i]); + + var pendingLanguages = langs.length; + function checkPendingLanguages() { + if (!pendingLanguages) { + win.setTimeout(onLangsLoaded, 0); + } + } + + var skinUrls = []; + for (var i = 0, n = skins.length; i < n; ++i) { + skinUrls.push(LOADER_BASE_URL + + '/skins/' + encodeURIComponent(skins[i]) + '.css'); + } + skinUrls.push(LOADER_BASE_URL + '/prettify.css'); + loadStylesheetsFallingBack(skinUrls); + + var prettyPrint = (function () { + /** + * @license + * Copyright (C) 2006 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + * + * <p> + * For a fairly comprehensive set of languages see the + * <a href="https://github.com/google/code-prettify#for-which-languages-does-it-work">README</a> + * file that came with this source. At a minimum, the lexer should work on a + * number of languages including C and friends, Java, Python, Bash, SQL, HTML, + * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk + * and a subset of Perl, but, because of commenting conventions, doesn't work on + * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. + * <p> + * Usage: <ol> + * <li> include this source file in an html page via + * {@code <script type="text/javascript" src="/path/to/prettify.js"></script>} + * <li> define style rules. See the example page for examples. + * <li> mark the {@code <pre>} and {@code <code>} tags in your source with + * {@code class=prettyprint.} + * You can also use the (html deprecated) {@code <xmp>} tag, but the pretty + * printer needs to do more substantial DOM manipulations to support that, so + * some css styles may not be preserved. + * </ol> + * That's it. I wanted to keep the API as simple as possible, so there's no + * need to specify which language the code is in, but if you wish, you can add + * another class to the {@code <pre>} or {@code <code>} element to specify the + * language, as in {@code <pre class="prettyprint lang-java">}. Any class that + * starts with "lang-" followed by a file extension, specifies the file type. + * See the "lang-*.js" files in this directory for code that implements + * per-language file handlers. + * <p> + * Change log:<br> + * cbeust, 2006/08/22 + * <blockquote> + * Java annotations (start with "@") are now captured as literals ("lit") + * </blockquote> + * @requires console + */ + + // JSLint declarations + /*global console, document, navigator, setTimeout, window, define */ + + + var HACK_TO_FIX_JS_INCLUDE_PL; + + /** + * {@type !{ + * 'createSimpleLexer': function (Array, Array): (function (JobT)), + * 'registerLangHandler': function (function (JobT), Array.<string>), + * 'PR_ATTRIB_NAME': string, + * 'PR_ATTRIB_NAME': string, + * 'PR_ATTRIB_VALUE': string, + * 'PR_COMMENT': string, + * 'PR_DECLARATION': string, + * 'PR_KEYWORD': string, + * 'PR_LITERAL': string, + * 'PR_NOCODE': string, + * 'PR_PLAIN': string, + * 'PR_PUNCTUATION': string, + * 'PR_SOURCE': string, + * 'PR_STRING': string, + * 'PR_TAG': string, + * 'PR_TYPE': string, + * 'prettyPrintOne': function (string, string, number|boolean), + * 'prettyPrint': function (?function, ?(HTMLElement|HTMLDocument)) + * }} + * @const + */ + var PR; + + /** + * Split {@code prettyPrint} into multiple timeouts so as not to interfere with + * UI events. + * If set to {@code false}, {@code prettyPrint()} is synchronous. + */ + window['PR_SHOULD_USE_CONTINUATION'] = true; + + /** + * Pretty print a chunk of code. + * @param {string} sourceCodeHtml The HTML to pretty print. + * @param {string} opt_langExtension The language name to use. + * Typically, a filename extension like 'cpp' or 'java'. + * @param {number|boolean} opt_numberLines True to number lines, + * or the 1-indexed number of the first line in sourceCodeHtml. + * @return {string} code as html, but prettier + */ + var prettyPrintOne; + /** + * Find all the {@code <pre>} and {@code <code>} tags in the DOM with + * {@code class=prettyprint} and prettify them. + * + * @param {Function} opt_whenDone called when prettifying is done. + * @param {HTMLElement|HTMLDocument} opt_root an element or document + * containing all the elements to pretty print. + * Defaults to {@code document.body}. + */ + var prettyPrint; + + + (function () { + var win = window; + // Keyword lists for various languages. + // We use things that coerce to strings to make them compact when minified + // and to defeat aggressive optimizers that fold large string constants. + var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"]; + var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + + "double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed," + + "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"]; + var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," + + "new,operator,private,protected,public,this,throw,true,try,typeof"]; + var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignas,alignof,align_union,asm,axiom,bool," + + "concept,concept_map,const_cast,constexpr,decltype,delegate," + + "dynamic_cast,explicit,export,friend,generic,late_check," + + "mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert," + + "static_cast,template,typeid,typename,using,virtual,where"]; + var JAVA_KEYWORDS = [COMMON_KEYWORDS, + "abstract,assert,boolean,byte,extends,finally,final,implements,import," + + "instanceof,interface,null,native,package,strictfp,super,synchronized," + + "throws,transient"]; + var CSHARP_KEYWORDS = [COMMON_KEYWORDS, + "abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending," + + "dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface," + + "internal,into,is,join,let,lock,null,object,out,override,orderby,params," + + "partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong," + + "unchecked,unsafe,ushort,value,var,virtual,where,yield"]; + var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," + + "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," + + "throw,true,try,unless,until,when,while,yes"; + var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS, + "abstract,async,await,constructor,debugger,enum,eval,export,function," + + "get,implements,instanceof,interface,let,null,set,undefined,var,with," + + "yield,Infinity,NaN"]; + var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," + + "goto,if,import,last,local,my,next,no,our,print,package,redo,require," + + "sub,undef,unless,until,use,wantarray,while,BEGIN,END"; + var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," + + "elif,except,exec,finally,from,global,import,in,is,lambda," + + "nonlocal,not,or,pass,print,raise,try,with,yield," + + "False,True,None"]; + var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," + + "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," + + "rescue,retry,self,super,then,true,undef,unless,until,when,yield," + + "BEGIN,END"]; + var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," + + "function,in,local,set,then,until"]; + var ALL_KEYWORDS = [ + CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, JSCRIPT_KEYWORDS, + PERL_KEYWORDS, PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS]; + var C_TYPES = /^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/; + + // token style names. correspond to css classes + /** + * token style for a string literal + * @const + */ + var PR_STRING = 'str'; + /** + * token style for a keyword + * @const + */ + var PR_KEYWORD = 'kwd'; + /** + * token style for a comment + * @const + */ + var PR_COMMENT = 'com'; + /** + * token style for a type + * @const + */ + var PR_TYPE = 'typ'; + /** + * token style for a literal value. e.g. 1, null, true. + * @const + */ + var PR_LITERAL = 'lit'; + /** + * token style for a punctuation string. + * @const + */ + var PR_PUNCTUATION = 'pun'; + /** + * token style for plain text. + * @const + */ + var PR_PLAIN = 'pln'; + + /** + * token style for an sgml tag. + * @const + */ + var PR_TAG = 'tag'; + /** + * token style for a markup declaration such as a DOCTYPE. + * @const + */ + var PR_DECLARATION = 'dec'; + /** + * token style for embedded source. + * @const + */ + var PR_SOURCE = 'src'; + /** + * token style for an sgml attribute name. + * @const + */ + var PR_ATTRIB_NAME = 'atn'; + /** + * token style for an sgml attribute value. + * @const + */ + var PR_ATTRIB_VALUE = 'atv'; + + /** + * A class that indicates a section of markup that is not code, e.g. to allow + * embedding of line numbers within code listings. + * @const + */ + var PR_NOCODE = 'nocode'; + + + + /** + * A set of tokens that can precede a regular expression literal in + * javascript + * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html + * has the full list, but I've removed ones that might be problematic when + * seen in languages that don't support regular expression literals. + * + * <p>Specifically, I've removed any keywords that can't precede a regexp + * literal in a syntactically legal javascript program, and I've removed the + * "in" keyword since it's not a keyword in many languages, and might be used + * as a count of inches. + * + * <p>The link above does not accurately describe EcmaScript rules since + * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works + * very well in practice. + * + * @private + * @const + */ + var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*'; + + // CAVEAT: this does not properly handle the case where a regular + // expression immediately follows another since a regular expression may + // have flags for case-sensitivity and the like. Having regexp tokens + // adjacent is not valid in any language I'm aware of, so I'm punting. + // TODO: maybe style special characters inside a regexp as punctuation. + + /** + * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally + * matches the union of the sets of strings matched by the input RegExp. + * Since it matches globally, if the input strings have a start-of-input + * anchor (/^.../), it is ignored for the purposes of unioning. + * @param {Array.<RegExp>} regexs non multiline, non-global regexs. + * @return {RegExp} a global regex. + */ + function combinePrefixPatterns(regexs) { + var capturedGroupIndex = 0; + + var needToFoldCase = false; + var ignoreCase = false; + for (var i = 0, n = regexs.length; i < n; ++i) { + var regex = regexs[i]; + if (regex.ignoreCase) { + ignoreCase = true; + } else if (/[a-z]/i.test(regex.source.replace( + /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) { + needToFoldCase = true; + ignoreCase = false; + break; + } + } + + var escapeCharToCodeUnit = { + 'b': 8, + 't': 9, + 'n': 0xa, + 'v': 0xb, + 'f': 0xc, + 'r': 0xd + }; + + function decodeEscape(charsetPart) { + var cc0 = charsetPart.charCodeAt(0); + if (cc0 !== 92 /* \\ */) { + return cc0; + } + var c1 = charsetPart.charAt(1); + cc0 = escapeCharToCodeUnit[c1]; + if (cc0) { + return cc0; + } else if ('0' <= c1 && c1 <= '7') { + return parseInt(charsetPart.substring(1), 8); + } else if (c1 === 'u' || c1 === 'x') { + return parseInt(charsetPart.substring(2), 16); + } else { + return charsetPart.charCodeAt(1); + } + } + + function encodeEscape(charCode) { + if (charCode < 0x20) { + return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16); + } + var ch = String.fromCharCode(charCode); + return (ch === '\\' || ch === '-' || ch === ']' || ch === '^') + ? "\\" + ch : ch; + } + + function caseFoldCharset(charSet) { + var charsetParts = charSet.substring(1, charSet.length - 1).match( + new RegExp( + '\\\\u[0-9A-Fa-f]{4}' + + '|\\\\x[0-9A-Fa-f]{2}' + + '|\\\\[0-3][0-7]{0,2}' + + '|\\\\[0-7]{1,2}' + + '|\\\\[\\s\\S]' + + '|-' + + '|[^-\\\\]', + 'g')); + var ranges = []; + var inverse = charsetParts[0] === '^'; + + var out = ['[']; + if (inverse) { out.push('^'); } + + for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) { + var p = charsetParts[i]; + if (/\\[bdsw]/i.test(p)) { // Don't muck with named groups. + out.push(p); + } else { + var start = decodeEscape(p); + var end; + if (i + 2 < n && '-' === charsetParts[i + 1]) { + end = decodeEscape(charsetParts[i + 2]); + i += 2; + } else { + end = start; + } + ranges.push([start, end]); + // If the range might intersect letters, then expand it. + // This case handling is too simplistic. + // It does not deal with non-latin case folding. + // It works for latin source code identifiers though. + if (!(end < 65 || start > 122)) { + if (!(end < 65 || start > 90)) { + ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]); + } + if (!(end < 97 || start > 122)) { + ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]); + } + } + } + } + + // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]] + // -> [[1, 12], [14, 14], [16, 17]] + ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); }); + var consolidatedRanges = []; + var lastRange = []; + for (var i = 0; i < ranges.length; ++i) { + var range = ranges[i]; + if (range[0] <= lastRange[1] + 1) { + lastRange[1] = Math.max(lastRange[1], range[1]); + } else { + consolidatedRanges.push(lastRange = range); + } + } + + for (var i = 0; i < consolidatedRanges.length; ++i) { + var range = consolidatedRanges[i]; + out.push(encodeEscape(range[0])); + if (range[1] > range[0]) { + if (range[1] + 1 > range[0]) { out.push('-'); } + out.push(encodeEscape(range[1])); + } + } + out.push(']'); + return out.join(''); + } + + function allowAnywhereFoldCaseAndRenumberGroups(regex) { + // Split into character sets, escape sequences, punctuation strings + // like ('(', '(?:', ')', '^'), and runs of characters that do not + // include any of the above. + var parts = regex.source.match( + new RegExp( + '(?:' + + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set + + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape + + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape + + '|\\\\[0-9]+' // a back-reference or octal escape + + '|\\\\[^ux0-9]' // other escape sequence + + '|\\(\\?[:!=]' // start of a non-capturing group + + '|[\\(\\)\\^]' // start/end of a group, or line start + + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters + + ')', + 'g')); + var n = parts.length; + + // Maps captured group numbers to the number they will occupy in + // the output or to -1 if that has not been determined, or to + // undefined if they need not be capturing in the output. + var capturedGroups = []; + + // Walk over and identify back references to build the capturedGroups + // mapping. + for (var i = 0, groupIndex = 0; i < n; ++i) { + var p = parts[i]; + if (p === '(') { + // groups are 1-indexed, so max group index is count of '(' + ++groupIndex; + } else if ('\\' === p.charAt(0)) { + var decimalValue = +p.substring(1); + if (decimalValue) { + if (decimalValue <= groupIndex) { + capturedGroups[decimalValue] = -1; + } else { + // Replace with an unambiguous escape sequence so that + // an octal escape sequence does not turn into a backreference + // to a capturing group from an earlier regex. + parts[i] = encodeEscape(decimalValue); + } + } + } + } + + // Renumber groups and reduce capturing groups to non-capturing groups + // where possible. + for (var i = 1; i < capturedGroups.length; ++i) { + if (-1 === capturedGroups[i]) { + capturedGroups[i] = ++capturedGroupIndex; + } + } + for (var i = 0, groupIndex = 0; i < n; ++i) { + var p = parts[i]; + if (p === '(') { + ++groupIndex; + if (!capturedGroups[groupIndex]) { + parts[i] = '(?:'; + } + } else if ('\\' === p.charAt(0)) { + var decimalValue = +p.substring(1); + if (decimalValue && decimalValue <= groupIndex) { + parts[i] = '\\' + capturedGroups[decimalValue]; + } + } + } + + // Remove any prefix anchors so that the output will match anywhere. + // ^^ really does mean an anchored match though. + for (var i = 0; i < n; ++i) { + if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; } + } + + // Expand letters to groups to handle mixing of case-sensitive and + // case-insensitive patterns if necessary. + if (regex.ignoreCase && needToFoldCase) { + for (var i = 0; i < n; ++i) { + var p = parts[i]; + var ch0 = p.charAt(0); + if (p.length >= 2 && ch0 === '[') { + parts[i] = caseFoldCharset(p); + } else if (ch0 !== '\\') { + // TODO: handle letters in numeric escapes. + parts[i] = p.replace( + /[a-zA-Z]/g, + function (ch) { + var cc = ch.charCodeAt(0); + return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']'; + }); + } + } + } + + return parts.join(''); + } + + var rewritten = []; + for (var i = 0, n = regexs.length; i < n; ++i) { + var regex = regexs[i]; + if (regex.global || regex.multiline) { throw new Error('' + regex); } + rewritten.push( + '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')'); + } + + return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g'); + } + + /** + * Split markup into a string of source code and an array mapping ranges in + * that string to the text nodes in which they appear. + * + * <p> + * The HTML DOM structure:</p> + * <pre> + * (Element "p" + * (Element "b" + * (Text "print ")) ; #1 + * (Text "'Hello '") ; #2 + * (Element "br") ; #3 + * (Text " + 'World';")) ; #4 + * </pre> + * <p> + * corresponds to the HTML + * {@code <p><b>print </b>'Hello '<br> + 'World';</p>}.</p> + * + * <p> + * It will produce the output:</p> + * <pre> + * { + * sourceCode: "print 'Hello '\n + 'World';", + * // 1 2 + * // 012345678901234 5678901234567 + * spans: [0, #1, 6, #2, 14, #3, 15, #4] + * } + * </pre> + * <p> + * where #1 is a reference to the {@code "print "} text node above, and so + * on for the other text nodes. + * </p> + * + * <p> + * The {@code} spans array is an array of pairs. Even elements are the start + * indices of substrings, and odd elements are the text nodes (or BR elements) + * that contain the text for those substrings. + * Substrings continue until the next index or the end of the source. + * </p> + * + * @param {Node} node an HTML DOM subtree containing source-code. + * @param {boolean|number} isPreformatted truthy if white-space in + * text nodes should be considered significant. + * @return {SourceSpansT} source code and the nodes in which they occur. + */ + function extractSourceSpans(node, isPreformatted) { + var nocode = /(?:^|\s)nocode(?:\s|$)/; + + var chunks = []; + var length = 0; + var spans = []; + var k = 0; + + function walk(node) { + var type = node.nodeType; + if (type == 1) { // Element + if (nocode.test(node.className)) { return; } + for (var child = node.firstChild; child; child = child.nextSibling) { + walk(child); + } + var nodeName = node.nodeName.toLowerCase(); + if ('br' === nodeName || 'li' === nodeName) { + chunks[k] = '\n'; + spans[k << 1] = length++; + spans[(k++ << 1) | 1] = node; + } + } else if (type == 3 || type == 4) { // Text + var text = node.nodeValue; + if (text.length) { + if (!isPreformatted) { + text = text.replace(/[ \t\r\n]+/g, ' '); + } else { + text = text.replace(/\r\n?/g, '\n'); // Normalize newlines. + } + // TODO: handle tabs here? + chunks[k] = text; + spans[k << 1] = length; + length += text.length; + spans[(k++ << 1) | 1] = node; + } + } + } + + walk(node); + + return { + sourceCode: chunks.join('').replace(/\n$/, ''), + spans: spans + }; + } + + /** + * Apply the given language handler to sourceCode and add the resulting + * decorations to out. + * @param {!Element} sourceNode + * @param {number} basePos the index of sourceCode within the chunk of source + * whose decorations are already present on out. + * @param {string} sourceCode + * @param {function(JobT)} langHandler + * @param {DecorationsT} out + */ + function appendDecorations( + sourceNode, basePos, sourceCode, langHandler, out) { + if (!sourceCode) { return; } + /** @type {JobT} */ + var job = { + sourceNode: sourceNode, + pre: 1, + langExtension: null, + numberLines: null, + sourceCode: sourceCode, + spans: null, + basePos: basePos, + decorations: null + }; + langHandler(job); + out.push.apply(out, job.decorations); + } + + var notWs = /\S/; + + /** + * Given an element, if it contains only one child element and any text nodes + * it contains contain only space characters, return the sole child element. + * Otherwise returns undefined. + * <p> + * This is meant to return the CODE element in {@code <pre><code ...>} when + * there is a single child element that contains all the non-space textual + * content, but not to return anything where there are multiple child elements + * as in {@code <pre><code>...</code><code>...</code></pre>} or when there + * is textual content. + */ + function childContentWrapper(element) { + var wrapper = undefined; + for (var c = element.firstChild; c; c = c.nextSibling) { + var type = c.nodeType; + wrapper = (type === 1) // Element Node + ? (wrapper ? element : c) + : (type === 3) // Text Node + ? (notWs.test(c.nodeValue) ? element : wrapper) + : wrapper; + } + return wrapper === element ? undefined : wrapper; + } + + /** Given triples of [style, pattern, context] returns a lexing function, + * The lexing function interprets the patterns to find token boundaries and + * returns a decoration list of the form + * [index_0, style_0, index_1, style_1, ..., index_n, style_n] + * where index_n is an index into the sourceCode, and style_n is a style + * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to + * all characters in sourceCode[index_n-1:index_n]. + * + * The stylePatterns is a list whose elements have the form + * [style : string, pattern : RegExp, DEPRECATED, shortcut : string]. + * + * Style is a style constant like PR_PLAIN, or can be a string of the + * form 'lang-FOO', where FOO is a language extension describing the + * language of the portion of the token in $1 after pattern executes. + * E.g., if style is 'lang-lisp', and group 1 contains the text + * '(hello (world))', then that portion of the token will be passed to the + * registered lisp handler for formatting. + * The text before and after group 1 will be restyled using this decorator + * so decorators should take care that this doesn't result in infinite + * recursion. For example, the HTML lexer rule for SCRIPT elements looks + * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match + * '<script>foo()<\/script>', which would cause the current decorator to + * be called with '<script>' which would not match the same rule since + * group 1 must not be empty, so it would be instead styled as PR_TAG by + * the generic tag rule. The handler registered for the 'js' extension would + * then be called with 'foo()', and finally, the current decorator would + * be called with '<\/script>' which would not match the original rule and + * so the generic tag rule would identify it as a tag. + * + * Pattern must only match prefixes, and if it matches a prefix, then that + * match is considered a token with the same style. + * + * Context is applied to the last non-whitespace, non-comment token + * recognized. + * + * Shortcut is an optional string of characters, any of which, if the first + * character, gurantee that this pattern and only this pattern matches. + * + * @param {Array} shortcutStylePatterns patterns that always start with + * a known character. Must have a shortcut string. + * @param {Array} fallthroughStylePatterns patterns that will be tried in + * order if the shortcut ones fail. May have shortcuts. + * + * @return {function (JobT)} a function that takes an undecorated job and + * attaches a list of decorations. + */ + function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { + var shortcuts = {}; + var tokenizer; + (function () { + var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); + var allRegexs = []; + var regexKeys = {}; + for (var i = 0, n = allPatterns.length; i < n; ++i) { + var patternParts = allPatterns[i]; + var shortcutChars = patternParts[3]; + if (shortcutChars) { + for (var c = shortcutChars.length; --c >= 0;) { + shortcuts[shortcutChars.charAt(c)] = patternParts; + } + } + var regex = patternParts[1]; + var k = '' + regex; + if (!regexKeys.hasOwnProperty(k)) { + allRegexs.push(regex); + regexKeys[k] = null; + } + } + allRegexs.push(/[\0-\uffff]/); + tokenizer = combinePrefixPatterns(allRegexs); + })(); + + var nPatterns = fallthroughStylePatterns.length; + + /** + * Lexes job.sourceCode and attaches an output array job.decorations of + * style classes preceded by the position at which they start in + * job.sourceCode in order. + * + * @type{function (JobT)} + */ + var decorate = function (job) { + var sourceCode = job.sourceCode, basePos = job.basePos; + var sourceNode = job.sourceNode; + /** Even entries are positions in source in ascending order. Odd enties + * are style markers (e.g., PR_COMMENT) that run from that position until + * the end. + * @type {DecorationsT} + */ + var decorations = [basePos, PR_PLAIN]; + var pos = 0; // index into sourceCode + var tokens = sourceCode.match(tokenizer) || []; + var styleCache = {}; + + for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) { + var token = tokens[ti]; + var style = styleCache[token]; + var match = void 0; + + var isEmbedded; + if (typeof style === 'string') { + isEmbedded = false; + } else { + var patternParts = shortcuts[token.charAt(0)]; + if (patternParts) { + match = token.match(patternParts[1]); + style = patternParts[0]; + } else { + for (var i = 0; i < nPatterns; ++i) { + patternParts = fallthroughStylePatterns[i]; + match = token.match(patternParts[1]); + if (match) { + style = patternParts[0]; + break; + } + } + + if (!match) { // make sure that we make progress + style = PR_PLAIN; + } + } + + isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5); + if (isEmbedded && !(match && typeof match[1] === 'string')) { + isEmbedded = false; + style = PR_SOURCE; + } + + if (!isEmbedded) { styleCache[token] = style; } + } + + var tokenStart = pos; + pos += token.length; + + if (!isEmbedded) { + decorations.push(basePos + tokenStart, style); + } else { // Treat group 1 as an embedded block of source code. + var embeddedSource = match[1]; + var embeddedSourceStart = token.indexOf(embeddedSource); + var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length; + if (match[2]) { + // If embeddedSource can be blank, then it would match at the + // beginning which would cause us to infinitely recurse on the + // entire token, so we catch the right context in match[2]. + embeddedSourceEnd = token.length - match[2].length; + embeddedSourceStart = embeddedSourceEnd - embeddedSource.length; + } + var lang = style.substring(5); + // Decorate the left of the embedded source + appendDecorations( + sourceNode, + basePos + tokenStart, + token.substring(0, embeddedSourceStart), + decorate, decorations); + // Decorate the embedded source + appendDecorations( + sourceNode, + basePos + tokenStart + embeddedSourceStart, + embeddedSource, + langHandlerForExtension(lang, embeddedSource), + decorations); + // Decorate the right of the embedded section + appendDecorations( + sourceNode, + basePos + tokenStart + embeddedSourceEnd, + token.substring(embeddedSourceEnd), + decorate, decorations); + } + } + job.decorations = decorations; + }; + return decorate; + } + + /** returns a function that produces a list of decorations from source text. + * + * This code treats ", ', and ` as string delimiters, and \ as a string + * escape. It does not recognize perl's qq() style strings. + * It has no special handling for double delimiter escapes as in basic, or + * the tripled delimiters used in python, but should work on those regardless + * although in those cases a single string literal may be broken up into + * multiple adjacent string literals. + * + * It recognizes C, C++, and shell style comments. + * + * @param {Object} options a set of optional parameters. + * @return {function (JobT)} a function that examines the source code + * in the input job and builds a decoration list which it attaches to + * the job. + */ + function sourceDecorator(options) { + var shortcutStylePatterns = [], fallthroughStylePatterns = []; + if (options['tripleQuotedStrings']) { + // '''multi-line-string''', 'single-line-string', and double-quoted + shortcutStylePatterns.push( + [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, + null, '\'"']); + } else if (options['multiLineStrings']) { + // 'multi-line-string', "multi-line-string" + shortcutStylePatterns.push( + [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, + null, '\'"`']); + } else { + // 'single-line-string', "single-line-string" + shortcutStylePatterns.push( + [PR_STRING, + /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, + null, '"\'']); + } + if (options['verbatimStrings']) { + // verbatim-string-literal production from the C# grammar. See issue 93. + fallthroughStylePatterns.push( + [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]); + } + var hc = options['hashComments']; + if (hc) { + if (options['cStyleComments']) { + if (hc > 1) { // multiline hash comments + shortcutStylePatterns.push( + [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']); + } else { + // Stop C preprocessor declarations at an unclosed open comment + shortcutStylePatterns.push( + [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/, + null, '#']); + } + // #include <stdio.h> + fallthroughStylePatterns.push( + [PR_STRING, + /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/, + null]); + } else { + shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); + } + } + if (options['cStyleComments']) { + fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); + fallthroughStylePatterns.push( + [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); + } + var regexLiterals = options['regexLiterals']; + if (regexLiterals) { + /** + * @const + */ + var regexExcls = regexLiterals > 1 + ? '' // Multiline regex literals + : '\n\r'; + /** + * @const + */ + var regexAny = regexExcls ? '.' : '[\\S\\s]'; + /** + * @const + */ + var REGEX_LITERAL = ( + // A regular expression literal starts with a slash that is + // not followed by * or / so that it is not confused with + // comments. + '/(?=[^/*' + regexExcls + '])' + // and then contains any number of raw characters, + + '(?:[^/\\x5B\\x5C' + regexExcls + ']' + // escape sequences (\x5C), + + '|\\x5C' + regexAny + // or non-nesting character sets (\x5B\x5D); + + '|\\x5B(?:[^\\x5C\\x5D' + regexExcls + ']' + + '|\\x5C' + regexAny + ')*(?:\\x5D|$))+' + // finally closed by a /. + + '/'); + fallthroughStylePatterns.push( + ['lang-regex', + RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')') + ]); + } + + var types = options['types']; + if (types) { + fallthroughStylePatterns.push([PR_TYPE, types]); + } + + var keywords = ("" + options['keywords']).replace(/^ | $/g, ''); + if (keywords.length) { + fallthroughStylePatterns.push( + [PR_KEYWORD, + new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'), + null]); + } + + shortcutStylePatterns.push([PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']); + + var punctuation = + // The Bash man page says + + // A word is a sequence of characters considered as a single + // unit by GRUB. Words are separated by metacharacters, + // which are the following plus space, tab, and newline: { } + // | & $ ; < > + // ... + + // A word beginning with # causes that word and all remaining + // characters on that line to be ignored. + + // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a + // comment but empirically + // $ echo {#} + // {#} + // $ echo \$# + // $# + // $ echo }# + // }# + + // so /(?:^|[|&;<>\s])/ is more appropriate. + + // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3 + // suggests that this definition is compatible with a + // default mode that tries to use a single token definition + // to recognize both bash/python style comments and C + // preprocessor directives. + + // This definition of punctuation does not include # in the list of + // follow-on exclusions, so # will not be broken before if preceeded + // by a punctuation character. We could try to exclude # after + // [|&;<>] but that doesn't seem to cause many major problems. + // If that does turn out to be a problem, we should change the below + // when hc is truthy to include # in the run of punctuation characters + // only when not followint [|&;<>]. + '^.[^\\s\\w.$@\'"`/\\\\]*'; + if (options['regexLiterals']) { + punctuation += '(?!\s*\/)'; + } + + fallthroughStylePatterns.push( + // TODO(mikesamuel): recognize non-latin letters and numerals in idents + [PR_LITERAL, /^@[a-z_$][a-z_$@0-9]*/i, null], + [PR_TYPE, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null], + [PR_PLAIN, /^[a-z_$][a-z_$@0-9]*/i, null], + [PR_LITERAL, + new RegExp( + '^(?:' + // A hex number + + '0x[a-f0-9]+' + // or an octal or decimal number, + + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)' + // possibly in scientific notation + + '(?:e[+\\-]?\\d+)?' + + ')' + // with an optional modifier like UL for unsigned long + + '[a-z]*', 'i'), + null, '0123456789'], + // Don't treat escaped quotes in bash as starting strings. + // See issue 144. + [PR_PLAIN, /^\\[\s\S]?/, null], + [PR_PUNCTUATION, new RegExp(punctuation), null]); + + return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); + } + + var decorateSource = sourceDecorator({ + 'keywords': ALL_KEYWORDS, + 'hashComments': true, + 'cStyleComments': true, + 'multiLineStrings': true, + 'regexLiterals': true + }); + + /** + * Given a DOM subtree, wraps it in a list, and puts each line into its own + * list item. + * + * @param {Node} node modified in place. Its content is pulled into an + * HTMLOListElement, and each line is moved into a separate list item. + * This requires cloning elements, so the input might not have unique + * IDs after numbering. + * @param {number|null|boolean} startLineNum + * If truthy, coerced to an integer which is the 1-indexed line number + * of the first line of code. The number of the first line will be + * attached to the list. + * @param {boolean} isPreformatted true iff white-space in text nodes should + * be treated as significant. + */ + function numberLines(node, startLineNum, isPreformatted) { + var nocode = /(?:^|\s)nocode(?:\s|$)/; + var lineBreak = /\r\n?|\n/; + + var document = node.ownerDocument; + + var li = document.createElement('li'); + while (node.firstChild) { + li.appendChild(node.firstChild); + } + // An array of lines. We split below, so this is initialized to one + // un-split line. + var listItems = [li]; + + function walk(node) { + var type = node.nodeType; + if (type == 1 && !nocode.test(node.className)) { // Element + if ('br' === node.nodeName) { + breakAfter(node); + // Discard the <BR> since it is now flush against a </LI>. + if (node.parentNode) { + node.parentNode.removeChild(node); + } + } else { + for (var child = node.firstChild; child; child = child.nextSibling) { + walk(child); + } + } + } else if ((type == 3 || type == 4) && isPreformatted) { // Text + var text = node.nodeValue; + var match = text.match(lineBreak); + if (match) { + var firstLine = text.substring(0, match.index); + node.nodeValue = firstLine; + var tail = text.substring(match.index + match[0].length); + if (tail) { + var parent = node.parentNode; + parent.insertBefore( + document.createTextNode(tail), node.nextSibling); + } + breakAfter(node); + if (!firstLine) { + // Don't leave blank text nodes in the DOM. + node.parentNode.removeChild(node); + } + } + } + } + + // Split a line after the given node. + function breakAfter(lineEndNode) { + // If there's nothing to the right, then we can skip ending the line + // here, and move root-wards since splitting just before an end-tag + // would require us to create a bunch of empty copies. + while (!lineEndNode.nextSibling) { + lineEndNode = lineEndNode.parentNode; + if (!lineEndNode) { return; } + } + + function breakLeftOf(limit, copy) { + // Clone shallowly if this node needs to be on both sides of the break. + var rightSide = copy ? limit.cloneNode(false) : limit; + var parent = limit.parentNode; + if (parent) { + // We clone the parent chain. + // This helps us resurrect important styling elements that cross lines. + // E.g. in <i>Foo<br>Bar</i> + // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>. + var parentClone = breakLeftOf(parent, 1); + // Move the clone and everything to the right of the original + // onto the cloned parent. + var next = limit.nextSibling; + parentClone.appendChild(rightSide); + for (var sibling = next; sibling; sibling = next) { + next = sibling.nextSibling; + parentClone.appendChild(sibling); + } + } + return rightSide; + } + + var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0); + + // Walk the parent chain until we reach an unattached LI. + for (var parent; + // Check nodeType since IE invents document fragments. + (parent = copiedListItem.parentNode) && parent.nodeType === 1;) { + copiedListItem = parent; + } + // Put it on the list of lines for later processing. + listItems.push(copiedListItem); + } + + // Split lines while there are lines left to split. + for (var i = 0; // Number of lines that have been split so far. + i < listItems.length; // length updated by breakAfter calls. + ++i) { + walk(listItems[i]); + } + + // Make sure numeric indices show correctly. + if (startLineNum === (startLineNum|0)) { + listItems[0].setAttribute('value', startLineNum); + } + + var ol = document.createElement('ol'); + ol.className = 'linenums'; + var offset = Math.max(0, ((startLineNum - 1 /* zero index */)) | 0) || 0; + for (var i = 0, n = listItems.length; i < n; ++i) { + li = listItems[i]; + // Stick a class on the LIs so that stylesheets can + // color odd/even rows, or any other row pattern that + // is co-prime with 10. + li.className = 'L' + ((i + offset) % 10); + if (!li.firstChild) { + li.appendChild(document.createTextNode('\xA0')); + } + ol.appendChild(li); + } + + node.appendChild(ol); + } + + /** + * Breaks {@code job.sourceCode} around style boundaries in + * {@code job.decorations} and modifies {@code job.sourceNode} in place. + * @param {JobT} job + * @private + */ + function recombineTagsAndDecorations(job) { + var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent); + isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8; + var newlineRe = /\n/g; + + var source = job.sourceCode; + var sourceLength = source.length; + // Index into source after the last code-unit recombined. + var sourceIndex = 0; + + var spans = job.spans; + var nSpans = spans.length; + // Index into spans after the last span which ends at or before sourceIndex. + var spanIndex = 0; + + var decorations = job.decorations; + var nDecorations = decorations.length; + // Index into decorations after the last decoration which ends at or before + // sourceIndex. + var decorationIndex = 0; + + // Remove all zero-length decorations. + decorations[nDecorations] = sourceLength; + var decPos, i; + for (i = decPos = 0; i < nDecorations;) { + if (decorations[i] !== decorations[i + 2]) { + decorations[decPos++] = decorations[i++]; + decorations[decPos++] = decorations[i++]; + } else { + i += 2; + } + } + nDecorations = decPos; + + // Simplify decorations. + for (i = decPos = 0; i < nDecorations;) { + var startPos = decorations[i]; + // Conflate all adjacent decorations that use the same style. + var startDec = decorations[i + 1]; + var end = i + 2; + while (end + 2 <= nDecorations && decorations[end + 1] === startDec) { + end += 2; + } + decorations[decPos++] = startPos; + decorations[decPos++] = startDec; + i = end; + } + + nDecorations = decorations.length = decPos; + + var sourceNode = job.sourceNode; + var oldDisplay = ""; + if (sourceNode) { + oldDisplay = sourceNode.style.display; + sourceNode.style.display = 'none'; + } + try { + var decoration = null; + while (spanIndex < nSpans) { + var spanStart = spans[spanIndex]; + var spanEnd = /** @type{number} */ (spans[spanIndex + 2]) + || sourceLength; + + var decEnd = decorations[decorationIndex + 2] || sourceLength; + + var end = Math.min(spanEnd, decEnd); + + var textNode = /** @type{Node} */ (spans[spanIndex + 1]); + var styledText; + if (textNode.nodeType !== 1 // Don't muck with <BR>s or <LI>s + // Don't introduce spans around empty text nodes. + && (styledText = source.substring(sourceIndex, end))) { + // This may seem bizarre, and it is. Emitting LF on IE causes the + // code to display with spaces instead of line breaks. + // Emitting Windows standard issue linebreaks (CRLF) causes a blank + // space to appear at the beginning of every line but the first. + // Emitting an old Mac OS 9 line separator makes everything spiffy. + if (isIE8OrEarlier) { + styledText = styledText.replace(newlineRe, '\r'); + } + textNode.nodeValue = styledText; + var document = textNode.ownerDocument; + var span = document.createElement('span'); + span.className = decorations[decorationIndex + 1]; + var parentNode = textNode.parentNode; + parentNode.replaceChild(span, textNode); + span.appendChild(textNode); + if (sourceIndex < spanEnd) { // Split off a text node. + spans[spanIndex + 1] = textNode + // TODO: Possibly optimize by using '' if there's no flicker. + = document.createTextNode(source.substring(end, spanEnd)); + parentNode.insertBefore(textNode, span.nextSibling); + } + } + + sourceIndex = end; + + if (sourceIndex >= spanEnd) { + spanIndex += 2; + } + if (sourceIndex >= decEnd) { + decorationIndex += 2; + } + } + } finally { + if (sourceNode) { + sourceNode.style.display = oldDisplay; + } + } + } + + /** Maps language-specific file extensions to handlers. */ + var langHandlerRegistry = {}; + /** Register a language handler for the given file extensions. + * @param {function (JobT)} handler a function from source code to a list + * of decorations. Takes a single argument job which describes the + * state of the computation and attaches the decorations to it. + * @param {Array.<string>} fileExtensions + */ + function registerLangHandler(handler, fileExtensions) { + for (var i = fileExtensions.length; --i >= 0;) { + var ext = fileExtensions[i]; + if (!langHandlerRegistry.hasOwnProperty(ext)) { + langHandlerRegistry[ext] = handler; + } else if (win['console']) { + console['warn']('cannot override language handler %s', ext); + } + } + } + function langHandlerForExtension(extension, source) { + if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) { + // Treat it as markup if the first non whitespace character is a < and + // the last non-whitespace character is a >. + extension = /^\s*</.test(source) + ? 'default-markup' + : 'default-code'; + } + return langHandlerRegistry[extension]; + } + registerLangHandler(decorateSource, ['default-code']); + registerLangHandler( + createSimpleLexer( + [], + [ + [PR_PLAIN, /^[^<?]+/], + [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/], + [PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/], + // Unescaped content in an unknown language + ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/], + ['lang-', /^<%([\s\S]+?)(?:%>|$)/], + [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/], + ['lang-', /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i], + // Unescaped content in javascript. (Or possibly vbscript). + ['lang-js', /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i], + // Contains unescaped stylesheet content + ['lang-css', /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i], + ['lang-in.tag', /^(<\/?[a-z][^<>]*>)/i] + ]), + ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']); + registerLangHandler( + createSimpleLexer( + [ + [PR_PLAIN, /^[\s]+/, null, ' \t\r\n'], + [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\''] + ], + [ + [PR_TAG, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i], + [PR_ATTRIB_NAME, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i], + ['lang-uq.val', /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/], + [PR_PUNCTUATION, /^[=<>\/]+/], + ['lang-js', /^on\w+\s*=\s*\"([^\"]+)\"/i], + ['lang-js', /^on\w+\s*=\s*\'([^\']+)\'/i], + ['lang-js', /^on\w+\s*=\s*([^\"\'>\s]+)/i], + ['lang-css', /^style\s*=\s*\"([^\"]+)\"/i], + ['lang-css', /^style\s*=\s*\'([^\']+)\'/i], + ['lang-css', /^style\s*=\s*([^\"\'>\s]+)/i] + ]), + ['in.tag']); + registerLangHandler( + createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']); + registerLangHandler(sourceDecorator({ + 'keywords': CPP_KEYWORDS, + 'hashComments': true, + 'cStyleComments': true, + 'types': C_TYPES + }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']); + registerLangHandler(sourceDecorator({ + 'keywords': 'null,true,false' + }), ['json']); + registerLangHandler(sourceDecorator({ + 'keywords': CSHARP_KEYWORDS, + 'hashComments': true, + 'cStyleComments': true, + 'verbatimStrings': true, + 'types': C_TYPES + }), ['cs']); + registerLangHandler(sourceDecorator({ + 'keywords': JAVA_KEYWORDS, + 'cStyleComments': true + }), ['java']); + registerLangHandler(sourceDecorator({ + 'keywords': SH_KEYWORDS, + 'hashComments': true, + 'multiLineStrings': true + }), ['bash', 'bsh', 'csh', 'sh']); + registerLangHandler(sourceDecorator({ + 'keywords': PYTHON_KEYWORDS, + 'hashComments': true, + 'multiLineStrings': true, + 'tripleQuotedStrings': true + }), ['cv', 'py', 'python']); + registerLangHandler(sourceDecorator({ + 'keywords': PERL_KEYWORDS, + 'hashComments': true, + 'multiLineStrings': true, + 'regexLiterals': 2 // multiline regex literals + }), ['perl', 'pl', 'pm']); + registerLangHandler(sourceDecorator({ + 'keywords': RUBY_KEYWORDS, + 'hashComments': true, + 'multiLineStrings': true, + 'regexLiterals': true + }), ['rb', 'ruby']); + registerLangHandler(sourceDecorator({ + 'keywords': JSCRIPT_KEYWORDS, + 'cStyleComments': true, + 'regexLiterals': true + }), ['javascript', 'js', 'ts', 'typescript']); + registerLangHandler(sourceDecorator({ + 'keywords': COFFEE_KEYWORDS, + 'hashComments': 3, // ### style block comments + 'cStyleComments': true, + 'multilineStrings': true, + 'tripleQuotedStrings': true, + 'regexLiterals': true + }), ['coffee']); + registerLangHandler( + createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']); + + /** @param {JobT} job */ + function applyDecorator(job) { + var opt_langExtension = job.langExtension; + + try { + // Extract tags, and convert the source code to plain text. + var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre); + /** Plain text. @type {string} */ + var source = sourceAndSpans.sourceCode; + job.sourceCode = source; + job.spans = sourceAndSpans.spans; + job.basePos = 0; + + // Apply the appropriate language handler + langHandlerForExtension(opt_langExtension, source)(job); + + // Integrate the decorations and tags back into the source code, + // modifying the sourceNode in place. + recombineTagsAndDecorations(job); + } catch (e) { + if (win['console']) { + console['log'](e && e['stack'] || e); + } + } + } + + /** + * Pretty print a chunk of code. + * @param sourceCodeHtml {string} The HTML to pretty print. + * @param opt_langExtension {string} The language name to use. + * Typically, a filename extension like 'cpp' or 'java'. + * @param opt_numberLines {number|boolean} True to number lines, + * or the 1-indexed number of the first line in sourceCodeHtml. + */ + function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) { + /** @type{number|boolean} */ + var nl = opt_numberLines || false; + /** @type{string|null} */ + var langExtension = opt_langExtension || null; + /** @type{!Element} */ + var container = document.createElement('div'); + // This could cause images to load and onload listeners to fire. + // E.g. <img onerror="alert(1337)" src="nosuchimage.png">. + // We assume that the inner HTML is from a trusted source. + // The pre-tag is required for IE8 which strips newlines from innerHTML + // when it is injected into a <pre> tag. + // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie + // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript + container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>'; + container = /** @type{!Element} */(container.firstChild); + if (nl) { + numberLines(container, nl, true); + } + + /** @type{JobT} */ + var job = { + langExtension: langExtension, + numberLines: nl, + sourceNode: container, + pre: 1, + sourceCode: null, + basePos: null, + spans: null, + decorations: null + }; + applyDecorator(job); + return container.innerHTML; + } + + /** + * Find all the {@code <pre>} and {@code <code>} tags in the DOM with + * {@code class=prettyprint} and prettify them. + * + * @param {Function} opt_whenDone called when prettifying is done. + * @param {HTMLElement|HTMLDocument} opt_root an element or document + * containing all the elements to pretty print. + * Defaults to {@code document.body}. + */ + function $prettyPrint(opt_whenDone, opt_root) { + var root = opt_root || document.body; + var doc = root.ownerDocument || document; + function byTagName(tn) { return root.getElementsByTagName(tn); } + // fetch a list of nodes to rewrite + var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')]; + var elements = []; + for (var i = 0; i < codeSegments.length; ++i) { + for (var j = 0, n = codeSegments[i].length; j < n; ++j) { + elements.push(codeSegments[i][j]); + } + } + codeSegments = null; + + var clock = Date; + if (!clock['now']) { + clock = { 'now': function () { return +(new Date); } }; + } + + // The loop is broken into a series of continuations to make sure that we + // don't make the browser unresponsive when rewriting a large page. + var k = 0; + + var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/; + var prettyPrintRe = /\bprettyprint\b/; + var prettyPrintedRe = /\bprettyprinted\b/; + var preformattedTagNameRe = /pre|xmp/i; + var codeRe = /^code$/i; + var preCodeXmpRe = /^(?:pre|code|xmp)$/i; + var EMPTY = {}; + + function doWork() { + var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ? + clock['now']() + 250 /* ms */ : + Infinity); + for (; k < elements.length && clock['now']() < endTime; k++) { + var cs = elements[k]; + + // Look for a preceding comment like + // <?prettify lang="..." linenums="..."?> + var attrs = EMPTY; + { + for (var preceder = cs; (preceder = preceder.previousSibling);) { + var nt = preceder.nodeType; + // <?foo?> is parsed by HTML 5 to a comment node (8) + // like <!--?foo?-->, but in XML is a processing instruction + var value = (nt === 7 || nt === 8) && preceder.nodeValue; + if (value + ? !/^\??prettify\b/.test(value) + : (nt !== 3 || /\S/.test(preceder.nodeValue))) { + // Skip over white-space text nodes but not others. + break; + } + if (value) { + attrs = {}; + value.replace( + /\b(\w+)=([\w:.%+-]+)/g, + function (_, name, value) { attrs[name] = value; }); + break; + } + } + } + + var className = cs.className; + if ((attrs !== EMPTY || prettyPrintRe.test(className)) + // Don't redo this if we've already done it. + // This allows recalling pretty print to just prettyprint elements + // that have been added to the page since last call. + && !prettyPrintedRe.test(className)) { + + // make sure this is not nested in an already prettified element + var nested = false; + for (var p = cs.parentNode; p; p = p.parentNode) { + var tn = p.tagName; + if (preCodeXmpRe.test(tn) + && p.className && prettyPrintRe.test(p.className)) { + nested = true; + break; + } + } + if (!nested) { + // Mark done. If we fail to prettyprint for whatever reason, + // we shouldn't try again. + cs.className += ' prettyprinted'; + + // If the classes includes a language extensions, use it. + // Language extensions can be specified like + // <pre class="prettyprint lang-cpp"> + // the language extension "cpp" is used to find a language handler + // as passed to PR.registerLangHandler. + // HTML5 recommends that a language be specified using "language-" + // as the prefix instead. Google Code Prettify supports both. + // http://dev.w3.org/html5/spec-author-view/the-code-element.html + var langExtension = attrs['lang']; + if (!langExtension) { + langExtension = className.match(langExtensionRe); + // Support <pre class="prettyprint"><code class="language-c"> + var wrapper; + if (!langExtension && (wrapper = childContentWrapper(cs)) + && codeRe.test(wrapper.tagName)) { + langExtension = wrapper.className.match(langExtensionRe); + } + + if (langExtension) { langExtension = langExtension[1]; } + } + + var preformatted; + if (preformattedTagNameRe.test(cs.tagName)) { + preformatted = 1; + } else { + var currentStyle = cs['currentStyle']; + var defaultView = doc.defaultView; + var whitespace = ( + currentStyle + ? currentStyle['whiteSpace'] + : (defaultView + && defaultView.getComputedStyle) + ? defaultView.getComputedStyle(cs, null) + .getPropertyValue('white-space') + : 0); + preformatted = whitespace + && 'pre' === whitespace.substring(0, 3); + } + + // Look for a class like linenums or linenums:<n> where <n> is the + // 1-indexed number of the first line. + var lineNums = attrs['linenums']; + if (!(lineNums = lineNums === 'true' || +lineNums)) { + lineNums = className.match(/\blinenums\b(?::(\d+))?/); + lineNums = + lineNums + ? lineNums[1] && lineNums[1].length + ? +lineNums[1] : true + : false; + } + if (lineNums) { numberLines(cs, lineNums, preformatted); } + + // do the pretty printing + var prettyPrintingJob = { + langExtension: langExtension, + sourceNode: cs, + numberLines: lineNums, + pre: preformatted, + sourceCode: null, + basePos: null, + spans: null, + decorations: null + }; + applyDecorator(prettyPrintingJob); + } + } + } + if (k < elements.length) { + // finish up in a continuation + win.setTimeout(doWork, 250); + } else if ('function' === typeof opt_whenDone) { + opt_whenDone(); + } + } + + doWork(); + } + + /** + * Contains functions for creating and registering new language handlers. + * @type {Object} + */ + var PR = win['PR'] = { + 'createSimpleLexer': createSimpleLexer, + 'registerLangHandler': registerLangHandler, + 'sourceDecorator': sourceDecorator, + 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, + 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, + 'PR_COMMENT': PR_COMMENT, + 'PR_DECLARATION': PR_DECLARATION, + 'PR_KEYWORD': PR_KEYWORD, + 'PR_LITERAL': PR_LITERAL, + 'PR_NOCODE': PR_NOCODE, + 'PR_PLAIN': PR_PLAIN, + 'PR_PUNCTUATION': PR_PUNCTUATION, + 'PR_SOURCE': PR_SOURCE, + 'PR_STRING': PR_STRING, + 'PR_TAG': PR_TAG, + 'PR_TYPE': PR_TYPE, + 'prettyPrintOne': + IN_GLOBAL_SCOPE + ? (win['prettyPrintOne'] = $prettyPrintOne) + : (prettyPrintOne = $prettyPrintOne), + 'prettyPrint': prettyPrint = + IN_GLOBAL_SCOPE + ? (win['prettyPrint'] = $prettyPrint) + : (prettyPrint = $prettyPrint) + }; + + // Make PR available via the Asynchronous Module Definition (AMD) API. + // Per https://github.com/amdjs/amdjs-api/wiki/AMD: + // The Asynchronous Module Definition (AMD) API specifies a + // mechanism for defining modules such that the module and its + // dependencies can be asynchronously loaded. + // ... + // To allow a clear indicator that a global define function (as + // needed for script src browser loading) conforms to the AMD API, + // any global define function SHOULD have a property called "amd" + // whose value is an object. This helps avoid conflict with any + // other existing JavaScript code that could have defined a define() + // function that does not conform to the AMD API. + var define = win['define']; + if (typeof define === "function" && define['amd']) { + define("google-code-prettify", [], function () { + return PR; + }); + } + })(); + return prettyPrint; + })(); + + // If this script is deferred or async and the document is already + // loaded we need to wait for language handlers to load before performing + // any autorun. + function onLangsLoaded() { + if (autorun) { + contentLoaded( + function () { + var n = callbacks.length; + var callback = n ? function () { + for (var i = 0; i < n; ++i) { + (function (i) { + win.setTimeout( + function () { + win['exports'][callbacks[i]].apply(win, arguments); + }, 0); + })(i); + } + } : void 0; + prettyPrint(callback); + }); + } + } + checkPendingLanguages(); + +}());
\ No newline at end of file diff --git a/static/js/selController.js b/static/js/selController.js index 7f678a8..06c1abb 100644 --- a/static/js/selController.js +++ b/static/js/selController.js @@ -765,7 +765,7 @@ function get_sensor_names_from_sdr(sdr_list){ } -angular.module('bmcApp').controller('selController', function($scope, Restangular) { +angular.module('bmcApp').controller('selController', function($scope) { var sdr_promise = Restangular.all('sdrentries').getList(); var sel_promise = Restangular.all('selentries').getList(); diff --git a/static/js/versionController.js b/static/js/versionController.js index 082ccf8..b77f9b4 100644 --- a/static/js/versionController.js +++ b/static/js/versionController.js @@ -1,4 +1,4 @@ -angular.module('bmcApp').controller('versionController', function($scope, Restangular) { +angular.module('bmcApp').controller('versionController', function($scope) { var system_status = Restangular.one('systeminfo').get().then(function(system_status) { $scope.system_status = system_status; |

