<commit_before>/*
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

import '../data-explorer.js';
import Xen from '../xen/xen.js';

// notes:
// Xen memoizes template parsing when given a <template> instead of String
// Xen.Template.html converts a String to a <template>
// we assign to `html` so syntax-highlighters treat the literals as HTML
const html = Xen.Template.html;

const template = html`

<button on-click="_onUpdate">Update</button>

Arc Handles

{{arcHandles}}

Context Handles

{{contextHandles}}

`;

const handleTemplate = html`

  <data-explorer style="font-size: 0.8em;" object="{{data}}"></data-explorer>

`;

class HandleExplorer extends Xen.Base {
  static get observedAttributes() { return ['arc']; }
  get template() {
    return template;
  }
  _wouldChangeProp() {
    return true;
  }
  _willReceiveProps(props, state) {
    state.needsQuery = true;
  }
  _update(props, state) {
    if (props.arc && state.needsQuery) {
      state.needsQuery = false;
      //this._setState({arcHandles: null, contextHandles: null});
      this._queryHandles(props.arc);
    }
  }
  _render(props, state) {
    return {
      arcHandles: {
        template: handleTemplate,
        models: state.arcHandles
      },
      contextHandles: {
        template: handleTemplate,
        models: state.contextHandles
      }
    };
  }
  async _queryHandles(arc) {
    const arcHandles = await this._digestHandles(arc._storeTags);
    const find = manifest => {
      let tags = [...manifest._storeTags];
      if (manifest.imports) {
        manifest.imports.forEach(imp => tags = tags.concat(find(imp)));
      }
      return tags;
    };
    const contextHandles = await this._digestHandles(find(arc.context));
    this._setState({arcHandles, contextHandles});
  }
  async _digestHandles(handles) {
    const result = [];
    if (handles) {
      for (let [handle, tags] of handles) {
        //if (handle.name === null) {
        //  continue;
        //}
        let values = `(don't know how to dereference)`;
        if (handle.toList) {
          const list = await handle.toList();
          values = list.map(item => item.rawData);
        } else if (handle.get) {
          values = await handle.get();
        } else {
          // lint?
        }
        const data = {
          name: handle.name,
          tags: tags ? [...tags].join(', ') : '',
          id: handle.id,
          storage: handle.storageKey,
          type: handle.type,
          //values: JSON.stringify(handle.toList ? await handle.toList() : `await handle.get()`, null, '  ')
          values
        };
        if (handle.description) {
          data.description = handle.description;
        }
        let moniker = handle.id.split(':').pop();
        result.push({tags: data.tags, data, name: handle.name || data.tags || moniker});
      }
    }
    return result;
  }
  _onUpdate() {
    this._setState({needsQuery: true});
  }
}
customElements.define('handle-explorer', HandleExplorer);
<commit_msg>Fix template in handle-explorer.js (#1464)<commit_after>/*
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

import '../data-explorer.js';
import Xen from '../xen/xen.js';

// notes:
// Xen memoizes template parsing when given a <template> instead of String
// Xen.Template.html converts a String to a <template>
// we assign to `html` so syntax-highlighters treat the literals as HTML
const html = Xen.Template.html;

const template = html`

<button on-click="_onUpdate">Update</button>

Arc Handles

{{arcHandles}}

Context Handles

{{contextHandles}}

`;

const handleTemplate = html`

    <data-explorer style="font-size: 0.8em;" object="{{data}}"></data-explorer>

`;

class HandleExplorer extends Xen.Base {
  static get observedAttributes() { return ['arc']; }
  get template() {
    return template;
  }
  _wouldChangeProp() {
    return true;
  }
  _willReceiveProps(props, state) {
    state.needsQuery = true;
  }
  _update(props, state) {
    if (props.arc && state.needsQuery) {
      state.needsQuery = false;
      //this._setState({arcHandles: null, contextHandles: null});
      this._queryHandles(props.arc);
    }
  }
  _render(props, state) {
    return {
      arcHandles: {
        template: handleTemplate,
        models: state.arcHandles
      },
      contextHandles: {
        template: handleTemplate,
        models: state.contextHandles
      }
    };
  }
  async _queryHandles(arc) {
    const arcHandles = await this._digestHandles(arc._storeTags);
    const find = manifest => {
      let tags = [...manifest._storeTags];
      if (manifest.imports) {
        manifest.imports.forEach(imp => tags = tags.concat(find(imp)));
      }
      return tags;
    };
    const contextHandles = await this._digestHandles(find(arc.context));
    this._setState({arcHandles, contextHandles});
  }
  async _digestHandles(handles) {
    const result = [];
    if (handles) {
      for (let [handle, tags] of handles) {
        //if (handle.name === null) {
        //  continue;
        //}
        let values = `(don't know how to dereference)`;
        if (handle.toList) {
          const list = await handle.toList();
          values = list.map(item => item.rawData);
        } else if (handle.get) {
          values = await handle.get();
        } else {
          // lint?
        }
        const data = {
          name: handle.name,
          tags: tags ? [...tags].join(', ') : '',
          id: handle.id,
          storage: handle.storageKey,
          type: handle.type,
          //values: JSON.stringify(handle.toList ? await handle.toList() : `await handle.get()`, null, '  ')
          values
        };
        if (handle.description) {
          data.description = handle.description;
        }
        let moniker = handle.id.split(':').pop();
        result.push({tags: data.tags, data, name: handle.name || data.tags || moniker});
      }
    }
    return result;
  }
  _onUpdate() {
    this._setState({needsQuery: true});
  }
}
customElements.define('handle-explorer', HandleExplorer);
<|endoftext|>


<commit_before>/**
 * JS for building the styles to apply to highlighted content
 *
 */
betterlink_user_interface.createModule("Submissions.Viewer", function(api, apiInternal) {
	api.requireModules( ["Util", "Util.DOM", "Event Messaging", "Selection Highlighter", "Smooth Scrolling"] );

	var DEFAULT_HIGHLIGHT_CUSTOM_ELEMENT = "mark";				//the element type that will wrap the selections
	var DEFAULT_HIGHLIGHT_CSS_CLASS = "betterlink-highlight";	//the CSS class that will be applied to all highlight elements
	var DEFAULT_HIGHLIGHT_ELEMENT_ID = "highlighted_element";	//an ID that will be applied to all highlight wrapper elements
	var HIGHLIGHT_CSS = "{ background: lightskyblue; color: #000; opacity: 0.95; }";

	var highlighterIdentifier = 'submissionViewer';
	var highlighterInitialized = false;

	// always refer to config via index-notation so the symbol isn't obfuscated
	api['config'] = api['config'] || {};
	var highlightConfig = {
		'highlightCustomElement' : DEFAULT_HIGHLIGHT_CUSTOM_ELEMENT,
		'highlightCssClass' : DEFAULT_HIGHLIGHT_CSS_CLASS,
		'highlightCustomCssClass' : '',
		'highlightElementId' : DEFAULT_HIGHLIGHT_ELEMENT_ID
	};
	apiInternal.util.extend(api['config'], highlightConfig);

	apiInternal.addInitListener(initializeHighlighterStyles);
	apiInternal.events.registerObserverForRemoveBetterlink(removeDecorationFromLoadedSubmission);

	function initializeHighlighterStyles() {
		if(highlighterInitialized) {
			return;
		}

		highlighterInitialized = true;
		var highlightOptions = {

			// any element that's highlighted should have the following properties
			'elementProperties': {
				'id': api['config']['highlightElementId']
			},

			// elements that we will apply our CSS class to, instead of creating
			// a new container element. ex:
			// this is my text v.
			// this is my text
			//
			// Note: if the existing element doesn't have all of the properties
			// specified above, we'll create a new container element anyways.
			'tagsToPreserve': ["span", "a", "mark"],

			// element type that we will wrap around the selected content when
			// splitting text nodes or when we can't apply our class name to
			// an existing element
			'elementTagName': api['config']['highlightCustomElement'],

			// CSS class name that will be applied to each element that is
			// highlighted
			'cssClass': getHighlightCSSClass()
		};

		insertHighlightStyle();
		apiInternal.events.registerObserverForReadyToDecorate(highlightContent);

		apiInternal.highlighters.add(highlighterIdentifier, highlightOptions);
		apiInternal.events.fireHighlighterStylesInitialized();
	}

	function removeDecorationFromLoadedSubmission() {
		if(!highlighterInitialized) {
			displayNotInitialized();
			return;
		}

		apiInternal.highlighters.removeAllHighlights(highlighterIdentifier);
	}

	function highlightContent(contentType, selection) {
		if(!highlighterInitialized) {
			displayNotInitialized();
			return;
		}

		if(contentType === 'loadedSubmission') {
			apiInternal.highlighters.highlightSelection(highlighterIdentifier, selection);
			jumpToHighlightedContent();
		}
	}

	function jumpToHighlightedContent() {
		var destination = api['config']['highlightElementId'];
		var success = apiInternal.smoothScroll(destination, {pixelBuffer: 50});
		if(!success) {
			if(!window.location.hash || !api['config']['preserveHash']) {
				window.location.hash = destination;
			}
		}
	}

	function insertHighlightStyle() {
		// always add the default CSS style with the default class name
		// allow a custom class name to be applied to ignore this style
		apiInternal.util.dom.addCssByClass(api['config']['highlightCssClass'], HIGHLIGHT_CSS);
	}

	// checks if the client has defined a custom CSS class name to override
	// the default name that is provided
	function getHighlightCSSClass() {
		if(api['config']['highlightCustomCssClass'])
			return api['config']['highlightCustomCssClass'];
		else
			return api['config']['highlightCssClass'];
	}

	function displayNotInitialized() {
		apiInternal.warn("Highlighting not yet initialized");
	}
});
<commit_msg>switch opacity for padding in .betterlink-highlight<commit_after>/**
 * JS for building the styles to apply to highlighted content
 *
 */
betterlink_user_interface.createModule("Submissions.Viewer", function(api, apiInternal) {
	api.requireModules( ["Util", "Util.DOM", "Event Messaging", "Selection Highlighter", "Smooth Scrolling"] );

	var DEFAULT_HIGHLIGHT_CUSTOM_ELEMENT = "mark";				//the element type that will wrap the selections
	var DEFAULT_HIGHLIGHT_CSS_CLASS = "betterlink-highlight";	//the CSS class that will be applied to all highlight elements
	var DEFAULT_HIGHLIGHT_ELEMENT_ID = "highlighted_element";	//an ID that will be applied to all highlight wrapper elements
	var HIGHLIGHT_CSS = "{ background: lightskyblue; color: #000; padding: 0; }";

	var highlighterIdentifier = 'submissionViewer';
	var highlighterInitialized = false;

	// always refer to config via index-notation so the symbol isn't obfuscated
	api['config'] = api['config'] || {};
	var highlightConfig = {
		'highlightCustomElement' : DEFAULT_HIGHLIGHT_CUSTOM_ELEMENT,
		'highlightCssClass' : DEFAULT_HIGHLIGHT_CSS_CLASS,
		'highlightCustomCssClass' : '',
		'highlightElementId' : DEFAULT_HIGHLIGHT_ELEMENT_ID
	};
	apiInternal.util.extend(api['config'], highlightConfig);

	apiInternal.addInitListener(initializeHighlighterStyles);
	apiInternal.events.registerObserverForRemoveBetterlink(removeDecorationFromLoadedSubmission);

	function initializeHighlighterStyles() {
		if(highlighterInitialized) {
			return;
		}

		highlighterInitialized = true;
		var highlightOptions = {

			// any element that's highlighted should have the following properties
			'elementProperties': {
				'id': api['config']['highlightElementId']
			},

			// elements that we will apply our CSS class to, instead of creating
			// a new container element. ex:
			// this is my text v.
			// this is my text
			//
			// Note: if the existing element doesn't have all of the properties
			// specified above, we'll create a new container element anyways.
			'tagsToPreserve': ["span", "a", "mark"],

			// element type that we will wrap around the selected content when
			// splitting text nodes or when we can't apply our class name to
			// an existing element
			'elementTagName': api['config']['highlightCustomElement'],

			// CSS class name that will be applied to each element that is
			// highlighted
			'cssClass': getHighlightCSSClass()
		};

		insertHighlightStyle();
		apiInternal.events.registerObserverForReadyToDecorate(highlightContent);

		apiInternal.highlighters.add(highlighterIdentifier, highlightOptions);
		apiInternal.events.fireHighlighterStylesInitialized();
	}

	function removeDecorationFromLoadedSubmission() {
		if(!highlighterInitialized) {
			displayNotInitialized();
			return;
		}

		apiInternal.highlighters.removeAllHighlights(highlighterIdentifier);
	}

	function highlightContent(contentType, selection) {
		if(!highlighterInitialized) {
			displayNotInitialized();
			return;
		}

		if(contentType === 'loadedSubmission') {
			apiInternal.highlighters.highlightSelection(highlighterIdentifier, selection);
			jumpToHighlightedContent();
		}
	}

	function jumpToHighlightedContent() {
		var destination = api['config']['highlightElementId'];
		var success = apiInternal.smoothScroll(destination, {pixelBuffer: 50});
		if(!success) {
			if(!window.location.hash || !api['config']['preserveHash']) {
				window.location.hash = destination;
			}
		}
	}

	function insertHighlightStyle() {
		// always add the default CSS style with the default class name
		// allow a custom class name to be applied to ignore this style
		apiInternal.util.dom.addCssByClass(api['config']['highlightCssClass'], HIGHLIGHT_CSS);
	}

	// checks if the client has defined a custom CSS class name to override
	// the default name that is provided
	function getHighlightCSSClass() {
		if(api['config']['highlightCustomCssClass'])
			return api['config']['highlightCustomCssClass'];
		else
			return api['config']['highlightCssClass'];
	}

	function displayNotInitialized() {
		apiInternal.warn("Highlighting not yet initialized");
	}
});
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    gulp = require('gulp'),
    gutil= require('gulp-util'),
    eslint = require('gulp-eslint'),
    jscs = require('gulp-jscs'),
    args = require('minimist')(process.argv.slice(2)),
    scm = require('@zalando/node-scm-source'),
    del = require( 'del' ),
    shell = require('gulp-shell'),
    replace = require('gulp-replace'),
    rename = require('gulp-rename'),
    critical = require('critical'),
    webpack = require('webpack');

var LODASH_FUNCS = [
        // own
        'chain',
        'debounce',
        'filter',
        'findLastIndex',
        'flatten',
        'forOwn',
        'groupBy',
        'intersection',
        'pluck',
        'reverse',
        'sortBy',
        'take',
        'times',
        'value',
        'values'
    ],
    LODASH_INCLUDE = 'include=' + LODASH_FUNCS.join(',');

/**
 * Deletes files or directories
 * @param  {array} globs Globs describing things to remove
 * @return {function} Function that deletes the things
 */
function remove(globs) {
    return function(done) {
        del(globs, done);
    };
}

// removes the output folder
gulp.task( 'clean', remove(['dist/**/*']));

// custom lodash build
gulp.task('lodash', shell.task([
    '../node_modules/lodash-cli/bin/lodash modern ' + LODASH_INCLUDE + ' -d -o lib/common/src/lodash.custom.js'
]));

// runs webpack and creates a bundle
gulp.task('pack', ['clean', 'lodash'], function(done) {
    var webpackConfig = require('./webpack.production.config');
    // here we could override production-specific properties
    webpack(
        webpackConfig,
        function(err, data) {
            if (err) {
                throw new gutil.PluginError('webpack', err);
            }
            gutil.log('[webpack]', data.toString());
            done();
        });
});

gulp.task('format', function() {
    return gulp
            .src(['lib/**/*.js', '!lib/common/src/lodash.custom.js'])
            .pipe(jscs({
                esnext: true,
                configPath: './.jscsrc'
            }));
});

gulp.task('scm-source', function(done) {
    fs.writeFile('../scm-source.json', JSON.stringify(scm(), null, 4), done);
});

// lints the source code using .eslintrc
gulp.task('lint', function() {
    return gulp
            .src(['lib/**/*.js', 'lib/**/*.jsx', '!lib/common/src/lodash.custom.js'])
            .pipe(eslint())
            .pipe(eslint.format())
            .pipe(eslint.failAfterError());
});

gulp.task('copy', function() {
    return gulp
            .src('stups_favicon.png')
            .pipe(gulp.dest('dist'));
});

gulp.task('extract-atf-css', ['cachebust', 'pack'], function(done) {
    var html = String(fs.readFileSync(path.join(__dirname + '/dist/index-prod.html')));
    // remove some stuff that critical doesn't like
    html = html
            .replace(/\?v=\d+/gi, '')
            .replace(/\/dist\//gi, '');

    critical.generate({
        base: './dist',
        html: html,
        dest: 'site.css',
        dimensions: [{
            // generic 13" laptop
            width: 1280,
            height: 800
        }, {
            // iphone 4s
            width: 640,
            height: 960
        }],
        minify: true
    }, function(err, css) {
        if (err) {
            console.log(err);
            return;
        }
        done();
    });
});

gulp.task('inline-atf-css', ['extract-atf-css'], function(done) {
    var inline = String(fs.readFileSync(path.join(__dirname + '/dist/site.css')));
    return gulp
            .src('dist/index-prod.html')
            .pipe(replace('${inline}', inline))
            .pipe(rename('index.html'))
            .pipe(gulp.dest('dist'));
});

gulp.task('cachebust', ['clean'], function() {
    return gulp
                .src('index-prod.html')
                .pipe(replace('${timestamp}', Date.now()))
                .pipe(gulp.dest('dist'));
});

gulp.task('build', ['pack', 'inline-atf-css', 'copy', 'scm-source']);

gulp.task('watch', ['watch:js']);
gulp.task('default', ['watch']);
<commit_msg>#162 add missing lodash func<commit_after>var fs = require('fs'),
    path = require('path'),
    gulp = require('gulp'),
    gutil= require('gulp-util'),
    eslint = require('gulp-eslint'),
    jscs = require('gulp-jscs'),
    args = require('minimist')(process.argv.slice(2)),
    scm = require('@zalando/node-scm-source'),
    del = require( 'del' ),
    shell = require('gulp-shell'),
    replace = require('gulp-replace'),
    rename = require('gulp-rename'),
    critical = require('critical'),
    webpack = require('webpack');

var LODASH_FUNCS = [
        // own
        'chain',
        'debounce',
        'extend',
        'filter',
        'findLastIndex',
        'flatten',
        'forOwn',
        'groupBy',
        'intersection',
        'pluck',
        'reverse',
        'sortBy',
        'take',
        'times',
        'value',
        'values'
    ],
    LODASH_INCLUDE = 'include=' + LODASH_FUNCS.join(',');

/**
 * Deletes files or directories
 * @param  {array} globs Globs describing things to remove
 * @return {function} Function that deletes the things
 */
function remove(globs) {
    return function(done) {
        del(globs, done);
    };
}

// removes the output folder
gulp.task( 'clean', remove(['dist/**/*']));

// custom lodash build
gulp.task('lodash', shell.task([
    '../node_modules/lodash-cli/bin/lodash modern ' + LODASH_INCLUDE + ' -d -o lib/common/src/lodash.custom.js'
]));

// runs webpack and creates a bundle
gulp.task('pack', ['clean', 'lodash'], function(done) {
    var webpackConfig = require('./webpack.production.config');
    // here we could override production-specific properties
    webpack(
        webpackConfig,
        function(err, data) {
            if (err) {
                throw new gutil.PluginError('webpack', err);
            }
            gutil.log('[webpack]', data.toString());
            done();
        });
});

gulp.task('format', function() {
    return gulp
            .src(['lib/**/*.js', '!lib/common/src/lodash.custom.js'])
            .pipe(jscs({
                esnext: true,
                configPath: './.jscsrc'
            }));
});

gulp.task('scm-source', function(done) {
    fs.writeFile('../scm-source.json', JSON.stringify(scm(), null, 4), done);
});

// lints the source code using .eslintrc
gulp.task('lint', function() {
    return gulp
            .src(['lib/**/*.js', 'lib/**/*.jsx', '!lib/common/src/lodash.custom.js'])
            .pipe(eslint())
            .pipe(eslint.format())
            .pipe(eslint.failAfterError());
});

gulp.task('copy', function() {
    return gulp
            .src('stups_favicon.png')
            .pipe(gulp.dest('dist'));
});

gulp.task('extract-atf-css', ['cachebust', 'pack'], function(done) {
    var html = String(fs.readFileSync(path.join(__dirname + '/dist/index-prod.html')));
    // remove some stuff that critical doesn't like
    html = html
            .replace(/\?v=\d+/gi, '')
            .replace(/\/dist\//gi, '');

    critical.generate({
        base: './dist',
        html: html,
        dest: 'site.css',
        dimensions: [{
            // generic 13" laptop
            width: 1280,
            height: 800
        }, {
            // iphone 4s
            width: 640,
            height: 960
        }],
        minify: true
    }, function(err, css) {
        if (err) {
            console.log(err);
            return;
        }
        done();
    });
});

gulp.task('inline-atf-css', ['extract-atf-css'], function(done) {
    var inline = String(fs.readFileSync(path.join(__dirname + '/dist/site.css')));
    return gulp
            .src('dist/index-prod.html')
            .pipe(replace('${inline}', inline))
            .pipe(rename('index.html'))
            .pipe(gulp.dest('dist'));
});

gulp.task('cachebust', ['clean'], function() {
    return gulp
                .src('index-prod.html')
                .pipe(replace('${timestamp}', Date.now()))
                .pipe(gulp.dest('dist'));
});

gulp.task('build', ['pack', 'inline-atf-css', 'copy', 'scm-source']);

gulp.task('watch', ['watch:js']);
gulp.task('default', ['watch']);
<|endoftext|>


<commit_before>'use strict';

var http = require('http'),
    https = require('https'),
    url = require('url'),
    Q = require('q'),
    AbstractProxy = require('../abstractProxy'),
    combinators = require('../../util/combinators'),
    querystring = require('querystring');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

function create (logger) {

    function setupProxy (baseUrl, originalRequest) {
        var parts = url.parse(baseUrl),
            protocol = parts.protocol === 'https:' ? https : http,
            options = {
                method: originalRequest.method,
                hostname: parts.hostname,
                port: parts.port,
                auth: parts.auth,
                path: originalRequest.path + '?' + querystring.stringify(originalRequest.query),
                headers: originalRequest.headers
            };
        options.headers.connection = 'close';

        var proxiedRequest = protocol.request(options);
        if (originalRequest.body) {
            proxiedRequest.write(originalRequest.body);
        }
        return proxiedRequest;
    }

    function proxy (proxiedRequest) {
        var deferred = Q.defer();

        proxiedRequest.end();

        proxiedRequest.once('response', function (response) {
            response.body = '';
            response.setEncoding('utf8');
            response.on('data', function (chunk) { response.body += chunk; });
            response.on('end', function () {
                var stubResponse = {
                    statusCode: response.statusCode,
                    headers: response.headers,
                    body: response.body
                };
                deferred.resolve(stubResponse);
            });
        });

        return deferred.promise;
    }

    return AbstractProxy.implement(logger, {
        formatRequest: combinators.identity,
        formatResponse: combinators.identity,
        formatDestination: combinators.identity,
        setupProxy: setupProxy,
        proxy: proxy
    });
}

module.exports = {
    create: create
};
<commit_msg>Removed unnecessary ? from proxy urls without query params https://github.com/bbyars/mountebank/issues/46<commit_after>'use strict';

var http = require('http'),
    https = require('https'),
    url = require('url'),
    Q = require('q'),
    AbstractProxy = require('../abstractProxy'),
    combinators = require('../../util/combinators'),
    querystring = require('querystring');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

function create (logger) {

    function toUrl (path, query) {
        var tail = querystring.stringify(query);
        if (tail === '') {
            return path;
        }
        return path + '?' + tail;
    }

    function setupProxy (baseUrl, originalRequest) {
        var parts = url.parse(baseUrl),
            protocol = parts.protocol === 'https:' ? https : http,
            options = {
                method: originalRequest.method,
                hostname: parts.hostname,
                port: parts.port,
                auth: parts.auth,
                path: toUrl(originalRequest.path, originalRequest.query),
                headers: originalRequest.headers
            };
        options.headers.connection = 'close';

        var proxiedRequest = protocol.request(options);
        if (originalRequest.body) {
            proxiedRequest.write(originalRequest.body);
        }
        return proxiedRequest;
    }

    function proxy (proxiedRequest) {
        var deferred = Q.defer();

        proxiedRequest.end();

        proxiedRequest.once('response', function (response) {
            response.body = '';
            response.setEncoding('utf8');
            response.on('data', function (chunk) { response.body += chunk; });
            response.on('end', function () {
                var stubResponse = {
                    statusCode: response.statusCode,
                    headers: response.headers,
                    body: response.body
                };
                deferred.resolve(stubResponse);
            });
        });

        return deferred.promise;
    }

    return AbstractProxy.implement(logger, {
        formatRequest: combinators.identity,
        formatResponse: combinators.identity,
        formatDestination: combinators.identity,
        setupProxy: setupProxy,
        proxy: proxy
    });
}

module.exports = {
    create: create
};
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
sap.ui.define([
	"./library"], function (library) {
	"use strict";

	/**
	 * DynamicPage Title renderer.
	 * @namespace
	 */
	var DynamicPageTitleRenderer = {
		apiVersion: 2
	};

	/**
	 * Renders the HTML for the given control, using the provided {@link sap.ui.core.RenderManager}.
	 *
	 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the Render-Output-Buffer
	 * @param {sap.ui.core.Control} oDynamicPageTitle An object representation of the control that should be rendered
	 */
	DynamicPageTitleRenderer.render = function (oRm, oDynamicPageTitle) {
		var oDynamicPageTitleState = oDynamicPageTitle._getState(),
			sSapFDynamicPageTitle = "sapFDynamicPageTitle",
			sBackgroundDesign = oDynamicPageTitle.getBackgroundDesign(),
			sLabelledBy = oDynamicPageTitle._getARIALabelReferences(oDynamicPageTitle._bExpandedState) || oDynamicPageTitle.DEFAULT_HEADER_TEXT_ID,
			sDescribedBy = oDynamicPageTitle._getAriaDescribedByReferences();

		// DynamicPageTitle Root DOM Element.
		oRm.openStart("div", oDynamicPageTitle);
		oRm.class(sSapFDynamicPageTitle);

		if (sBackgroundDesign) {
			oRm.class(sSapFDynamicPageTitle + sBackgroundDesign);
		}

		oRm.openEnd();

		oRm.openStart("span", oDynamicPageTitle.getId() + "-focusSpan")
			.class("sapFDynamicPageTitleFocusSpan")
			.attr("role", "button")
			.attr("aria-expanded", oDynamicPageTitle._bExpandedState)
			.attr("aria-labelledby", sLabelledBy)
			.attr("aria-describedby", sDescribedBy)
			.attr("tabindex", 0);

		oRm.openEnd()
			.close("span");

		this._renderTopArea(oRm, oDynamicPageTitleState);
		this._renderMainArea(oRm, oDynamicPageTitleState);
		this._renderSnappedExpandedContentArea(oRm, oDynamicPageTitleState);

		if (oDynamicPageTitleState.hasSnappedTitleOnMobile) {
			this._renderSnappedTitleOnMobile(oRm, oDynamicPageTitleState);
		}

		oRm.renderControl(oDynamicPageTitleState.expandButton);

		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderTopArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasTopContent) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-top");
			oRm.class("sapFDynamicPageTitleTop");
			if (oDynamicPageTitleState.hasOnlyBreadcrumbs){
				oRm.class("sapFDynamicPageTitleTopBreadCrumbsOnly");
			}
			if (oDynamicPageTitleState.hasOnlyNavigationActions){
				oRm.class("sapFDynamicPageTitleTopNavActionsOnly");
			}
			oRm.openEnd();

			this._renderTopBreadcrumbsArea(oRm, oDynamicPageTitleState);
			this._renderTopNavigationArea(oRm, oDynamicPageTitleState);

			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderTopBreadcrumbsArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.breadcrumbs) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-breadcrumbs");
			oRm.class("sapFDynamicPageTitleTopLeft");
			oRm.openEnd();
			oRm.renderControl(oDynamicPageTitleState.breadcrumbs);
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderTopNavigationArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasNavigationActions) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-topNavigationArea");
			oRm.class("sapFDynamicPageTitleTopRight");
			oRm.openEnd();
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderMainArea = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-main");
		oRm.class("sapFDynamicPageTitleMain");
		if (!oDynamicPageTitleState.hasContent) {
			oRm.class("sapFDynamicPageTitleMainNoContent");
		}
		oRm.openEnd();

		oRm.openStart("div");
		oRm.class("sapFDynamicPageTitleMainInner");
		oRm.openEnd();

		this._renderMainHeadingArea(oRm, oDynamicPageTitleState);
		this._renderMainContentArea(oRm, oDynamicPageTitleState);
		this._renderMainActionsArea(oRm, oDynamicPageTitleState);

		oRm.close("div");

		this._renderMainNavigationArea(oRm, oDynamicPageTitleState);

		oRm.close("div"); // Root end.
	};

	DynamicPageTitleRenderer._renderMainHeadingArea = function (oRm, oDynamicPageTitleState) {
		// Heading Area
		oRm.openStart("div", oDynamicPageTitleState.id + "-left-inner");
		oRm.class("sapFDynamicPageTitleMainHeading");
		oRm.style("flex-shrink", oDynamicPageTitleState.headingAreaShrinkFactor.toString());
		oRm.openEnd();
		// Left Area -> heading aggregation
		oRm.openStart("div");
		oRm.class("sapFDynamicPageTitleHeading-CTX");
		oRm.class("sapFDynamicPageTitleMainHeadingInner");
		oRm.openEnd();
		if (oDynamicPageTitleState.heading) {
			// If heading is given, it should be used
			oRm.renderControl(oDynamicPageTitleState.heading);
		} else {
			// Otherwise, snapped and expanded heading should be used
			if (oDynamicPageTitleState.snappedHeading) {
				DynamicPageTitleRenderer._renderSnappedHeading(oRm, oDynamicPageTitleState);
			}
			if (oDynamicPageTitleState.expandedHeading) {
				DynamicPageTitleRenderer._renderExpandHeading(oRm, oDynamicPageTitleState);
			}
		}
		oRm.close("div");

		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainContentArea = function (oRm, oDynamicPageTitleState) {
		// Content aggregation
		oRm.openStart("div", oDynamicPageTitleState.id + "-content");
		oRm.class("sapFDynamicPageTitleMainContent");
		oRm.class("sapFDynamicPageTitleContent-CTX");
		oRm.style("flex-shrink", oDynamicPageTitleState.contentAreaShrinkFactor.toString());
		if (oDynamicPageTitleState.contentAreaFlexBasis) {
			oRm.style("flex-basis", oDynamicPageTitleState.contentAreaFlexBasis);
		}
		if (oDynamicPageTitleState.contentAreaHasContent) {
			oRm.class("sapFDynamicPageTitleMainContentHasContent");
		}
		oRm.openEnd();
		oDynamicPageTitleState.content.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainActionsArea = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-mainActions");
		oRm.class("sapFDynamicPageTitleMainActions");
		oRm.style("flex-shrink", oDynamicPageTitleState.actionsAreaShrinkFactor.toString());
		if (oDynamicPageTitleState.actionsAreaFlexBasis) {
			oRm.style("flex-basis", oDynamicPageTitleState.actionsAreaFlexBasis);
		}
		if (oDynamicPageTitleState.actionsAreaHasContent) {
			oRm.class("sapFDynamicPageTitleMainActionsHasContent");
		}
		oRm.openEnd();
		if (oDynamicPageTitleState.hasActions) {
			oRm.renderControl(oDynamicPageTitleState.actionBar);
		}
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainNavigationArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasNavigationActions) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-mainNavigationAreaWrapper");
			oRm.class("sapFDynamicPageTitleMainNavigationArea");
			oRm.openEnd();

			oRm.renderControl(oDynamicPageTitleState.separator);

			oRm.openStart("div", oDynamicPageTitleState.id + "-mainNavigationArea");
			oRm.class("sapFDynamicPageTitleMainNavigationAreaInner");
			oRm.openEnd();
			oRm.close("div");
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderSnappedExpandedContentArea = function (oRm, oDynamicPageTitleState) {
		// Heading Area -> snappedContent/expandContent aggregation
		if (oDynamicPageTitleState.hasAdditionalContent) {
			oRm.openStart("div");
			oRm.class("sapFDynamicPageTitleMainHeadingSnappedExpandContent");
			oRm.openEnd();
			if (oDynamicPageTitleState.hasSnappedContent && !oDynamicPageTitleState.hasSnappedTitleOnMobile) {
				DynamicPageTitleRenderer._renderSnappedContent(oRm, oDynamicPageTitleState);
			}
			if (oDynamicPageTitleState.hasExpandedContent) {
				DynamicPageTitleRenderer._renderExpandContent(oRm, oDynamicPageTitleState);
			}
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderExpandHeading = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-expand-heading-wrapper");
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.expandedHeading);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedHeading = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-heading-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
			oRm.class("sapUiForcedHidden");
		}
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.snappedHeading);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderExpandContent = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-expand-wrapper");
		oRm.openEnd();
		oDynamicPageTitleState.expandedContent.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedContent = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
			oRm.class("sapUiForcedHidden");
		}
		oRm.class("sapFDynamicPageTitleSnapped");
		oRm.openEnd();
		oDynamicPageTitleState.snappedContent.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedTitleOnMobile = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-title-on-mobile-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
			oRm.class("sapUiForcedHidden");
		}
		oRm.class("sapFDynamicPageTitleSnappedTitleOnMobile");
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.snappedTitleOnMobileContext);
		oRm.renderControl(oDynamicPageTitleState.snappedTitleOnMobileIcon);
		oRm.close("div");
	};

	return DynamicPageTitleRenderer;

}, /* bExport= */ true);
<commit_msg>[FIX] sap.f.DynamicPageTitle: Revert fix for redundant tab stops<commit_after>/*!
 * ${copyright}
 */
sap.ui.define([
	"./library"], function (library) {
	"use strict";

	/**
	 * DynamicPage Title renderer.
	 * @namespace
	 */
	var DynamicPageTitleRenderer = {
		apiVersion: 2
	};

	/**
	 * Renders the HTML for the given control, using the provided {@link sap.ui.core.RenderManager}.
	 *
	 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the Render-Output-Buffer
	 * @param {sap.ui.core.Control} oDynamicPageTitle An object representation of the control that should be rendered
	 */
	DynamicPageTitleRenderer.render = function (oRm, oDynamicPageTitle) {
		var oDynamicPageTitleState = oDynamicPageTitle._getState(),
			sSapFDynamicPageTitle = "sapFDynamicPageTitle",
			sBackgroundDesign = oDynamicPageTitle.getBackgroundDesign(),
			sLabelledBy = oDynamicPageTitle._getARIALabelReferences(oDynamicPageTitle._bExpandedState) || oDynamicPageTitle.DEFAULT_HEADER_TEXT_ID,
			sDescribedBy = oDynamicPageTitle._getAriaDescribedByReferences();

		// DynamicPageTitle Root DOM Element.
		oRm.openStart("div", oDynamicPageTitle);
		oRm.class(sSapFDynamicPageTitle);

		if (sBackgroundDesign) {
			oRm.class(sSapFDynamicPageTitle + sBackgroundDesign);
		}

		oRm.openEnd();

		oRm.openStart("span", oDynamicPageTitle.getId() + "-focusSpan")
			.class("sapFDynamicPageTitleFocusSpan")
			.attr("role", "button")
			.attr("aria-expanded", oDynamicPageTitle._bExpandedState)
			.attr("aria-labelledby", sLabelledBy)
			.attr("aria-describedby", sDescribedBy)
			.attr("tabindex", 0);

		oRm.openEnd()
			.close("span");

		this._renderTopArea(oRm, oDynamicPageTitleState);
		this._renderMainArea(oRm, oDynamicPageTitleState);
		this._renderSnappedExpandedContentArea(oRm, oDynamicPageTitleState);

		if (oDynamicPageTitleState.hasSnappedTitleOnMobile) {
			this._renderSnappedTitleOnMobile(oRm, oDynamicPageTitleState);
		}

		oRm.renderControl(oDynamicPageTitleState.expandButton);

		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderTopArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasTopContent) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-top");
			oRm.class("sapFDynamicPageTitleTop");
			if (oDynamicPageTitleState.hasOnlyBreadcrumbs){
				oRm.class("sapFDynamicPageTitleTopBreadCrumbsOnly");
			}
			if (oDynamicPageTitleState.hasOnlyNavigationActions){
				oRm.class("sapFDynamicPageTitleTopNavActionsOnly");
			}
			oRm.openEnd();

			this._renderTopBreadcrumbsArea(oRm, oDynamicPageTitleState);
			this._renderTopNavigationArea(oRm, oDynamicPageTitleState);

			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderTopBreadcrumbsArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.breadcrumbs) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-breadcrumbs");
			oRm.class("sapFDynamicPageTitleTopLeft");
			oRm.openEnd();
			oRm.renderControl(oDynamicPageTitleState.breadcrumbs);
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderTopNavigationArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasNavigationActions) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-topNavigationArea");
			oRm.class("sapFDynamicPageTitleTopRight");
			oRm.openEnd();
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderMainArea = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-main");
		oRm.class("sapFDynamicPageTitleMain");
		if (!oDynamicPageTitleState.hasContent) {
			oRm.class("sapFDynamicPageTitleMainNoContent");
		}
		oRm.openEnd();

		oRm.openStart("div");
		oRm.class("sapFDynamicPageTitleMainInner");
		oRm.openEnd();

		this._renderMainHeadingArea(oRm, oDynamicPageTitleState);
		this._renderMainContentArea(oRm, oDynamicPageTitleState);
		this._renderMainActionsArea(oRm, oDynamicPageTitleState);

		oRm.close("div");

		this._renderMainNavigationArea(oRm, oDynamicPageTitleState);

		oRm.close("div"); // Root end.
	};

	DynamicPageTitleRenderer._renderMainHeadingArea = function (oRm, oDynamicPageTitleState) {
		// Heading Area
		oRm.openStart("div", oDynamicPageTitleState.id + "-left-inner");
		oRm.class("sapFDynamicPageTitleMainHeading");
		oRm.style("flex-shrink", oDynamicPageTitleState.headingAreaShrinkFactor.toString());
		oRm.openEnd();
		// Left Area -> heading aggregation
		oRm.openStart("div");
		oRm.class("sapFDynamicPageTitleHeading-CTX");
		oRm.class("sapFDynamicPageTitleMainHeadingInner");
		oRm.openEnd();
		if (oDynamicPageTitleState.heading) {
			// If heading is given, it should be used
			oRm.renderControl(oDynamicPageTitleState.heading);
		} else {
			// Otherwise, snapped and expanded heading should be used
			if (oDynamicPageTitleState.snappedHeading) {
				DynamicPageTitleRenderer._renderSnappedHeading(oRm, oDynamicPageTitleState);
			}
			if (oDynamicPageTitleState.expandedHeading) {
				DynamicPageTitleRenderer._renderExpandHeading(oRm, oDynamicPageTitleState);
			}
		}
		oRm.close("div");

		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainContentArea = function (oRm, oDynamicPageTitleState) {
		// Content aggregation
		oRm.openStart("div", oDynamicPageTitleState.id + "-content");
		oRm.class("sapFDynamicPageTitleMainContent");
		oRm.class("sapFDynamicPageTitleContent-CTX");
		oRm.style("flex-shrink", oDynamicPageTitleState.contentAreaShrinkFactor.toString());
		if (oDynamicPageTitleState.contentAreaFlexBasis) {
			oRm.style("flex-basis", oDynamicPageTitleState.contentAreaFlexBasis);
		}
		if (oDynamicPageTitleState.contentAreaHasContent) {
			oRm.class("sapFDynamicPageTitleMainContentHasContent");
		}
		oRm.openEnd();
		oDynamicPageTitleState.content.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainActionsArea = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-mainActions");
		oRm.class("sapFDynamicPageTitleMainActions");
		oRm.style("flex-shrink", oDynamicPageTitleState.actionsAreaShrinkFactor.toString());
		if (oDynamicPageTitleState.actionsAreaFlexBasis) {
			oRm.style("flex-basis", oDynamicPageTitleState.actionsAreaFlexBasis);
		}
		if (oDynamicPageTitleState.actionsAreaHasContent) {
			oRm.class("sapFDynamicPageTitleMainActionsHasContent");
		}
		oRm.openEnd();
		if (oDynamicPageTitleState.hasActions) {
			oRm.renderControl(oDynamicPageTitleState.actionBar);
		}
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderMainNavigationArea = function (oRm, oDynamicPageTitleState) {
		if (oDynamicPageTitleState.hasNavigationActions) {
			oRm.openStart("div", oDynamicPageTitleState.id + "-mainNavigationAreaWrapper");
			oRm.class("sapFDynamicPageTitleMainNavigationArea");
			oRm.openEnd();

			oRm.renderControl(oDynamicPageTitleState.separator);

			oRm.openStart("div", oDynamicPageTitleState.id + "-mainNavigationArea");
			oRm.class("sapFDynamicPageTitleMainNavigationAreaInner");
			oRm.openEnd();
			oRm.close("div");
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderSnappedExpandedContentArea = function (oRm, oDynamicPageTitleState) {
		// Heading Area -> snappedContent/expandContent aggregation
		if (oDynamicPageTitleState.hasAdditionalContent) {
			oRm.openStart("div");
			oRm.class("sapFDynamicPageTitleMainHeadingSnappedExpandContent");
			oRm.openEnd();
			if (oDynamicPageTitleState.hasSnappedContent && !oDynamicPageTitleState.hasSnappedTitleOnMobile) {
				DynamicPageTitleRenderer._renderSnappedContent(oRm, oDynamicPageTitleState);
			}
			if (oDynamicPageTitleState.hasExpandedContent) {
				DynamicPageTitleRenderer._renderExpandContent(oRm, oDynamicPageTitleState);
			}
			oRm.close("div");
		}
	};

	DynamicPageTitleRenderer._renderExpandHeading = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-expand-heading-wrapper");
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.expandedHeading);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedHeading = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-heading-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
		}
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.snappedHeading);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderExpandContent = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-expand-wrapper");
		oRm.openEnd();
		oDynamicPageTitleState.expandedContent.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedContent = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
		}
		oRm.class("sapFDynamicPageTitleSnapped");
		oRm.openEnd();
		oDynamicPageTitleState.snappedContent.forEach(oRm.renderControl, oRm);
		oRm.close("div");
	};

	DynamicPageTitleRenderer._renderSnappedTitleOnMobile = function (oRm, oDynamicPageTitleState) {
		oRm.openStart("div", oDynamicPageTitleState.id + "-snapped-title-on-mobile-wrapper");
		if (!oDynamicPageTitleState.isSnapped) {
			oRm.class("sapUiHidden");
		}
		oRm.class("sapFDynamicPageTitleSnappedTitleOnMobile");
		oRm.openEnd();
		oRm.renderControl(oDynamicPageTitleState.snappedTitleOnMobileContext);
		oRm.renderControl(oDynamicPageTitleState.snappedTitleOnMobileIcon);
		oRm.close("div");
	};

	return DynamicPageTitleRenderer;

}, /* bExport= */ true);
<|endoftext|>


<commit_before>import {
	BufferGeometry, Float32BufferAttribute,
	FaceColors, Mesh,
	MeshLambertMaterial
} from '../../Three';

import { StencilLib } from '../../core/StencilLib';

const unselectedMaterial = new MeshLambertMaterial( { color: 0x444444, vertexColors: FaceColors } );

function Walls () {

	const geometry = new BufferGeometry();

	Mesh.call( this, geometry, unselectedMaterial );

	return this;

}

Walls.prototype = Object.create( Mesh.prototype );

Walls.prototype.onBeforeRender = StencilLib.featureOnBeforeRender;
Walls.prototype.onAfterRender = StencilLib.featureOnAfterRender;

Walls.prototype.type = 'Walls';
Walls.prototype.ready = true;

Walls.prototype.addWalls = function ( vertices, indices, indexRuns ) {

	const geometry = this.geometry;
	const position = geometry.getAttribute( 'position' );

	if ( position === undefined ) {

		const positions = new Float32BufferAttribute( vertices.length * 3, 3 );

		geometry.addAttribute( 'position', positions.copyVector3sArray( vertices ) );

		geometry.setIndex( indices );

	} else {

		// FIXME: alllocate new buffer of old + new length, adjust indexs and append old data after new data.

		console.error( 'Walls: appending not yet implemented' );

	}

	geometry.computeVertexNormals();
	geometry.computeBoundingBox();

	this.indexRuns = indexRuns;

	return this;

};

Walls.prototype.setShading = function ( selectedRuns, selectedMaterial ) {

	const geometry = this.geometry;
	const indexRuns = this.indexRuns;

	geometry.clearGroups();

	this.visible = true && this.ready;

	if ( selectedRuns.size && indexRuns ) {

		this.material = [ selectedMaterial, unselectedMaterial ];

		let indexRun = indexRuns[ 0 ];

		let start = indexRun.start;
		let count = indexRun.count;

		let currentMaterial;
		let lastMaterial = selectedRuns.has( indexRun.survey ) ? 0 : 1;

		// merge adjacent runs with shared material.

		for ( var run = 1, l = indexRuns.length; run < l; run++ ) {

			indexRun = indexRuns[ run ];

			currentMaterial = selectedRuns.has( indexRun.survey ) ? 0 : 1;

			if ( currentMaterial === lastMaterial && indexRun.start === start + count ) {

				count += indexRun.count;

			} else {

				geometry.addGroup( start, count, lastMaterial );

				start = indexRun.start;
				count = indexRun.count;

				lastMaterial = currentMaterial;

			}

		}

		geometry.addGroup( start, count, lastMaterial );

	} else {

		this.material = selectedMaterial;

	}

};

Walls.prototype.cutRuns = function ( selectedRuns ) {

	const geometry = this.geometry;

	const vertices = geometry.getAttribute( 'position' );
	const indices = geometry.index;

	const indexRuns = this.indexRuns;

	const newIndices = [];
	const newVertices = [];

	const newIndexRuns = [];

	// map old vertex index values to new index values
	const vMap = new Map();

	const l = indexRuns.length;
	var run;

	for ( run = 0; run < l; run++ ) {

		const indexRun = indexRuns[ run ];

		let i, newVertexIndex = 0, fp = 0;

		if ( selectedRuns.has( indexRun.survey ) ) {

			const start = indexRun.start;
			const count = indexRun.count;

			const end = start + count;

			const itemSize = vertices.itemSize;
			const oldVertices = vertices.array;

			for ( i = start; i < end; i++ ) {

				const index = indices.getX( i );

				let newIndex = vMap.get( index );

				if ( newIndex === undefined ) {

					const offset = index * itemSize;

					newIndex = newVertexIndex++;

					vMap.set( index, newIndex );

					newVertices.push( oldVertices[ offset ], oldVertices[ offset + 1 ], oldVertices[ offset + 2 ] );

				}

				newIndices.push( newIndex );

			}

			indexRun.start = fp;

			fp += count;

			newIndexRuns.push( indexRun );

		}

	}

	if ( newIndices.length === 0 ) return false;

	// replace position and index attributes - dispose of old attributes
	geometry.index.setArray( new indices.array.constructor( newIndices ) );
	geometry.index.needsUpdate = true;

	vertices.setArray( new Float32Array( newVertices ) );
	vertices.needsUpdate = true;

	geometry.computeVertexNormals();
	geometry.computeBoundingBox();

	this.indexRuns = newIndexRuns;

	return true;

};

export { Walls };
<commit_msg>revert change that broke cut operation<commit_after>import {
	BufferGeometry, Float32BufferAttribute,
	FaceColors, Mesh,
	MeshLambertMaterial
} from '../../Three';

import { StencilLib } from '../../core/StencilLib';

const unselectedMaterial = new MeshLambertMaterial( { color: 0x444444, vertexColors: FaceColors } );

function Walls () {

	const geometry = new BufferGeometry();

	Mesh.call( this, geometry, unselectedMaterial );

	this.type = 'Walls';

	return this;

}

Walls.prototype = Object.create( Mesh.prototype );

Walls.prototype.onBeforeRender = StencilLib.featureOnBeforeRender;
Walls.prototype.onAfterRender = StencilLib.featureOnAfterRender;

Walls.prototype.ready = true;

Walls.prototype.addWalls = function ( vertices, indices, indexRuns ) {

	const geometry = this.geometry;
	const position = geometry.getAttribute( 'position' );

	if ( position === undefined ) {

		const positions = new Float32BufferAttribute( vertices.length * 3, 3 );

		geometry.addAttribute( 'position', positions.copyVector3sArray( vertices ) );

		geometry.setIndex( indices );

	} else {

		// FIXME: alllocate new buffer of old + new length, adjust indexs and append old data after new data.

		console.error( 'Walls: appending not yet implemented' );

	}

	geometry.computeVertexNormals();
	geometry.computeBoundingBox();

	this.indexRuns = indexRuns;

	return this;

};

Walls.prototype.setShading = function ( selectedRuns, selectedMaterial ) {

	const geometry = this.geometry;
	const indexRuns = this.indexRuns;

	geometry.clearGroups();

	this.visible = true && this.ready;

	if ( selectedRuns.size && indexRuns ) {

		this.material = [ selectedMaterial, unselectedMaterial ];

		let indexRun = indexRuns[ 0 ];

		let start = indexRun.start;
		let count = indexRun.count;

		let currentMaterial;
		let lastMaterial = selectedRuns.has( indexRun.survey ) ? 0 : 1;

		// merge adjacent runs with shared material.

		for ( var run = 1, l = indexRuns.length; run < l; run++ ) {

			indexRun = indexRuns[ run ];

			currentMaterial = selectedRuns.has( indexRun.survey ) ? 0 : 1;

			if ( currentMaterial === lastMaterial && indexRun.start === start + count ) {

				count += indexRun.count;

			} else {

				geometry.addGroup( start, count, lastMaterial );

				start = indexRun.start;
				count = indexRun.count;

				lastMaterial = currentMaterial;

			}

		}

		geometry.addGroup( start, count, lastMaterial );

	} else {

		this.material = selectedMaterial;

	}

};

Walls.prototype.cutRuns = function ( selectedRuns ) {

	const geometry = this.geometry;

	const vertices = geometry.getAttribute( 'position' );
	const indices = geometry.index;

	const indexRuns = this.indexRuns;

	const newIndices = [];
	const newVertices = [];

	const newIndexRuns = [];

	// map old vertex index values to new index values
	const vMap = new Map();

	const l = indexRuns.length;
	var run;

	for ( run = 0; run < l; run++ ) {

		const indexRun = indexRuns[ run ];

		let i, newVertexIndex = 0, fp = 0;

		if ( selectedRuns.has( indexRun.survey ) ) {

			const start = indexRun.start;
			const count = indexRun.count;

			const end = start + count;

			const itemSize = vertices.itemSize;
			const oldVertices = vertices.array;

			for ( i = start; i < end; i++ ) {

				const index = indices.getX( i );

				let newIndex = vMap.get( index );

				if ( newIndex === undefined ) {

					const offset = index * itemSize;

					newIndex = newVertexIndex++;

					vMap.set( index, newIndex );

					newVertices.push( oldVertices[ offset ], oldVertices[ offset + 1 ], oldVertices[ offset + 2 ] );

				}

				newIndices.push( newIndex );

			}

			indexRun.start = fp;

			fp += count;

			newIndexRuns.push( indexRun );

		}

	}

	if ( newIndices.length === 0 ) return false;

	// replace position and index attributes - dispose of old attributes
	geometry.index.setArray( new indices.array.constructor( newIndices ) );
	geometry.index.needsUpdate = true;

	vertices.setArray( new Float32Array( newVertices ) );
	vertices.needsUpdate = true;

	geometry.computeVertexNormals();
	geometry.computeBoundingBox();

	this.indexRuns = newIndexRuns;

	return true;

};

export { Walls };
<|endoftext|>


<commit_before>import request from 'request';
import _ from 'lodash';

let emotes;
const cache = {};
let loaded = false;

/**
 * getEmotes() makes an API request to twitchemotes.com
 * and gets the latest Twitch.tv emote data
 * @return {Promise} returns emote data as a JSON after the API call
 */
function getEmotes() {
  return new Promise((resolve, reject) => {
    loaded = false;
    request('https://twitchemotes.com/api_cache/v2/images.json', (error, response, body) => {
      if (!error && response.statusCode === 200) {
        emotes = JSON.parse(body).images;
        loaded = true;
        resolve(JSON.parse(body).images);
      }

      reject(error);
    });
  });
}

getEmotes().then(() => {
  // update emote list every 30 minutes
  setInterval(() => {
    getEmotes();
  }, 1800000);
});

/**
 * queryEmoteList() checks the user's input against the list of emote codes for a match
 * @param {Object} emoteList - object containing emote metadata
 * @param {String} emoteCode - the emote code inputted by the user
 * @return {Number} returns image_id that corresponds to a matching emote code
 */
function queryEmoteList(emoteList, emoteCode) {
  return new Promise((resolve, reject) => {
    /**
     * key === image_id && value === emoteCode
     * finds the key-value pair that matches the emoteCode provided
     */
    const emoteDetails = _.findKey(emoteList, o => (
      o.code === emoteCode
    ));

    if (emoteDetails !== undefined) {
      resolve(emoteDetails);
    } else {
      reject(emoteDetails);
    }
  });
}

/**
 * emoteChecker() queries the cache and the emote list for emote code matches
 * @param {String} emoteCode - the emote code inputted by the user
 * @return {Number} returns image_id that corresponds to a matching emote code
 */
function emoteChecker(emoteCode) {
  if (_.isEmpty(cache)) {
    // query emote list because cache is empty
    return queryEmoteList(emotes, emoteCode);
  }

  if (Promise.reject(queryEmoteList(cache, emoteCode)) === undefined) {
    // check if cache contains emote already
    return queryEmoteList(emotes, emoteCode);
  }

  // query emote list if emote not already in cache
  return queryEmoteList(emotes, emoteCode);
}

/**
 * returnImage() returns the image URL for matching emote codes
 * @param {Number} imageID - image ID of the matching emote
 * @return {String} URL to the emote image
 */
function returnImage(imageID) {
  return `https://static-cdn.jtvnw.net/emoticons/v1/${imageID}/1.0`;
}

/**
 * matchEmotes() returns matching Twitch emotes
 * @param {Array} wordList - array of variables taken each chat message
 * @return {Object} object containing emote metadata and image URLs
 */
export function matchEmotes(wordList) {
  if (!loaded) {
    return false;
  }

  return new Promise((resolve) => {
    const images = [];

    wordList.forEach((emoteCode) => {
      emoteChecker(emoteCode).then((response) => {
        const imageID = response;
        cache[imageID] = { code: emoteCode };
        const pair = {};
        pair[emoteCode] = returnImage(response);
        images.push(pair);
      }).then(() => {
        resolve(images);
      });
    }, this);
  });
}
<commit_msg>Refactor<commit_after>import request from 'request';
import _ from 'lodash';

let emotes;
const cache = {};
let loaded = false;

/**
 * getEmotes() makes an API request to twitchemotes.com
 * and gets the latest Twitch.tv emote data
 * @return {Promise} returns emote data as a JSON after the API call
 */
function getEmotes() {
  return new Promise((resolve, reject) => {
    loaded = false;
    request('https://twitchemotes.com/api_cache/v2/images.json', (error, response, body) => {
      if (!error && response.statusCode === 200) {
        emotes = JSON.parse(body).images;
        loaded = true;
        resolve(JSON.parse(body).images);
      }

      reject(error);
    });
  });
}

// update emote list every 30 minutes
getEmotes().then(() => setInterval(() => getEmotes(), 1800000));

/**
 * queryEmoteList() checks the user's input against the list of emote codes for a match
 * @param {Object} emoteList - object containing emote metadata
 * @param {String} emoteCode - the emote code inputted by the user
 * @return {Number} returns image_id that corresponds to a matching emote code
 */
function queryEmoteList(emoteList, emoteCode) {
  return new Promise((resolve, reject) => {
    /**
     * key === image_id && value === emoteCode
     * finds the key-value pair that matches the emoteCode provided
     */
    const emoteDetails = _.findKey(emoteList, o => o.code === emoteCode);

    if (emoteDetails !== undefined) {
      resolve(emoteDetails);
    } else {
      reject(emoteDetails);
    }
  });
}

/**
 * emoteChecker() queries the cache and the emote list for emote code matches
 * @param {String} emoteCode - the emote code inputted by the user
 * @return {Number} returns image_id that corresponds to a matching emote code
 */
function emoteChecker(emoteCode) {
  // query emote list because cache is empty
  if (_.isEmpty(cache)) return queryEmoteList(emotes, emoteCode);

  if (Promise.reject(queryEmoteList(cache, emoteCode)) === undefined) {
    // check if cache contains emote already
    return queryEmoteList(emotes, emoteCode);
  }

  // query emote list if emote not already in cache
  return queryEmoteList(emotes, emoteCode);
}

/**
 * returnImage() returns the image URL for matching emote codes
 * @param {Number} imageID - image ID of the matching emote
 * @return {String} URL to the emote image
 */
function returnImage(imageID) {
  return `https://static-cdn.jtvnw.net/emoticons/v1/${imageID}/1.0`;
}

/**
 * matchEmotes() returns matching Twitch emotes
 * @param {Array} wordList - array of variables taken each chat message
 * @return {Object} object containing emote metadata and image URLs
 */
export function matchEmotes(wordList) {
  if (!loaded) return false;

  return new Promise(resolve => {
    const images = [];

    wordList.forEach(emoteCode => {
      emoteChecker(emoteCode).then(response => {
        const imageID = response;
        cache[imageID] = { code: emoteCode };
        const pair = {};
        pair[emoteCode] = returnImage(response);
        images.push(pair);
      }).then(() => {
        resolve(images);
      });
    }, this);
  });
}
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const BoshDirectorClient = require('../../data-access-layer/bosh/BoshDirectorClient');

class Plan {
  constructor(service, options) {
    _
      .chain(this)
      .assign({
        service: service
      })
      .defaults(options, {
        metadata: undefined,
        free: true,
        credentials: {},
        syslog_drain_port: null,
        syslog_drain_protocol: 'syslog'
      })
      .value();
  }

  get stemcell() {
    return _
      .chain(this.manager.settings)
      .get('stemcell', {})
      .defaults(BoshDirectorClient.getInfrastructure().stemcell)
      .update('version', version => '' + version)
      .value();
  }

  get releases() {
    return _
      .chain(this.manager.settings)
      .get('releases')
      .map(release => _.pick(release, 'name', 'version'))
      .sortBy(release => `${release.name}/${release.version}`)
      .value();
  }

  get supportedFeatures() {
    return _.get(this.manager.settings, 'agent.supported_features');
  }

  get updatePredecessors() {
    return _.get(this.manager.settings, 'update_predecessors');
  }

  toJSON() {
    return _
      .chain(this)
      .pick(this.constructor.keys)
      .tap(plan => _.assign(plan.metadata, {
        update_predecessors: this.updatePredecessors,
        supported_features: this.supportedFeatures
      }))
      .value();
  }

  static get keys() {
    return [
      'id',
      'name',
      'description',
      'metadata',
      'free'
    ];
  }
}

module.exports = Plan;<commit_msg>Enable schemas in the service plan<commit_after>'use strict';

const _ = require('lodash');
const BoshDirectorClient = require('../../data-access-layer/bosh/BoshDirectorClient');

class Plan {
  constructor(service, options) {
    _
      .chain(this)
      .assign({
        service: service
      })
      .defaults(options, {
        metadata: undefined,
        free: true,
        credentials: {},
        syslog_drain_port: null,
        syslog_drain_protocol: 'syslog'
      })
      .value();
  }

  get stemcell() {
    return _
      .chain(this.manager.settings)
      .get('stemcell', {})
      .defaults(BoshDirectorClient.getInfrastructure().stemcell)
      .update('version', version => '' + version)
      .value();
  }

  get releases() {
    return _
      .chain(this.manager.settings)
      .get('releases')
      .map(release => _.pick(release, 'name', 'version'))
      .sortBy(release => `${release.name}/${release.version}`)
      .value();
  }

  get supportedFeatures() {
    return _.get(this.manager.settings, 'agent.supported_features');
  }

  get updatePredecessors() {
    return _.get(this.manager.settings, 'update_predecessors');
  }

  toJSON() {
    return _
      .chain(this)
      .pick(this.constructor.keys)
      .tap(plan => _.assign(plan.metadata, {
        update_predecessors: this.updatePredecessors,
        supported_features: this.supportedFeatures
      }))
      .value();
  }

  static get keys() {
    return [
      'id',
      'name',
      'description',
      'metadata',
      'schemas',
      'free'
    ];
  }
}

module.exports = Plan;<|endoftext|>


<commit_before>/* Copyright (c) 2011, 2012 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

/**
 * Class for reading and writing Well-Known Text.
 *
 * NOTE: Adapted from OpenLayers 2.11 implementation.
 */

(function() {
    /**
     * Create a new parser for GeoJSON
     *
     * @param {GeometryFactory}
     *          geometryFactory
     * @return An instance of GeoJsonParser.
     */
    jsts.io.GeoJSONParser = function(geometryFactory) {
        this.geometryFactory = geometryFactory || new jsts.geom.GeometryFactory();
        this.geometryTypes = [ 'point', 'multipoint', 'linestring', 'multilinestring', 'polygon', 'multipolygon' ];
    };

    /**
     * Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries
     *
     * @param {}
     *          A GeoJSON object
     * @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances
     */
    jsts.io.GeoJSONParser.prototype.read = function(json) {
        var obj;
        if (typeof json === 'string') {
            obj = JSON.parse(json);
        } else {
            obj = json;
        }

        var type = obj.type.toLowerCase();

        if (!this.parse[type]) {
            throw new Error('Unknown GeoJSON type: ' + obj.type);
        }

        if (this.geometryTypes.indexOf(type) != -1) {
            return this.parse[type].apply(this, [ obj.coordinates ]);
        } else if (type === 'geometrycollection') {
            return this.parse[type].apply(this, [ obj.geometries ]);
        }

        // feature or feature collection
        return this.parse[type].apply(this, [ obj ]);
    };

    jsts.io.GeoJSONParser.prototype.parse = {
        /**
         * Parse a GeoJSON Feature object
         *
         * @param {Object}
         *          obj Object to parse
         *
         * @return {Object} Feature with geometry/bbox converted to JSTS Geometries
         */
        'feature': function(obj) {
            var feature = {};

            // copy features
            for (var key in obj) {
                feature[key] = obj[key];
            }

            // parse geometry
            if (obj.geometry) {
                var type = obj.geometry.type.toLowerCase();
                if (!this.parse[type]) {
                    throw new Error('Unknown GeoJSON type: ' + obj.type);
                }
                feature.geometry = this.read(obj.geometry);
            }

            // bbox
            if (obj.bbox) {
                feature.bbox = this.parse.bbox.apply(this, [ obj.bbox ]);
            }

            return feature;
        },

        /**
         * Parse a GeoJSON FeatureCollection object
         *
         * @param {Object}
         *          obj Object to parse
         *
         * @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries
         */
        'featurecollection': function(obj) {
            var featureCollection = {};

            if (obj.features) {
                featureCollection.features = [];

                for (var i = 0; i < obj.features.length; ++i) {
                    featureCollection.features.push(this.read(obj.features[i]));
                }
            }

            if (obj.bbox) {
                featureCollection.bbox = this.parse.bbox.apply(this, [ obj.bbox ]);
            }

            return featureCollection;
        },

        /**
         * Convert the ordinates in an array to an array of jsts.geom.Coordinates
         *
         * @param {Array}
         *          array Array with {Number}s
         *
         * @return {Array} Array with jsts.geom.Coordinates
         */
        'coordinates': function(array) {
            var coordinates = [];

            for (var i = 0; i < array.length; ++i) {
                var sub = array[i];
                coordinates.push(new jsts.geom.Coordinate(sub[0], sub[1]));
            }

            return coordinates;
        },

        /**
         * Convert the bbox to a jsts.geom.LinearRing
         *
         * @param {Array}
         *          array Array with [xMin, yMin, xMax, yMax]
         *
         * @return {Array} Array with jsts.geom.Coordinates
         */
        'bbox': function(array) {
            return this.geometryFactory.createLinearRing([
                new jsts.geom.Coordinate(array[0], array[1]),
                new jsts.geom.Coordinate(array[2], array[1]),
                new jsts.geom.Coordinate(array[2], array[3]),
                new jsts.geom.Coordinate(array[0], array[3]),
                new jsts.geom.Coordinate(array[0], array[1]),
            ]);
        },

        /**
         * Convert an Array with ordinates to a jsts.geom.Point
         *
         * @param {Array}
         *          array Array with ordinates
         *
         * @return {jsts.geom.Point} Point
         */
        'point': function(array) {
            var coordinate = new jsts.geom.Coordinate(array[0], array[1]);
            return this.geometryFactory.createPoint(coordinate);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.MultiPoint
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.MultiPoint} MultiPoint
         */
        'multipoint': function(array) {
            var points = [];

            for (var i = 0; i < array.length; ++i) {
                points.push(this.parse.point.apply(this, [ array[i] ]));
            }

            return this.geometryFactory.createMultiPoint(points);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.LineString
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.LineString} LineString
         */
        'linestring': function(array) {
            var coordinates = this.parse.coordinates.apply(this, [ array ]);
            return this.geometryFactory.createLineString(coordinates);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.MultiLineString
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.MultiLineString} MultiLineString
         */
        'multilinestring': function(array) {
            var lineStrings = [];

            for (var i = 0; i < array.length; ++i) {
                lineStrings.push(this.parse.linestring.apply(this, [ array[i] ]));
            }

            return this.geometryFactory.createMultiLineString(lineStrings);
        },

        /**
         * Convert an Array to a jsts.geom.Polygon
         *
         * @param {Array}
         *          array Array with shell and holes
         *
         * @return {jsts.geom.Polygon} Polygon
         */
        'polygon': function(array) {
            // shell
            var shellCoordinates = this.parse.coordinates.apply(this, [ array[0] ]);
            var shell = this.geometryFactory.createLinearRing(shellCoordinates);

            // holes
            var holes = [];
            for (var i = 1; i < array.length; ++i) {
                var hole = array[i];
                var coordinates = this.parse.coordinates.apply(this, [ hole ]);
                var linearRing = this.geometryFactory.createLinearRing(coordinates);
                holes.push(linearRing);
            }

            return this.geometryFactory.createPolygon(shell, holes);
        },

        /**
         * Convert an Array to a jsts.geom.MultiPolygon
         *
         * @param {Array}
         *          array Array of arrays with shell and rings
         *
         * @return {jsts.geom.MultiPolygon} MultiPolygon
         */
        'multipolygon': function(array) {
            var polygons = [];

            for (var i = 0; i < array.length; ++i) {
                var polygon = array[i];
                polygons.push(this.parse.polygon.apply(this, [ polygon ]));
            }

            return this.geometryFactory.createMultiPolygon(polygons);
        },

        /**
         * Convert an Array to a jsts.geom.GeometryCollection
         *
         * @param {Array}
         *          array Array of GeoJSON geometries
         *
         * @return {jsts.geom.GeometryCollection} GeometryCollection
         */
        'geometrycollection': function(array) {
            var geometries = [];

            for (var i = 0; i < array.length; ++i) {
                var geometry = array[i];
                geometries.push(this.read(geometry));
            }

            return this.geometryFactory.createGeometryCollection(geometries);
        }
    };

    /**
     * Serialize a Geometry object into GeoJSON
     *
     * @param {jsts.geom.geometry}
     *          geometry A Geometry or array of Geometries
     * @return {Object} A GeoJSON object represting the input Geometry/Geometries
     */
    jsts.io.GeoJSONParser.prototype.write = function(geometry) {
        var geoJson = {
            'type': null
        };

        if (geometry instanceof Array) {
            // XXX: TODO
        } else if (geometry.CLASS_NAME.indexOf('jsts.geom') == 0) {
            geoJson = this.extract.geometry.apply(this, [ geometry]);
        }

        return geoJson;
    };

    jsts.io.GeoJSONParser.prototype.extract = {
        /**
         * Convert a Geometry to a GeoJSON object
         *
         * @param {jsts.geom.Geometry}
         *          geometry Geometry to convert
         *
         * @return {Object} GeoJSON object
         */
        'geometry': function(geometry) {
            var type = geometry.CLASS_NAME.split('.')[2];
            if (!this.extract[type.toLowerCase()]) {
                return null;
            }

            return {
                'type': type,
                'geometry': this.extract[type.toLowerCase()].apply(this, [ geometry ])
            };
        },

        /**
         * Convert a jsts.geom.Coordinate to an Array
         *
         * @param {jsts.geom.Coordinate}
         *          coordinate Coordinate to convert
         *
         * @return {Array} Array of ordinates
         */
        'coordinate': function(coordinate) {
            return [ coordinate.x, coordinate.y ];
        },

        /**
         * Convert a jsts.geom.Point to a GeoJSON object
         *
         * @param {jsts.geom.Point}
         *          point Point to convert
         *
         * @return {Array} Array of 2 ordinates (paired to a coordinate)
         */
        'point': function(point) {
            var coordinate = point.coordinate;
            return this.extract.coordinate.apply(this, [ coordinate ]);
        },

        /**
         * Convert a jsts.geom.MultiPoint to a GeoJSON object
         *
         * @param {jsts.geom.MultiPoint}
         *          multipoint MultiPoint to convert
         *
         * @return {Array} Array of coordinates
         */
        'multipoint': function(multipoint) {
            var array = [];

            for (var i = 0; i < multipoint.geometries.length; ++i) {
                var point = multipoint.geometries[i];
                array.push(this.extract.point.apply(this, [ point ]));
            }

            return array;
        },

        /**
         * Convert a jsts.geom.LineString to a GeoJSON object
         *
         * @param {jsts.geom.LineString}
         *          linestring LineString to convert
         *
         * @return {Array} Array of coordinates
         */
        'linestring': function(linestring) {
            var array = [];

            for (var i = 0; i < linestring.points.length; ++i) {
                var coordinate = linestring.points[i];
                array.push(this.extract.coordinate.apply(this, [ coordinate ]));
            }

            return array;
        },

        /**
         * Convert a jsts.geom.MultiLineString to a GeoJSON object
         *
         * @param {jsts.geom.MultiLineString}
         *          multilinestring MultiLineString to convert
         *
         * @return {Array} Array of Array of coordinates
         */
        'multilinestring': function(multilinestring) {
            var array = [];

            for (var i = 0; i < multilinestring.geometries.length; ++i) {
                var linestring = multilinestring.geometries[i];
                array.push(this.extract.linestring.apply(this, [ linestring ]));
            }

            return array;
        },

        /**
         * Convert a jsts.geom.Polygon to a GeoJSON object
         *
         * @param {jsts.geom.Polygon}
         *          polygon Polygon to convert
         *
         * @return {Array} Array with shell, holes
         */
        'polygon': function(polygon) {
            var array = [];

            array.push(this.extract.linestring.apply(this, [ polygon.shell ]));
            for (var i = 0; i < polygon.holes.length; ++i) {
                var hole = polygon.holes[i];
                array.push(this.extract.linestring.apply(this, [ hole ]));
            }

            return array;
        },

        /**
         * Convert a jsts.geom.MultiPolygon to a GeoJSON object
         *
         * @param {jsts.geom.MultiPolygon}
         *          multipolygon MultiPolygon to convert
         *
         * @return {Array} Array of polygons
         */
        'multipolygon': function(multipolygon) {
            var array = [];

            for (var i = 0; i < multipolygon.geometries.length; ++i) {
                var polygon = multipolygon.geometries[i];
                array.push(this.extract.polygon.apply(this, [ polygon ]));
            }

            return array;
        },

        /**
         * Convert a jsts.geom.GeometryCollection to a GeoJSON object
         *
         * @param {jsts.geom.GeometryCollection}
         *          collection GeometryCollection to convert
         *
         * @return {Array} Array of geometries
         */
        'geometrycollection': function(collection) {
            var array = [];

            for (var i = 0; i < collection.geometries.length; ++i) {
                var geometry = collection.geometries[i];
                array.push(this.extract.geometry.apply(this, [ geometry ]));
            }

            return array;
        }
    };
})();
<commit_msg>Fixed GeoJSONParser<commit_after>/* Copyright (c) 2011, 2012 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

/**
 * Class for reading and writing Well-Known Text.
 *
 * NOTE: Adapted from OpenLayers 2.11 implementation.
 */

(function() {
    /**
     * Create a new parser for GeoJSON
     *
     * @param {GeometryFactory}
     *          geometryFactory
     * @return An instance of GeoJsonParser.
     */
    jsts.io.GeoJSONParser = function(geometryFactory) {
        this.geometryFactory = geometryFactory || new jsts.geom.GeometryFactory();
        this.geometryTypes = [ 'Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon' ];
    };

    /**
     * Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries
     *
     * @param {}
     *          A GeoJSON object
     * @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances
     */
    jsts.io.GeoJSONParser.prototype.read = function(json) {
        var obj;
        if (typeof json === 'string') {
            obj = JSON.parse(json);
        } else {
            obj = json;
        }

        var type = obj.type;

        if (!this.parse[type]) {
            throw new Error('Unknown GeoJSON type: ' + obj.type);
        }

        if (this.geometryTypes.indexOf(type) != -1) {
            return this.parse[type].apply(this, [ obj.coordinates ]);
        } else if (type === 'GeometryCollection') {
            return this.parse[type].apply(this, [ obj.geometries ]);
        }

        // feature or feature collection
        return this.parse[type].apply(this, [ obj ]);
    };

    jsts.io.GeoJSONParser.prototype.parse = {
        /**
         * Parse a GeoJSON Feature object
         *
         * @param {Object}
         *          obj Object to parse
         *
         * @return {Object} Feature with geometry/bbox converted to JSTS Geometries
         */
        'Feature': function(obj) {
            var feature = {};

            // copy features
            for (var key in obj) {
                feature[key] = obj[key];
            }

            // parse geometry
            if (obj.geometry) {
                var type = obj.geometry.type;
                if (!this.parse[type]) {
                    throw new Error('Unknown GeoJSON type: ' + obj.type);
                }
                feature.geometry = this.read(obj.geometry);
            }

            // bbox
            if (obj.bbox) {
                feature.bbox = this.parse.bbox.apply(this, [ obj.bbox ]);
            }

            return feature;
        },

        /**
         * Parse a GeoJSON FeatureCollection object
         *
         * @param {Object}
         *          obj Object to parse
         *
         * @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries
         */
        'FeatureCollection': function(obj) {
            var featureCollection = {};

            if (obj.features) {
                featureCollection.features = [];

                for (var i = 0; i < obj.features.length; ++i) {
                    featureCollection.features.push(this.read(obj.features[i]));
                }
            }

            if (obj.bbox) {
                featureCollection.bbox = this.parse.bbox.apply(this, [ obj.bbox ]);
            }

            return featureCollection;
        },

        /**
         * Convert the ordinates in an array to an array of jsts.geom.Coordinates
         *
         * @param {Array}
         *          array Array with {Number}s
         *
         * @return {Array} Array with jsts.geom.Coordinates
         */
        'coordinates': function(array) {
            var coordinates = [];

            for (var i = 0; i < array.length; ++i) {
                var sub = array[i];
                coordinates.push(new jsts.geom.Coordinate(sub[0], sub[1]));
            }

            return coordinates;
        },

        /**
         * Convert the bbox to a jsts.geom.LinearRing
         *
         * @param {Array}
         *          array Array with [xMin, yMin, xMax, yMax]
         *
         * @return {Array} Array with jsts.geom.Coordinates
         */
        'bbox': function(array) {
            return this.geometryFactory.createLinearRing([
                new jsts.geom.Coordinate(array[0], array[1]),
                new jsts.geom.Coordinate(array[2], array[1]),
                new jsts.geom.Coordinate(array[2], array[3]),
                new jsts.geom.Coordinate(array[0], array[3]),
                new jsts.geom.Coordinate(array[0], array[1]),
            ]);
        },

        /**
         * Convert an Array with ordinates to a jsts.geom.Point
         *
         * @param {Array}
         *          array Array with ordinates
         *
         * @return {jsts.geom.Point} Point
         */
        'Point': function(array) {
            var coordinate = new jsts.geom.Coordinate(array[0], array[1]);
            return this.geometryFactory.createPoint(coordinate);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.MultiPoint
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.MultiPoint} MultiPoint
         */
        'MultiPoint': function(array) {
            var points = [];

            for (var i = 0; i < array.length; ++i) {
                points.push(this.parse.Point.apply(this, [ array[i] ]));
            }

            return this.geometryFactory.createMultiPoint(points);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.LineString
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.LineString} LineString
         */
        'LineString': function(array) {
            var coordinates = this.parse.coordinates.apply(this, [ array ]);
            return this.geometryFactory.createLineString(coordinates);
        },

        /**
         * Convert an Array with coordinates to a jsts.geom.MultiLineString
         *
         * @param {Array}
         *          array Array with coordinates
         *
         * @return {jsts.geom.MultiLineString} MultiLineString
         */
        'MultiLineString': function(array) {
            var lineStrings = [];

            for (var i = 0; i < array.length; ++i) {
                lineStrings.push(this.parse.LineString.apply(this, [ array[i] ]));
            }

            return this.geometryFactory.createMultiLineString(lineStrings);
        },

        /**
         * Convert an Array to a jsts.geom.Polygon
         *
         * @param {Array}
         *          array Array with shell and holes
         *
         * @return {jsts.geom.Polygon} Polygon
         */
        'Polygon': function(array) {
            // shell
            var shellCoordinates = this.parse.coordinates.apply(this, [ array[0] ]);
            var shell = this.geometryFactory.createLinearRing(shellCoordinates);

            // holes
            var holes = [];
            for (var i = 1; i < array.length; ++i) {
                var hole = array[i];
                var coordinates = this.parse.coordinates.apply(this, [ hole ]);
                var linearRing = this.geometryFactory.createLinearRing(coordinates);
                holes.push(linearRing);
            }

            return this.geometryFactory.createPolygon(shell, holes);
        },

        /**
         * Convert an Array to a jsts.geom.MultiPolygon
         *
         * @param {Array}
         *          array Array of arrays with shell and rings
         *
         * @return {jsts.geom.MultiPolygon} MultiPolygon
         */
        'MultiPolygon': function(array) {
            var polygons = [];

            for (var i = 0; i < array.length; ++i) {
                var polygon = array[i];
                polygons.push(this.parse.Polygon.apply(this, [ polygon ]));
            }

            return this.geometryFactory.createMultiPolygon(polygons);
        },

        /**
         * Convert an Array to a jsts.geom.GeometryCollection
         *
         * @param {Array}
         *          array Array of GeoJSON geometries
         *
         * @return {jsts.geom.GeometryCollection} GeometryCollection
         */
        'GeometryCollection': function(array) {
            var geometries = [];

            for (var i = 0; i < array.length; ++i) {
                var geometry = array[i];
                geometries.push(this.read(geometry));
            }

            return this.geometryFactory.createGeometryCollection(geometries);
        }
    };

    /**
     * Serialize a Geometry object into GeoJSON
     *
     * @param {jsts.geom.geometry}
     *          geometry A Geometry or array of Geometries
     * @return {Object} A GeoJSON object represting the input Geometry/Geometries
     */
    jsts.io.GeoJSONParser.prototype.write = function(geometry) {
        var type = geometry.CLASS_NAME.slice(10);

        if (!this.extract[type]) {
            throw new Error('Geometry is not supported');
        }

        return this.extract[type].apply(this, [ geometry ]);
    };

    jsts.io.GeoJSONParser.prototype.extract = {
        /**
         * Convert a jsts.geom.Coordinate to an Array
         *
         * @param {jsts.geom.Coordinate}
         *          coordinate Coordinate to convert
         *
         * @return {Array} Array of ordinates
         */
        'coordinate': function(coordinate) {
            return [ coordinate.x, coordinate.y ];
        },

        /**
         * Convert a jsts.geom.Point to a GeoJSON object
         *
         * @param {jsts.geom.Point}
         *          point Point to convert
         *
         * @return {Array} Array of 2 ordinates (paired to a coordinate)
         */
        'Point': function(point) {
            var array = this.extract.coordinate.apply(this, [ point.coordinate ])

            return {
                type: 'Point',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.MultiPoint to a GeoJSON object
         *
         * @param {jsts.geom.MultiPoint}
         *          multipoint MultiPoint to convert
         *
         * @return {Array} Array of coordinates
         */
        'MultiPoint': function(multipoint) {
            var array = [];

            for (var i = 0; i < multipoint.geometries.length; ++i) {
                var point = multipoint.geometries[i];
                var geoJson = this.extract.Point.apply(this, [ point ]);
                array.push(geoJson.coordinates);
            }

            return {
                type: 'MultiPoint',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.LineString to a GeoJSON object
         *
         * @param {jsts.geom.LineString}
         *          linestring LineString to convert
         *
         * @return {Array} Array of coordinates
         */
        'LineString': function(linestring) {
            var array = [];

            for (var i = 0; i < linestring.points.length; ++i) {
                var coordinate = linestring.points[i];
                array.push(this.extract.coordinate.apply(this, [ coordinate ]));
            }

            return {
                type: 'LineString',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.MultiLineString to a GeoJSON object
         *
         * @param {jsts.geom.MultiLineString}
         *          multilinestring MultiLineString to convert
         *
         * @return {Array} Array of Array of coordinates
         */
        'MultiLineString': function(multilinestring) {
            var array = [];

            for (var i = 0; i < multilinestring.geometries.length; ++i) {
                var linestring = multilinestring.geometries[i];
                var geoJson = this.extract.LineString.apply(this, [ linestring ]);
                array.push(geoJson.coordinates);
            }

            return {
                type: 'MultiLineString',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.Polygon to a GeoJSON object
         *
         * @param {jsts.geom.Polygon}
         *          polygon Polygon to convert
         *
         * @return {Array} Array with shell, holes
         */
        'Polygon': function(polygon) {
            var array = [];

            // shell
            var shellGeoJson = this.extract.LineString.apply(this, [ polygon.shell ]);
            array.push(shellGeoJson.coordinates);

            // holes
            for (var i = 0; i < polygon.holes.length; ++i) {
                var hole = polygon.holes[i];
                var holeGeoJson = this.extract.LineString.apply(this, [ hole ]);
                array.push(holeGeoJson.coordinates);
            }

            return {
                type: 'Polygon',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.MultiPolygon to a GeoJSON object
         *
         * @param {jsts.geom.MultiPolygon}
         *          multipolygon MultiPolygon to convert
         *
         * @return {Array} Array of polygons
         */
        'MultiPolygon': function(multipolygon) {
            var array = [];

            for (var i = 0; i < multipolygon.geometries.length; ++i) {
                var polygon = multipolygon.geometries[i];
                var geoJson = this.extract.Polygon.apply(this, [ polygon ]);
                array.push(geoJson.coordinates);
            }

            return {
                type: 'MultiPolygon',
                coordinates: array
            };
        },

        /**
         * Convert a jsts.geom.GeometryCollection to a GeoJSON object
         *
         * @param {jsts.geom.GeometryCollection}
         *          collection GeometryCollection to convert
         *
         * @return {Array} Array of geometries
         */
        'GeometryCollection': function(collection) {
            var array = [];

            for (var i = 0; i < collection.geometries.length; ++i) {
                var geometry = collection.geometries[i];
                var type = geometry.CLASS_NAME.slice(10);
                array.push(this.extract[type].apply(this, [ geometry ]));
            }

            return {
                type: 'GeometryCollection',
                geometries: array
            };
        }
    };
})();
<|endoftext|>