<commit_before>/** @preserve
jsPDF addImage plugin (JPEG only at this time)
Copyright (c) 2012 https://github.com/siefkenj/
*/

/**
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

;(function(jsPDFAPI) {
'use strict'

var namespace = 'addImage_'

// takes a string imgData containing the raw bytes of
// a jpeg image and returns [width, height]
// Algorithm from: http://www.64lines.com/jpeg-width-height
var getJpegSize = function(imgData) {
	'use strict'
	var width, height;
	// Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
	if (!imgData.charCodeAt(0) === 0xff ||
		!imgData.charCodeAt(1) === 0xd8 ||
		!imgData.charCodeAt(2) === 0xff ||
		!imgData.charCodeAt(3) === 0xe0 ||
		!imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
		!imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
		!imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
		!imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
		!imgData.charCodeAt(10) === 0x00) {
			throw new Error('getJpegSize requires a binary jpeg file')
	}
	var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
	var i = 4, len = imgData.length;
	while ( i < len ) {
		i += blockLength;
		if (imgData.charCodeAt(i) !== 0xff) {
			throw new Error('getJpegSize could not find the size of the image');
		}
		if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman  - Baseline DCT
		    imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman  - Extended sequential DCT
		    imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2)
		    imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
		    imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5)
		    imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6)
		    imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7)
		    imgData.charCodeAt(i+1) === 0xc7) {
			height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
			width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
			return [width, height];
		} else {
			i += 2;
			blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
		}
	}
}
// Image functionality ported from pdf.js
, putImage = function(img) {
	var objectNumber = this.internal.newObject()
	, out = this.internal.write
	, putStream = this.internal.putStream

	img['n'] = objectNumber

	out('<</Type /XObject')
	out('/Subtype /Image')
	out('/Width ' + img['w'])
	out('/Height ' + img['h'])
	if (img['cs'] === 'Indexed') {
		out('/ColorSpace [/Indexed /DeviceRGB '
				+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
				+ ' 0 R]');
	} else {
		out('/ColorSpace /' + img['cs']);
		if (img['cs'] === 'DeviceCMYK') {
			out('/Decode [1 0 1 0 1 0 1 0]');
		}
	}
	out('/BitsPerComponent ' + img['bpc']);
	if ('f' in img) {
		out('/Filter /' + img['f']);
	}
	if ('dp' in img) {
		out('/DecodeParms <<' + img['dp'] + '>>');
	}
	if ('trns' in img && img['trns'].constructor == Array) {
		var trns = '';
		for ( var i = 0; i < img['trns'].length; i++) {
			trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
			out('/Mask [' + trns + ']');
		}
	}
	if ('smask' in img) {
		out('/SMask ' + (objectNumber + 1) + ' 0 R');
	}
	out('/Length ' + img['data'].length + '>>');

	putStream(img['data']);

	out('endobj');
}
, putResourcesCallback = function() {
	var images = this.internal.collections[namespace + 'images']
	for ( var i in images ) {
		putImage.call(this, images[i])
	}
}
, putXObjectsDictCallback = function(){
	var images = this.internal.collections[namespace + 'images']
	, out = this.internal.write
	, image
	for (var i in images) {
		image = images[i]
		out(
			'/I' + image['i']
			, image['n']
			, '0'
			, 'R'
		)
	}
}

jsPDFAPI.addImage = function(imageData, format, x, y, w, h) {
	'use strict'
	if(typeof imageData === 'string' && imageData.substr(0,14) === 'data:image/jpg') {
		imageData = imageData.replace('data:image/jpg','data:image/jpeg');
	}
	if (typeof imageData === 'object' && imageData.nodeType === 1) {
        var canvas = document.createElement('canvas');
        canvas.width = imageData.clientWidth || imageData.width;
	    canvas.height = imageData.clientHeight || imageData.height;

        var ctx = canvas.getContext('2d');
        if (!ctx) {
            throw ('addImage requires canvas to be supported by browser.');
        }
        ctx.drawImage(imageData, 0, 0, canvas.width, canvas.height);
        imageData = canvas.toDataURL('image/jpeg');
	    format = "JPEG";
	}
	if (format.toUpperCase() !== 'JPEG') {
		throw new Error('addImage currently only supports format \'JPEG\', not \''+format+'\'');
	}

	var imageIndex
	, images = this.internal.collections[namespace + 'images']
	, coord = this.internal.getCoordinateString
	, vcoord = this.internal.getVerticalCoordinateString;

	// Detect if the imageData is raw binary or Data URL
	if (imageData.substring(0, 23) === 'data:image/jpeg;base64,') {
		imageData = atob(imageData.replace('data:image/jpeg;base64,', ''));
	}

	if (images){
		// this is NOT the first time this method is ran on this instance of jsPDF object.
		imageIndex = Object.keys ?
		Object.keys(images).length :
		(function(o){
			var i = 0
			for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
			return i
		})(images)
	} else {
		// this is the first time this method is ran on this instance of jsPDF object.
		imageIndex = 0
		this.internal.collections[namespace + 'images'] = images = {}
		this.internal.events.subscribe('putResources', putResourcesCallback)
		this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback)
	}

	var dims = getJpegSize(imageData);
	var info = {
		w : dims[0],
		h : dims[1],
		cs : 'DeviceRGB',
		bpc : 8,
		f : 'DCTDecode',
		i : imageIndex,
		data : imageData
		// n: objectNumber will be added by putImage code

	};
	images[imageIndex] = info
	if (!w && !h) {
		w = -96;
		h = -96;
	}
	if (w < 0) {
		w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
	}
	if (h < 0) {
		h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
	}
	if (w === 0) {
		w = h * info['w'] / info['h'];
	}
	if (h === 0) {
		h = w * info['h'] / info['w'];
	}

	this.internal.write(
		'q'
		, coord(w)
		, '0 0'
		, coord(h) // TODO: check if this should be shifted by vcoord
		, coord(x)
		, vcoord(y + h)
		, 'cm /I'+info['i']
		, 'Do Q'
	)

	return this
}
})(jsPDF.API);
<commit_msg>addImage: 'format' does not really needs to be required, just assume it's JPEG<commit_after>/** @preserve
jsPDF addImage plugin (JPEG only at this time)
Copyright (c) 2012 https://github.com/siefkenj/
*/

/**
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

;(function(jsPDFAPI) {
'use strict'

var namespace = 'addImage_'

// takes a string imgData containing the raw bytes of
// a jpeg image and returns [width, height]
// Algorithm from: http://www.64lines.com/jpeg-width-height
var getJpegSize = function(imgData) {
	'use strict'
	var width, height;
	// Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
	if (!imgData.charCodeAt(0) === 0xff ||
		!imgData.charCodeAt(1) === 0xd8 ||
		!imgData.charCodeAt(2) === 0xff ||
		!imgData.charCodeAt(3) === 0xe0 ||
		!imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
		!imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
		!imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
		!imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
		!imgData.charCodeAt(10) === 0x00) {
			throw new Error('getJpegSize requires a binary jpeg file')
	}
	var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
	var i = 4, len = imgData.length;
	while ( i < len ) {
		i += blockLength;
		if (imgData.charCodeAt(i) !== 0xff) {
			throw new Error('getJpegSize could not find the size of the image');
		}
		if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman  - Baseline DCT
		    imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman  - Extended sequential DCT
		    imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2)
		    imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
		    imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5)
		    imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6)
		    imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7)
		    imgData.charCodeAt(i+1) === 0xc7) {
			height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
			width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
			return [width, height];
		} else {
			i += 2;
			blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
		}
	}
}
// Image functionality ported from pdf.js
, putImage = function(img) {
	var objectNumber = this.internal.newObject()
	, out = this.internal.write
	, putStream = this.internal.putStream

	img['n'] = objectNumber

	out('<</Type /XObject')
	out('/Subtype /Image')
	out('/Width ' + img['w'])
	out('/Height ' + img['h'])
	if (img['cs'] === 'Indexed') {
		out('/ColorSpace [/Indexed /DeviceRGB '
				+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
				+ ' 0 R]');
	} else {
		out('/ColorSpace /' + img['cs']);
		if (img['cs'] === 'DeviceCMYK') {
			out('/Decode [1 0 1 0 1 0 1 0]');
		}
	}
	out('/BitsPerComponent ' + img['bpc']);
	if ('f' in img) {
		out('/Filter /' + img['f']);
	}
	if ('dp' in img) {
		out('/DecodeParms <<' + img['dp'] + '>>');
	}
	if ('trns' in img && img['trns'].constructor == Array) {
		var trns = '';
		for ( var i = 0; i < img['trns'].length; i++) {
			trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
			out('/Mask [' + trns + ']');
		}
	}
	if ('smask' in img) {
		out('/SMask ' + (objectNumber + 1) + ' 0 R');
	}
	out('/Length ' + img['data'].length + '>>');

	putStream(img['data']);

	out('endobj');
}
, putResourcesCallback = function() {
	var images = this.internal.collections[namespace + 'images']
	for ( var i in images ) {
		putImage.call(this, images[i])
	}
}
, putXObjectsDictCallback = function(){
	var images = this.internal.collections[namespace + 'images']
	, out = this.internal.write
	, image
	for (var i in images) {
		image = images[i]
		out(
			'/I' + image['i']
			, image['n']
			, '0'
			, 'R'
		)
	}
}

jsPDFAPI.addImage = function(imageData, format, x, y, w, h) {
	'use strict'
	if(typeof format === 'number') {
		var tmp = h;
		h = w;
		w = y;
		y = x;
		x = format;
		format = tmp || 'JPEG';
	}
	if(typeof imageData === 'string' && imageData.substr(0,14) === 'data:image/jpg') {
		imageData = imageData.replace('data:image/jpg','data:image/jpeg');
	}
	if (typeof imageData === 'object' && imageData.nodeType === 1) {
        var canvas = document.createElement('canvas');
        canvas.width = imageData.clientWidth || imageData.width;
	    canvas.height = imageData.clientHeight || imageData.height;

        var ctx = canvas.getContext('2d');
        if (!ctx) {
            throw ('addImage requires canvas to be supported by browser.');
        }
        ctx.drawImage(imageData, 0, 0, canvas.width, canvas.height);
        imageData = canvas.toDataURL('image/jpeg');
	    format = "JPEG";
	}
	if (format.toUpperCase() !== 'JPEG') {
		throw new Error('addImage currently only supports format \'JPEG\', not \''+format+'\'');
	}

	var imageIndex
	, images = this.internal.collections[namespace + 'images']
	, coord = this.internal.getCoordinateString
	, vcoord = this.internal.getVerticalCoordinateString;

	// Detect if the imageData is raw binary or Data URL
	if (imageData.substring(0, 23) === 'data:image/jpeg;base64,') {
		imageData = atob(imageData.replace('data:image/jpeg;base64,', ''));
	}

	if (images){
		// this is NOT the first time this method is ran on this instance of jsPDF object.
		imageIndex = Object.keys ?
		Object.keys(images).length :
		(function(o){
			var i = 0
			for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
			return i
		})(images)
	} else {
		// this is the first time this method is ran on this instance of jsPDF object.
		imageIndex = 0
		this.internal.collections[namespace + 'images'] = images = {}
		this.internal.events.subscribe('putResources', putResourcesCallback)
		this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback)
	}

	var dims = getJpegSize(imageData);
	var info = {
		w : dims[0],
		h : dims[1],
		cs : 'DeviceRGB',
		bpc : 8,
		f : 'DCTDecode',
		i : imageIndex,
		data : imageData
		// n: objectNumber will be added by putImage code

	};
	images[imageIndex] = info
	if (!w && !h) {
		w = -96;
		h = -96;
	}
	if (w < 0) {
		w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
	}
	if (h < 0) {
		h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
	}
	if (w === 0) {
		w = h * info['w'] / info['h'];
	}
	if (h === 0) {
		h = w * info['h'] / info['w'];
	}

	this.internal.write(
		'q'
		, coord(w)
		, '0 0'
		, coord(h) // TODO: check if this should be shifted by vcoord
		, coord(x)
		, vcoord(y + h)
		, 'cm /I'+info['i']
		, 'Do Q'
	)

	return this
}
})(jsPDF.API);
<|endoftext|>


<commit_before>/* eslint-disable no-magic-numbers */

var c = require('./common');

module.exports = {
  collections: {

    config: [{
      key: 'schemaVersion',
      value: 8,  // new
    }],

    entries: [{
      _id: c.id('581f166110a1482dd0b7ea01'),
      data: {
        isVisit: false,
        markdown: 'A ghost town',
        filepath: null,
        mimetype: null,
        thumbfilepath: null,
        thumbmimetype: null,
      },
      deleted: false,
      locationId: c.irbeneId,
      time: '2009-09-04T23:44:21.000Z',
      type: 'location_entry',
      user: 'admin',
    }, {
      _id: c.id('581f166110a1482dd0b7ea02'),
      data: {
        isVisit: false,
        markdown: null,
        filepath: '2009/RxRvKSlbl/radar.jpg',  // the sample contains this
        mimetype: 'image/jpeg',
        thumbfilepath: '2009/RxRvKSlbl/radar_medium.jpg',
        thumbmimetype: 'image/jpeg',
      },
      deleted: false,
      locationId: c.irbeneId,
      time: '2009-10-02T11:11:01.000Z',
      type: 'location_entry',
      user: 'admin',
    }],

    events: [{
      data: {
        lng: 21.857705,
        lat: 57.55341,
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-07-30T10:44:57.000Z',
      type: 'location_created',
      user: 'admin',
    }, {
      data: {
        entryId: c.id('581f166110a1482dd0b7ea01'),
        isVisit: false,
        markdown: 'A ghost town',
        filepath: null,
        mimetype: null,
        thumbfilepath: null,
        thumbmimetype: null,
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-09-04T23:44:21.000Z',
      type: 'location_entry_created',
      user: 'admin',
    }, {
      data: {
        entryId: c.id('581f166110a1482dd0b7ea02'),
        isVisit: false,
        markdown: null,
        filepath: '2009/RxRvKSlbl/radar.jpg',  // the sample contains this
        mimetype: 'image/jpeg',
        thumbfilepath: '2009/RxRvKSlbl/radar_medium.jpg',
        thumbmimetype: 'image/jpeg',
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-10-02T11:11:01.000Z',
      type: 'location_entry_created',
      user: 'admin',
    }],

    users: [{
      admin: true,
      email: 'admin@example.com',
      hash: c.PASSWORD,
      name: 'admin',
      points: 0,
      status: 'active',
    }],

    locations: [{
      _id: c.irbeneId,
      creator: 'admin',
      deleted: false,
      geom: {
        type: 'Point',
        coordinates: [21.857705, 57.55341],
      },
      layer: 12,
      isLayered: true,
      name: 'Irbene',
      points: 0,
      places: [],
      tags: ['walk-in'],
      text1: '',  // new
      text2: '',  // new
    }],
  },
};
<commit_msg>Doc schema step<commit_after>/* eslint-disable no-magic-numbers */
// NOTE This file is an important documentation of the data structure of v8.

var c = require('./common');

module.exports = {
  collections: {

    config: [{
      key: 'schemaVersion',
      value: 8,  // new
    }],

    entries: [{
      _id: c.id('581f166110a1482dd0b7ea01'),
      data: {
        isVisit: false,
        markdown: 'A ghost town',
        filepath: null,
        mimetype: null,
        thumbfilepath: null,
        thumbmimetype: null,
      },
      deleted: false,
      locationId: c.irbeneId,
      time: '2009-09-04T23:44:21.000Z',
      type: 'location_entry',
      user: 'admin',
    }, {
      _id: c.id('581f166110a1482dd0b7ea02'),
      data: {
        isVisit: false,
        markdown: null,
        filepath: '2009/RxRvKSlbl/radar.jpg',  // the sample contains this
        mimetype: 'image/jpeg',
        thumbfilepath: '2009/RxRvKSlbl/radar_medium.jpg',
        thumbmimetype: 'image/jpeg',
      },
      deleted: false,
      locationId: c.irbeneId,
      time: '2009-10-02T11:11:01.000Z',
      type: 'location_entry',
      user: 'admin',
    }],

    events: [{
      data: {
        lng: 21.857705,
        lat: 57.55341,
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-07-30T10:44:57.000Z',
      type: 'location_created',
      user: 'admin',
    }, {
      data: {
        entryId: c.id('581f166110a1482dd0b7ea01'),
        isVisit: false,
        markdown: 'A ghost town',
        filepath: null,
        mimetype: null,
        thumbfilepath: null,
        thumbmimetype: null,
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-09-04T23:44:21.000Z',
      type: 'location_entry_created',
      user: 'admin',
    }, {
      data: {
        entryId: c.id('581f166110a1482dd0b7ea02'),
        isVisit: false,
        markdown: null,
        filepath: '2009/RxRvKSlbl/radar.jpg',  // the sample contains this
        mimetype: 'image/jpeg',
        thumbfilepath: '2009/RxRvKSlbl/radar_medium.jpg',
        thumbmimetype: 'image/jpeg',
      },
      locationId: c.irbeneId,
      locationName: 'Irbene',
      time: '2009-10-02T11:11:01.000Z',
      type: 'location_entry_created',
      user: 'admin',
    }],

    users: [{
      admin: true,
      email: 'admin@example.com',
      hash: c.PASSWORD,
      name: 'admin',
      points: 0,
      // points7days: created by worker
      // points30days: created by worker
      status: 'active',
    }],

    locations: [{
      _id: c.irbeneId,
      creator: 'admin',
      deleted: false,
      geom: {
        type: 'Point',
        coordinates: [21.857705, 57.55341],
      },
      layer: 12,
      isLayered: true,
      name: 'Irbene',
      points: 0,
      places: [],
      tags: ['walk-in'],
      text1: '',  // new
      text2: '',  // new
    }],
  },
};
<|endoftext|>


<commit_before>import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
chai.should();
import * as Sut from './V1Server';

describe('src/V1Server', function() {
	let actual;
	describe('given a V1 instance server url, protocol, port, username, password', () => {
		let v1ServerInfo;
		beforeEach(() => {
			v1ServerInfo = {
				hostname: 'some URL',
				instance: 'some Instance',
				protocol: 'https',
				port: '8081'
			};
		});

		describe('when getting the Urls for the VersionOne instance', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo);
			});

			it('it should return a way to get the Rest API Url', () => {
				chai.should().exist(actual.rest);
			});
		});

		describe('when getting the rest Url', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo).rest();
			});

			it('it should return the Rest API Url', () => {
				actual.should.equal('https://some URL/some Instance:8081/rest-1.v1/Data');
			});
		});

		describe('when getting the query.v1 Url', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo).query();
			});

			it('it should return the Rest API Url', () => {
				actual.should.equal('https://some URL/some Instance:8081/query.v1');
			});
		});
	});
});<commit_msg>#21 Specs that port should be before the instance name in the correct format: http://host:port/instance-name<commit_after>import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);
chai.should();
import * as Sut from './V1Server';

describe('src/V1Server', function() {
	let actual;
	describe('given a V1 instance server url, protocol, port, username, password', () => {
		let v1ServerInfo;
		beforeEach(() => {
			v1ServerInfo = {
				hostname: 'some URL',
				instance: 'some Instance',
				protocol: 'https',
				port: '8081'
			};
		});

		describe('when getting the Urls for the VersionOne instance', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo);
			});

			it('it should return a way to get the Rest API Url', () => {
				chai.should().exist(actual.rest);
			});
		});

		describe('when getting the rest Url', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo).rest();
			});

			it('it should return the Rest API Url', () => {
				actual.should.equal('https://some URL:8081/some Instance/rest-1.v1/Data');
			});
		});

		describe('when getting the query.v1 Url', () => {
			beforeEach(() => {
				actual = Sut.getUrlsForV1Server(v1ServerInfo).query();
			});

			it('it should return the Rest API Url', () => {
				actual.should.equal('https://some URL:8081/some Instance/query.v1');
			});
		});
	});
});<|endoftext|>


<commit_before>'use strict'
/* eslint-env browser, webextensions */

const offlinePeerCount = -1

function initState (options) {
  const state = {}
  // we store the most used values in optimized form
  // to minimize performance impact on overall browsing experience
  state.peerCount = offlinePeerCount
  state.ipfsNodeType = options.ipfsNodeType
  state.pubGwURL = new URL(options.publicGatewayUrl)
  state.pubGwURLString = state.pubGwURL.toString()
  state.redirect = options.useCustomGateway
  state.apiURL = new URL(options.ipfsApiUrl)
  state.apiURLString = state.apiURL.toString()
  state.gwURL = new URL(options.customGatewayUrl)
  state.gwURLString = state.gwURL.toString()
  state.automaticMode = options.automaticMode
  state.linkify = options.linkify
  state.dnslink = options.dnslink
  state.preloadAtPublicGateway = options.preloadAtPublicGateway
  state.catchUnhandledProtocols = options.catchUnhandledProtocols
  state.displayNotifications = options.displayNotifications
  state.ipfsProxy = options.ipfsProxy
  return state
}

exports.initState = initState
exports.offlinePeerCount = offlinePeerCount
<commit_msg>init node config in state<commit_after>'use strict'
/* eslint-env browser, webextensions */

const offlinePeerCount = -1

function initState (options) {
  const state = {}
  // we store the most used values in optimized form
  // to minimize performance impact on overall browsing experience
  state.peerCount = offlinePeerCount
  state.ipfsNodeType = options.ipfsNodeType
  state.ipfsNodeConfig = options.ipfsNodeConfig
  state.pubGwURL = new URL(options.publicGatewayUrl)
  state.pubGwURLString = state.pubGwURL.toString()
  state.redirect = options.useCustomGateway
  state.apiURL = new URL(options.ipfsApiUrl)
  state.apiURLString = state.apiURL.toString()
  state.gwURL = new URL(options.customGatewayUrl)
  state.gwURLString = state.gwURL.toString()
  state.automaticMode = options.automaticMode
  state.linkify = options.linkify
  state.dnslink = options.dnslink
  state.preloadAtPublicGateway = options.preloadAtPublicGateway
  state.catchUnhandledProtocols = options.catchUnhandledProtocols
  state.displayNotifications = options.displayNotifications
  state.ipfsProxy = options.ipfsProxy
  return state
}

exports.initState = initState
exports.offlinePeerCount = offlinePeerCount
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const chalk = require('chalk');

const Faker = require('../Libs/Faker');
const Mocha = require('mocha');

class Worker {
    constructor(scenario) {
        this.scenario = scenario;
        this.mocha = new Mocha();
        this.mocha.addFile(scenario.entrypoint);
        this.mocha.reporter('json');
        this.mocha.timeout(0);
        this.data = scenario.data;

        // Register worker process globals
        global.Faker = new Faker;
        global.Save = (path, data) => {
            _.set(this.data, path, data);

            process.send({
                save: {
                    path: path,
                    data: data
                }
            });
        };

        global.Get = (path) => _.get(this.data, path);

        global.Runs = (path) => {
            var theSnippet = require(process.cwd() + '/' + path);

            if (typeof theSnippet == 'function') {
                theSnippet();
            }

            return theSnippet;
        };
    }
    setup(done) {
        done();
    }
    teardown(done) {
        done();
    }
    run(done) {
        let output = '';

        process.stdout.write = (str) => {
            output += str;
        };

        this.mocha.run((failures) => {
            process.send({ output: output });
            done();
        });
    }
}

module.exports = Worker;
<commit_msg>Moves teardown<commit_after>'use strict';

const _ = require('lodash');
const chalk = require('chalk');

const Faker = require('../Libs/Faker');
const Mocha = require('mocha');

class Worker {
    constructor(scenario) {
        this.scenario = scenario;
        this.mocha = new Mocha();
        this.mocha.addFile(scenario.entrypoint);
        this.mocha.reporter('json');
        this.mocha.timeout(0);
        this.data = scenario.data;

        // Register worker process globals
        global.Faker = new Faker;
        global.Save = (path, data) => {
            _.set(this.data, path, data);

            process.send({
                save: {
                    path: path,
                    data: data
                }
            });
        };

        global.Get = (path) => _.get(this.data, path);

        global.Runs = (path) => {
            var theSnippet = require(process.cwd() + '/' + path);

            if (typeof theSnippet == 'function') {
                theSnippet();
            }

            return theSnippet;
        };
    }
    setup(done) {
        done();
    }
    run(done) {
        let output = '';

        process.stdout.write = (str) => {
            output += str;
        };

        this.mocha.run((failures) => {
            process.send({ output: output });
            done();
        });
    teardown(done) {
        done();
    }
}

module.exports = Worker;
<|endoftext|>


<commit_before>/**
 * @file MaterialDatePicker component
 * @author sunday(sunday.wei@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import cloneDeep from 'lodash/cloneDeep';
import classNames from 'classnames';

import DatePickerTextField from '../_MaterialDatePickerTextField';
import DayPicker from '../_DayPicker';
import MonthPicker from '../_MonthPicker';
import YearPicker from '../_YearPicker';
import Popup from '../Popup';
import Theme from '../Theme';

import Position from '../_statics/Position';
import {findDOMNode} from 'react-dom';
import DropdownCalculation from '../_vendors/DropdownCalculation';

class MaterialDatePicker extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.validValue = true;
        const defaultValue = props.value ? props.value : moment().format('YYYY-MM-DD');

        this.state = {
            value: props.value,
            popupVisible: false,
            isAbove: false,
            year: moment(defaultValue).format('YYYY'),
            month: moment(defaultValue).format('MM'),
            day: moment(defaultValue).format('DD'),
            datePickerLevel: 'day',
            marginLeft: 0
        };

    }

    datePickerChangeHandle = selectLevel => {
        this.setState({
            datePickerLevel: selectLevel
        });
    };

    textFieldChangeHandle = text => {

        const {minValue, maxValue, dateFormat} = this.props;
        if (text && text.length) {
            const flag = moment(text, this.props.dateFormat, true).isValid();
            if (flag) {
                if (minValue && moment(text).isBefore(minValue) || maxValue && moment(text).isAfter(maxValue)) {

                } else {
                    const year = moment(text).format('YYYY'),
                        month = moment(text).format('MM'),
                        day = moment(text).format('DD');
                    this.setState({
                        value: moment(text, dateFormat),
                        year: year,
                        month: month,
                        day: day
                    });
                }
            } else {

            }
        } else {
            this.setState({
                value: ''
            });
        }
    };

    dayPickerChangeHandle = date => {
        const {autoClose, dateFormat} = this.props;
        let state = cloneDeep(this.state);
        state.value = moment(date.time, dateFormat);
        state.year = date.year;
        state.month = date.month;
        state.day = date.day;
        state.popupVisible = !autoClose;
        if (state.popupVisible) {
            this.setState(state);
        } else {
            !this.props.disabled && this.setState(state, () => {
                this.props.onChange && this.props.onChange(moment(date.time).format(dateFormat));
            });
        }
    };

    monthPickerChangeHandle = date => {
        this.setState({
            datePickerLevel: 'day',
            year: date.year,
            month: date.month
        });
    };

    yearPickerChangeHandle = year => {
        this.setState({
            datePickerLevel: 'month',
            year: year
        });
    };

    todayHandle = () => {
        const {dateFormat} = this.props;
        const year = moment().format('YYYY'),
            month = moment().format('MM'),
            day = moment().format('DD');
        let timer = moment(moment(), dateFormat);
        this.setState({
            value: timer,
            year: year,
            month: month,
            day: day
        });
    };

    togglePopup = e => {
        if (this.validValue) {
            this.setState({
                popupVisible: !this.state.popupVisible
            });
        }
    };

    closePopup = () => {
        const {value} = this.state;
        !this.props.disabled && this.setState({
            popupVisible: false
        }, () => {
            this.props.onChange && this.props.onChange(value && moment(value).format(this.props.dateFormat));
        });
    };

    popupRenderHandler = popupEl => {

        if (this.props.position) {
            return;
        }

        const isAbove = DropdownCalculation.isAbove(this.dropdownEl, this.triggerEl, findDOMNode(popupEl));
        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    componentDidMount() {
        // debugger
        const {value, dateFormat} = this.props;
        let state = cloneDeep(this.state);
        if (value) {
            if (moment(value, dateFormat).isValid()) {
                const year = moment(value).format('YYYY'),
                    month = moment(value).format('MM'),
                    day = moment(value).format('DD');
                state.value = moment(value, dateFormat);
                state.year = year;
                state.month = month;
                state.day = day;
                this.setState(state);
            } else {
                this.validValue = false;
                console.error('Invalid date');
            }
        }

        this.datePicker = this.refs.datePicker;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value || nextProps.dateFormat !== this.props.dateFormat) {
            this.setState({
                value: moment(nextProps.value, nextProps.dateFormat),
                dateFormat: nextProps.dateFormat,
                year: moment(nextProps.value).format('YYYY'),
                month: moment(nextProps.value).format('MM'),
                day: moment(nextProps.value).format('DD')
            });
        }
    }

    render() {

        const {
                className, name, placeholder, dateFormat, maxValue, minValue, label, isLabelAnimate, isFooter, position,
                theme, popupClassName, rightIconCls, previousYearIconCls, previousMonthIconCls, nextYearIconCls,
                nextMonthIconCls
            } = this.props,
            {value, popupVisible, datePickerLevel, year, month, day, isAbove, isHover, isFocus} = this.state,

            pickerClassName = classNames('material-date-picker', {
                [className]: className
            }),

            textValue = value && moment(value).format(dateFormat);

        return (

                <DatePickerTextField ref="trigger"
                                     name={name}
                                     placeholder={placeholder}
                                     value={textValue}
                                     theme={theme}
                                     readOnly={!popupVisible}
                                     clearButtonVisible={false}
                                     isFocusedSelectAll={false}
                                     popupVisible={popupVisible}
                                     label={label}
                                     isLabelAnimate={isLabelAnimate}
                                     rightIconCls={rightIconCls}
                                     onChange={this.textFieldChangeHandle}
                                     onClick={e => {
                                         this.togglePopup(e);
                                     }}/>

                <Popup className={`material-date-picker-popup ${popupClassName}`}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                       hasTriangle={false}
                       onRender={this.popupRenderHandler}
                       onRequestClose={() => {
                           this.closePopup(3);
                       }}>

                    {
                        datePickerLevel == 'day' ?
                            <DayPicker value={value}
                                       dateFormat={dateFormat}
                                       year={year}
                                       month={month}
                                       day={day}
                                       maxValue={maxValue}
                                       minValue={minValue}
                                       isFooter={isFooter}
                                       previousYearIconCls={previousYearIconCls}
                                       previousMonthIconCls={previousMonthIconCls}
                                       nextYearIconCls={nextYearIconCls}
                                       nextMonthIconCls={nextMonthIconCls}
                                       onChange={this.dayPickerChangeHandle}
                                       previousClick={this.datePickerChangeHandle}/>
                            : (
                                datePickerLevel == 'month' ?
                                    <MonthPicker value={value}
                                                 year={year}
                                                 month={month}
                                                 day={day}
                                                 maxValue={maxValue}
                                                 minValue={minValue}
                                                 previousYearIconCls={previousYearIconCls}
                                                 previousMonthIconCls={previousMonthIconCls}
                                                 nextYearIconCls={nextYearIconCls}
                                                 nextMonthIconCls={nextMonthIconCls}
                                                 onChange={this.monthPickerChangeHandle}
                                                 previousClick={this.datePickerChangeHandle}/>
                                    :
                                    <YearPicker value={value}
                                                year={year}
                                                month={month}
                                                day={day}
                                                maxValue={maxValue}
                                                minValue={minValue}
                                                previousYearIconCls={previousYearIconCls}
                                                previousMonthIconCls={previousMonthIconCls}
                                                nextYearIconCls={nextYearIconCls}
                                                nextMonthIconCls={nextMonthIconCls}
                                                onChange={this.yearPickerChangeHandle}/>
                            )
                    }

                    {
                        isFooter && datePickerLevel == 'day' ?

                                {
                                    (minValue && moment(this.props.value).isBefore(minValue))
                                    || (maxValue && moment(maxValue).isBefore(this.props.value)) ?

                                            Today

                                        :

                                            Today

                                }

                            :
                            null
                    }

                </Popup>

        );
    }
}

MaterialDatePicker.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Date picker input name.
     */
    name: PropTypes.string,

    /**
     * This is the initial date value of the component.
     */
    value: PropTypes.any,

    /**
     * The label of the date picker.
     */
    label: PropTypes.any,

    /**
     * The animate of the date picker.
     */
    isLabelAnimate: PropTypes.bool,

    /**
     * The ending of a range of valid dates. The range includes the endDate.
     */
    maxValue: PropTypes.any,

    /**
     * The beginning of a range of valid dates. The range includes the startDate.
     */
    minValue: PropTypes.any,

    /**
     * DatePicker textField element placeholder.
     */
    placeholder: PropTypes.string,

    /**
     * Date format.
     */
    dateFormat: PropTypes.string,

    /**
     * If true,hide date display.
     */
    autoClose: PropTypes.bool,

    /**
     * Callback function that is fired when the date value changes.
     */
    onChange: PropTypes.func

};

MaterialDatePicker.defaultProps = {
    name: '',
    maxValue: '',
    minValue: '',
    popupClassName: '',
    placeholder: 'Date',
    dateFormat: 'YYYY-MM-DD',
    isLabelAnimate: true,
    autoClose: true,
    isFooter: true,
    previousYearIconCls:'fas fa-angle-double-left',
    previousMonthIconCls:'fas fa-angle-left',
    nextYearIconCls:'fas fa-angle-double-right',
    nextMonthIconCls:'fas fa-angle-right',
    position: Position.BOTTOM_LEFT
};

export default MaterialDatePicker;<commit_msg>update MaterialDatePicker<commit_after>/**
 * @file MaterialDatePicker component
 * @author sunday(sunday.wei@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import cloneDeep from 'lodash/cloneDeep';
import classNames from 'classnames';

import DatePickerTextField from '../_MaterialDatePickerTextField';
import DayPicker from '../_DayPicker';
import MonthPicker from '../_MonthPicker';
import YearPicker from '../_YearPicker';
import Popup from '../Popup';
import Theme from '../Theme';

import Position from '../_statics/Position';
import {findDOMNode} from 'react-dom';
import DropdownCalculation from '../_vendors/DropdownCalculation';

class MaterialDatePicker extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.validValue = true;
        const defaultValue = props.value ? props.value : moment().format('YYYY-MM-DD');

        this.state = {
            value: props.value,
            popupVisible: false,
            isAbove: false,
            year: moment(defaultValue).format('YYYY'),
            month: moment(defaultValue).format('MM'),
            day: moment(defaultValue).format('DD'),
            datePickerLevel: 'day',
            marginLeft: 0
        };

    }

    datePickerChangeHandle = selectLevel => {
        this.setState({
            datePickerLevel: selectLevel
        });
    };

    textFieldChangeHandle = text => {

        const {minValue, maxValue, dateFormat} = this.props;
        if (text && text.length) {
            const flag = moment(text, this.props.dateFormat, true).isValid();
            if (flag) {
                if (minValue && moment(text).isBefore(minValue) || maxValue && moment(text).isAfter(maxValue)) {

                } else {
                    const year = moment(text).format('YYYY'),
                        month = moment(text).format('MM'),
                        day = moment(text).format('DD');
                    this.setState({
                        value: moment(text, dateFormat),
                        year: year,
                        month: month,
                        day: day
                    });
                }
            } else {

            }
        } else {
            this.setState({
                value: ''
            });
        }
    };

    dayPickerChangeHandle = date => {
        const {autoClose, dateFormat} = this.props;
        let state = cloneDeep(this.state);
        state.value = moment(date.time, dateFormat);
        state.year = date.year;
        state.month = date.month;
        state.day = date.day;
        state.popupVisible = !autoClose;
        if (state.popupVisible) {
            this.setState(state);
        } else {
            !this.props.disabled && this.setState(state, () => {
                this.props.onChange && this.props.onChange(moment(date.time).format(dateFormat));
            });
        }
    };

    monthPickerChangeHandle = date => {
        this.setState({
            datePickerLevel: 'day',
            year: date.year,
            month: date.month
        });
    };

    yearPickerChangeHandle = year => {
        this.setState({
            datePickerLevel: 'month',
            year: year
        });
    };

    todayHandle = () => {
        const {dateFormat} = this.props;
        const year = moment().format('YYYY'),
            month = moment().format('MM'),
            day = moment().format('DD');
        let timer = moment(moment(), dateFormat);
        this.setState({
            value: timer,
            year: year,
            month: month,
            day: day
        });
    };

    togglePopup = e => {
        if (this.validValue) {
            this.setState({
                popupVisible: !this.state.popupVisible
            });
        }
    };

    closePopup = () => {
        const {value} = this.state;
        !this.props.disabled && this.setState({
            popupVisible: false
        }, () => {
            this.props.onChange && this.props.onChange(value && moment(value).format(this.props.dateFormat));
        });
    };

    popupRenderHandler = popupEl => {

        if (this.props.position) {
            return;
        }

        const isAbove = DropdownCalculation.isAbove(this.dropdownEl, this.triggerEl, findDOMNode(popupEl));
        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    componentDidMount() {
        // debugger
        const {value, dateFormat} = this.props;
        let state = cloneDeep(this.state);
        if (value) {
            if (moment(value, dateFormat).isValid()) {
                const year = moment(value).format('YYYY'),
                    month = moment(value).format('MM'),
                    day = moment(value).format('DD');
                state.value = moment(value, dateFormat);
                state.year = year;
                state.month = month;
                state.day = day;
                this.setState(state);
            } else {
                this.validValue = false;
                console.error('Invalid date');
            }
        }

        this.datePicker = this.refs.datePicker;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value || nextProps.dateFormat !== this.props.dateFormat) {
            this.setState({
                value: moment(nextProps.value, nextProps.dateFormat),
                dateFormat: nextProps.dateFormat,
                year: moment(nextProps.value).format('YYYY'),
                month: moment(nextProps.value).format('MM'),
                day: moment(nextProps.value).format('DD')
            });
        }
    }

    render() {

        const {
                className, name, placeholder, dateFormat, maxValue, minValue, label, isLabelAnimate, isFooter, position,
                theme, popupClassName, rightIconCls, previousYearIconCls, previousMonthIconCls, nextYearIconCls,
                nextMonthIconCls
            } = this.props,
            {value, popupVisible, datePickerLevel, year, month, day, isAbove, isHover, isFocus} = this.state,

            pickerClassName = classNames('material-date-picker', {
                [className]: className
            }),

            textValue = value && moment(value).format(dateFormat);

        return (

                <DatePickerTextField ref="trigger"
                                     name={name}
                                     placeholder={placeholder}
                                     value={textValue}
                                     theme={theme}
                                     readOnly={!popupVisible}
                                     clearButtonVisible={false}
                                     isFocusedSelectAll={false}
                                     popupVisible={popupVisible}
                                     label={label}
                                     isLabelAnimate={isLabelAnimate}
                                     rightIconCls={rightIconCls}
                                     onChange={this.textFieldChangeHandle}
                                     onClick={e => this.togglePopup(e)}/>

                <Popup className={`material-date-picker-popup ${popupClassName}`}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                       hasTriangle={false}
                       onRender={this.popupRenderHandler}
                       onRequestClose={() => this.closePopup(3)}>

                    {
                        datePickerLevel == 'day' ?
                            <DayPicker value={value}
                                       dateFormat={dateFormat}
                                       year={year}
                                       month={month}
                                       day={day}
                                       maxValue={maxValue}
                                       minValue={minValue}
                                       isFooter={isFooter}
                                       previousYearIconCls={previousYearIconCls}
                                       previousMonthIconCls={previousMonthIconCls}
                                       nextYearIconCls={nextYearIconCls}
                                       nextMonthIconCls={nextMonthIconCls}
                                       onChange={this.dayPickerChangeHandle}
                                       previousClick={this.datePickerChangeHandle}/>
                            : (
                                datePickerLevel == 'month' ?
                                    <MonthPicker value={value}
                                                 year={year}
                                                 month={month}
                                                 day={day}
                                                 maxValue={maxValue}
                                                 minValue={minValue}
                                                 previousYearIconCls={previousYearIconCls}
                                                 previousMonthIconCls={previousMonthIconCls}
                                                 nextYearIconCls={nextYearIconCls}
                                                 nextMonthIconCls={nextMonthIconCls}
                                                 onChange={this.monthPickerChangeHandle}
                                                 previousClick={this.datePickerChangeHandle}/>
                                    :
                                    <YearPicker value={value}
                                                year={year}
                                                month={month}
                                                day={day}
                                                maxValue={maxValue}
                                                minValue={minValue}
                                                previousYearIconCls={previousYearIconCls}
                                                previousMonthIconCls={previousMonthIconCls}
                                                nextYearIconCls={nextYearIconCls}
                                                nextMonthIconCls={nextMonthIconCls}
                                                onChange={this.yearPickerChangeHandle}/>
                            )
                    }

                    {
                        isFooter && datePickerLevel == 'day' ?

                                {
                                    (minValue && moment(this.props.value).isBefore(minValue))
                                    || (maxValue && moment(maxValue).isBefore(this.props.value)) ?

                                            Today

                                        :

                                            Today

                                }

                            :
                            null
                    }

                </Popup>

        );
    }
}

MaterialDatePicker.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Date picker input name.
     */
    name: PropTypes.string,

    /**
     * This is the initial date value of the component.
     */
    value: PropTypes.any,

    /**
     * The label of the date picker.
     */
    label: PropTypes.any,

    /**
     * The animate of the date picker.
     */
    isLabelAnimate: PropTypes.bool,

    /**
     * The ending of a range of valid dates. The range includes the endDate.
     */
    maxValue: PropTypes.any,

    /**
     * The beginning of a range of valid dates. The range includes the startDate.
     */
    minValue: PropTypes.any,

    /**
     * DatePicker textField element placeholder.
     */
    placeholder: PropTypes.string,

    /**
     * Date format.
     */
    dateFormat: PropTypes.string,

    /**
     * If true,hide date display.
     */
    autoClose: PropTypes.bool,

    /**
     * Callback function that is fired when the date value changes.
     */
    onChange: PropTypes.func

};

MaterialDatePicker.defaultProps = {
    name: '',
    maxValue: '',
    minValue: '',
    popupClassName: '',
    placeholder: 'Date',
    dateFormat: 'YYYY-MM-DD',
    isLabelAnimate: true,
    autoClose: true,
    isFooter: true,
    previousYearIconCls: 'fas fa-angle-double-left',
    previousMonthIconCls: 'fas fa-angle-left',
    nextYearIconCls: 'fas fa-angle-double-right',
    nextMonthIconCls: 'fas fa-angle-right',
    position: Position.BOTTOM_LEFT
};

export default MaterialDatePicker;<|endoftext|>


<commit_before>"use strict";

commonModule.service("apiStorage", ["$q", "$rootScope", "$timeout", "apiAuth",
  function ($q, $rootScope, $timeout, apiAuth) {
    var self = this;
    var getCompanyId = function () {
      var res = "";
      if (apiAuth.userCompany) {
        res = apiAuth.userCompany.id;
      }
      return res;
    };

    var loadStorageAPI = function () {
      gapi.client.load("storage", "v0.01", function () {
        if (gapi.client.storage) {
          console && console.log("Storage API is loaded");
          $rootScope.$broadcast("storageApi.loaded");
        } else {
          console && console.error("Store API is NOT loaded");
        }
      }, rvGlobals.STORAGE_URL);
    };

    $rootScope.$on("userCompany.loaded", function (event) {

      loadStorageAPI();

    });

    this.getFiles = function (companyId) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId
      };
      var request = gapi.client.storage.files.get(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code === 200) {
          $rootScope.actionsDisabled = false;
        }
        else if (resp.code === 403 || resp.code === 401 || resp.code === 400) {
          $rootScope.authenticationError = true;
        }
        else if (resp.code == 404) {
          $rootScope.actionsDisabled = false;
          $rootScope.requireBucketCreation = true;
        }
      deferred.resolve(resp);
      });

      return deferred.promise;
    };

    this.deleteFiles = function (companyId, files, validationRequired) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "files": files
      };
      var request = gapi.client.storage.files.delete(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error deleting files: ", resp);
          resp = null;
        }
        deferred.resolve(resp);
      });

      return deferred.promise;
    };

    this.getFileUrl = function (companyId, file) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "file": file
      };
      var request = gapi.client.storage.file.url(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error retrieving policy: ", resp);
          resp = null;
        }
        deferred.resolve(resp.response);
      });

      return deferred.promise;

    };

    this.createBucket = function (companyId) {
      var deferred = $q.defer();
      var obj = {
        "companyId": companyId,
      };
      var request = gapi.client.storage.createBucket(obj);
      request.execute(function (resp) {
        if (resp.code !== 200) {
          console && console.error("Error creating bucket: ", resp);
          deferred.reject(resp);
        } else {
          console && console.log(resp);
          deferred.resolve(resp);
        }
      });
      return deferred.promise;
    };

    this.getUploadPolicyBase64 = function (bucketName, uploadFileName, contentType, responseUrl) {

      var policyString = '{' +
        '  "expiration": "2020-01-01T12:00:00.000Z",' +
        '  "conditions": [' +
        '    {"bucket": "' + bucketName + '" },' +
        '    {"acl": "public-read" },' +
        '    ["eq", "$key", "' + uploadFileName + '"],' +
        '    ["starts-with", "$Content-Type", "' + contentType + '"],' +
        '    ["starts-with", "$Cache-Control", "public, max-age=60"],' +
        '    {"success_action_redirect": "' + responseUrl + '" },' +
        '  ]' +
        '}';

      return utf8_to_b64(policyString);

    };

    function utf8_to_b64( str ) {
      return window.btoa(unescape(encodeURIComponent( str )));
    }

    this.getSignedPolicy = function (companyId, policyBase64) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "policyBase64": policyBase64
      };
      var request = gapi.client.storage.signPolicy(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error retrieving policy: ", resp);
          resp = null;
        }
        deferred.resolve(resp.response);
      });

      return deferred.promise;
    };
  } ]);
<commit_msg>Allow storage api url override<commit_after>"use strict";

commonModule.service("apiStorage", ["$q", "$rootScope", "$timeout", "apiAuth", "$routeParams",
  function ($q, $rootScope, $timeout, apiAuth, $routeParams) {
    var self = this;
    var getCompanyId = function () {
      var res = "";
      if (apiAuth.userCompany) {
        res = apiAuth.userCompany.id;
      }
      return res;
    };

    var loadStorageAPI = function () {
      gapi.client.load("storage", "v0.01", function () {
        if (gapi.client.storage) {
          console && console.log("Storage API is loaded");
          $rootScope.$broadcast("storageApi.loaded");
        } else {
          console && console.error("Store API is NOT loaded");
        }
      }, $routeParams.apiuri ? $routeParams.apiuri : rvGlobals.STORAGE_URL);
    };

    $rootScope.$on("userCompany.loaded", function (event) {

      loadStorageAPI();

    });

    this.getFiles = function (companyId) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId
      };
      var request = gapi.client.storage.files.get(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code === 200) {
          $rootScope.actionsDisabled = false;
        }
        else if (resp.code === 403 || resp.code === 401 || resp.code === 400) {
          $rootScope.authenticationError = true;
        }
        else if (resp.code == 404) {
          $rootScope.actionsDisabled = false;
          $rootScope.requireBucketCreation = true;
        }
      deferred.resolve(resp);
      });

      return deferred.promise;
    };

    this.deleteFiles = function (companyId, files, validationRequired) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "files": files
      };
      var request = gapi.client.storage.files.delete(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error deleting files: ", resp);
          resp = null;
        }
        deferred.resolve(resp);
      });

      return deferred.promise;
    };

    this.getFileUrl = function (companyId, file) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "file": file
      };
      var request = gapi.client.storage.file.url(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error retrieving policy: ", resp);
          resp = null;
        }
        deferred.resolve(resp.response);
      });

      return deferred.promise;

    };

    this.createBucket = function (companyId) {
      var deferred = $q.defer();
      var obj = {
        "companyId": companyId,
      };
      var request = gapi.client.storage.createBucket(obj);
      request.execute(function (resp) {
        if (resp.code !== 200) {
          console && console.error("Error creating bucket: ", resp);
          deferred.reject(resp);
        } else {
          console && console.log(resp);
          deferred.resolve(resp);
        }
      });
      return deferred.promise;
    };

    this.getUploadPolicyBase64 = function (bucketName, uploadFileName, contentType, responseUrl) {

      var policyString = '{' +
        '  "expiration": "2020-01-01T12:00:00.000Z",' +
        '  "conditions": [' +
        '    {"bucket": "' + bucketName + '" },' +
        '    {"acl": "public-read" },' +
        '    ["eq", "$key", "' + uploadFileName + '"],' +
        '    ["starts-with", "$Content-Type", "' + contentType + '"],' +
        '    ["starts-with", "$Cache-Control", "public, max-age=60"],' +
        '    {"success_action_redirect": "' + responseUrl + '" },' +
        '  ]' +
        '}';

      return utf8_to_b64(policyString);

    };

    function utf8_to_b64( str ) {
      return window.btoa(unescape(encodeURIComponent( str )));
    }

    this.getSignedPolicy = function (companyId, policyBase64) {
      var deferred = $q.defer();

      var obj = {
        "companyId": companyId,
        "policyBase64": policyBase64
      };
      var request = gapi.client.storage.signPolicy(obj);
      request.execute(function (resp) {
        console && console.log(resp);
        if (resp.code !== 200) {
          console && console.error("Error retrieving policy: ", resp);
          resp = null;
        }
        deferred.resolve(resp.response);
      });

      return deferred.promise;
    };
  } ]);
<|endoftext|>


<commit_before>'use strict';

var last = require('lodash/array/last');
var each = require('lodash/collection/each');
var uuid = require('../../util/uuid');
var annotationHelpers = require('../annotationHelpers');
var deleteSelection = require('./deleteSelection');
var insertText = require('./insertText');
var breakNode = require('./breakNode');

var CLIPBOARD_CONTAINER_ID = require('./copySelection').CLIPBOARD_CONTAINER_ID;
var CLIPBOARD_PROPERTY_ID = require('./copySelection').CLIPBOARD_PROPERTY_ID;

/* jshint latedef: false */

/**
  Pastes clipboard content at the current selection

  @param {Object} args object with `selection` and `doc` for Substance content or
  `text` for external HTML content
  @return {Object} with updated `selection`
*/

var paste = function(tx, args) {
  if (args.selection.isNull()) {
    console.error("Can not paste, without selection.");
    return args;
  }
  // TODO: is there a better way to detect that this paste is happening within a
  // container?
  var inContainer = !!args.containerId;
  var pasteDoc = args.doc;

  // when we are in a container, we interpret line-breaks
  // and create a document with multiple paragraphs
  // in a PropertyEditor we paste the text as is
  if (args.text && !pasteDoc) {
    if (inContainer) {
      args.doc = pasteDoc = _convertPlainTextToDocument(tx, args);
    } else {
      return insertText(tx, args);
    }
  }
  if (!args.selection.isCollapsed()) {
    var tmp = deleteSelection(tx, args);
    args.selection = tmp.selection;
  }
  var nodes = pasteDoc.get(CLIPBOARD_CONTAINER_ID).nodes;
  if (nodes.length > 0) {
    var first = pasteDoc.get(nodes[0]);
    // copy of a property selection creates a doc containing
    // one default text node with a specific id
    if (nodes.length === 1 && first.id === CLIPBOARD_PROPERTY_ID) {
      return _pasteAnnotatedText(tx, args);
    } else {
      return _pasteDocument(tx, args);
    }
  }
  return args;
};

/*
  Splits plain text by lines and puts them into paragraphs.
*/
function _convertPlainTextToDocument(tx, args) {
  var defaultTextType = tx.getSchema().getDefaultTextType();
  var lines = args.text.split(/\s*\n\s*\n/);
  var pasteDoc = tx.newInstance();
  var container = pasteDoc.create({
    type: 'container',
    id: CLIPBOARD_CONTAINER_ID,
    nodes: []
  });
  var node;
  if (lines.length === 1) {
    node = pasteDoc.create({
      id: CLIPBOARD_PROPERTY_ID,
      type: defaultTextType,
      content: lines[0]
    });
    container.show(node.id);
  } else {
    for (var i = 0; i < lines.length; i++) {
      node = pasteDoc.create({
        id: uuid(defaultTextType),
        type: defaultTextType,
        content: lines[i]
      });
      container.show(node.id);
    }
  }
  return pasteDoc;
}

function _pasteAnnotatedText(tx, args) {
  var copy = args.doc;
  var selection = args.selection;

  var nodes = copy.get(CLIPBOARD_CONTAINER_ID).nodes;
  var textPath = [nodes[0], 'content'];
  var text = copy.get(textPath);
  var annotations = copy.getIndex('annotations').get(textPath);
  // insert plain text
  var path = selection.start.path;
  var offset = selection.start.offset;
  tx.update(path, { insert: { offset: offset, value: text } } );
  annotationHelpers.insertedText(tx, selection.start, text.length);
  selection = tx.createSelection({
    type: 'property',
    path: selection.start.path,
    startOffset: selection.start.offset+text.length
  });
  // copy annotations
  each(annotations, function(anno) {
    var data = anno.toJSON();
    data.path = path.slice(0);
    data.startOffset += offset;
    data.endOffset += offset;
    if (tx.get(data.id)) {
      data.id = uuid(data.type);
    }
    tx.create(data);
  });
  args.selection = selection;
  return args;
}

function _pasteDocument(tx, args) {
  var pasteDoc = args.doc;
  var containerId = args.containerId;
  var selection = args.selection;
  var container = tx.get(containerId);

  var startPath = selection.start.path;
  var startAddress = container.getAddress(startPath);
  var nextAddress = container.getNextAddress(startAddress);
  var insertPos;
  // Break, unless we are at the last character of a node,
  // then we can simply insert after the node
  if ( (!nextAddress || nextAddress[0] !== startAddress[0]) &&
    tx.get(startPath).length === selection.start.offset )
  {
    insertPos = startAddress[0] + 1;
  } else {
    var result = breakNode(tx, args);
    selection = result.selection;
    insertPos = startAddress[0] + 1;
  }
  if (insertPos < 0) {
    console.error('Could not find insertion position in ContainerNode.');
  }
  // transfer nodes from content document
  // TODO: transfer annotations
  var nodeIds = pasteDoc.get(CLIPBOARD_CONTAINER_ID).nodes;
  var annoIndex = pasteDoc.getIndex('annotations');
  var insertedNodes = [];
  for (var i = 0; i < nodeIds.length; i++) {
    var nodeId = nodeIds[i];
    var node = pasteDoc.get(nodeId).toJSON();
    // create a new id if the node exists already
    if (tx.get(nodeId)) {
      node.id = uuid(node.type);
    }
    node = tx.create(node);
    container.show(node.id, insertPos++);
    insertedNodes.push(node);

    // transfer annotations
    // what about nodes that are referenced by annotations?
    var annos = annoIndex.get(nodeId);
    for (var j = 0; j < annos.length; j++) {
      var data = annos[j].toJSON();
      if (node.id !== nodeId) {
        data.path[0] = node.id;
      }
      if (tx.get(data.id)) {
        data.id = uuid(data.type);
      }
      tx.create(data);
    }
  }

  if (insertedNodes.length === 0) return args;

  // set a new selection
  var lastPath = container.getLastPath(last(insertedNodes));
  var lastLength = tx.get(lastPath).length;
  // This version turned out to be useful in some situations
  // as it hightlights the pasted content
  // we leave it here for debugging
  if (false) {
    var firstPath = container.getFirstPath(insertedNodes[0]);
    selection = tx.createSelection({
      type: 'container',
      containerId: container.id,
      startPath: firstPath,
      startOffset: 0,
      endPath: lastPath,
      endOffset: lastLength
    });
  } else {
    selection = tx.createSelection({
      type: 'property',
      path: lastPath,
      startOffset: lastLength
    });
  }
  args.selection = selection;
  return args;
}

module.exports = paste;
<commit_msg>Clean up.<commit_after>'use strict';

var last = require('lodash/array/last');
var each = require('lodash/collection/each');
var uuid = require('../../util/uuid');
var annotationHelpers = require('../annotationHelpers');
var deleteSelection = require('./deleteSelection');
var insertText = require('./insertText');
var breakNode = require('./breakNode');

var CLIPBOARD_CONTAINER_ID = require('./copySelection').CLIPBOARD_CONTAINER_ID;
var CLIPBOARD_PROPERTY_ID = require('./copySelection').CLIPBOARD_PROPERTY_ID;

/* jshint latedef: false */

/**
  Pastes clipboard content at the current selection

  @param {Object} args object with `selection` and `doc` for Substance content or
  `text` for external HTML content
  @return {Object} with updated `selection`
*/

var paste = function(tx, args) {
  if (args.selection.isNull()) {
    console.error("Can not paste, without selection.");
    return args;
  }
  // TODO: is there a better way to detect that this paste is happening within a
  // container?
  var inContainer = !!args.containerId;
  var pasteDoc = args.doc;

  // when we are in a container, we interpret line-breaks
  // and create a document with multiple paragraphs
  // in a PropertyEditor we paste the text as is
  if (args.text && !pasteDoc) {
    if (inContainer) {
      args.doc = pasteDoc = _convertPlainTextToDocument(tx, args);
    } else {
      return insertText(tx, args);
    }
  }
  if (!args.selection.isCollapsed()) {
    var tmp = deleteSelection(tx, args);
    args.selection = tmp.selection;
  }
  var nodes = pasteDoc.get(CLIPBOARD_CONTAINER_ID).nodes;
  if (nodes.length > 0) {
    var first = pasteDoc.get(nodes[0]);
    // copy of a property selection creates a doc containing
    // one default text node with a specific id
    if (nodes.length === 1 && first.id === CLIPBOARD_PROPERTY_ID) {
      return _pasteAnnotatedText(tx, args);
    } else {
      return _pasteDocument(tx, args);
    }
  }
  return args;
};

/*
  Splits plain text by lines and puts them into paragraphs.
*/
function _convertPlainTextToDocument(tx, args) {
  var defaultTextType = tx.getSchema().getDefaultTextType();
  var lines = args.text.split(/\s*\n\s*\n/);
  var pasteDoc = tx.newInstance();
  var container = pasteDoc.create({
    type: 'container',
    id: CLIPBOARD_CONTAINER_ID,
    nodes: []
  });
  var node;
  if (lines.length === 1) {
    node = pasteDoc.create({
      id: CLIPBOARD_PROPERTY_ID,
      type: defaultTextType,
      content: lines[0]
    });
    container.show(node.id);
  } else {
    for (var i = 0; i < lines.length; i++) {
      node = pasteDoc.create({
        id: uuid(defaultTextType),
        type: defaultTextType,
        content: lines[i]
      });
      container.show(node.id);
    }
  }
  return pasteDoc;
}

function _pasteAnnotatedText(tx, args) {
  var copy = args.doc;
  var selection = args.selection;

  var nodes = copy.get(CLIPBOARD_CONTAINER_ID).nodes;
  var textPath = [nodes[0], 'content'];
  var text = copy.get(textPath);
  var annotations = copy.getIndex('annotations').get(textPath);
  // insert plain text
  var path = selection.start.path;
  var offset = selection.start.offset;
  tx.update(path, { insert: { offset: offset, value: text } } );
  annotationHelpers.insertedText(tx, selection.start, text.length);
  selection = tx.createSelection({
    type: 'property',
    path: selection.start.path,
    startOffset: selection.start.offset+text.length
  });
  // copy annotations
  each(annotations, function(anno) {
    var data = anno.toJSON();
    data.path = path.slice(0);
    data.startOffset += offset;
    data.endOffset += offset;
    if (tx.get(data.id)) {
      data.id = uuid(data.type);
    }
    tx.create(data);
  });
  args.selection = selection;
  return args;
}

function _pasteDocument(tx, args) {
  var pasteDoc = args.doc;
  var containerId = args.containerId;
  var selection = args.selection;
  var container = tx.get(containerId);

  var startPath = selection.start.path;
  var startAddress = container.getAddress(startPath);
  var nextAddress = container.getNextAddress(startAddress);
  var insertPos;
  // Break, unless we are at the last character of a node,
  // then we can simply insert after the node
  if ( (!nextAddress || nextAddress[0] !== startAddress[0]) &&
    tx.get(startPath).length === selection.start.offset )
  {
    insertPos = startAddress[0] + 1;
  } else {
    var result = breakNode(tx, args);
    selection = result.selection;
    insertPos = startAddress[0] + 1;
  }
  // TODO how should this check be useful?
  if (insertPos < 0) {
    console.error('Could not find insertion position in ContainerNode.');
  }
  // transfer nodes from content document
  var nodeIds = pasteDoc.get(CLIPBOARD_CONTAINER_ID).nodes;
  var annoIndex = pasteDoc.getIndex('annotations');
  var insertedNodes = [];
  for (var i = 0; i < nodeIds.length; i++) {
    var nodeId = nodeIds[i];
    var node = pasteDoc.get(nodeId).toJSON();
    // create a new id if the node exists already
    if (tx.get(nodeId)) {
      node.id = uuid(node.type);
    }
    node = tx.create(node);
    container.show(node.id, insertPos++);
    insertedNodes.push(node);

    // transfer annotations
    // what if we have changed the id of nodes that are referenced by annotations?
    var annos = annoIndex.get(nodeId);
    for (var j = 0; j < annos.length; j++) {
      var data = annos[j].toJSON();
      if (node.id !== nodeId) {
        data.path[0] = node.id;
      }
      if (tx.get(data.id)) {
        data.id = uuid(data.type);
      }
      tx.create(data);
    }
  }

  if (insertedNodes.length === 0) return args;

  // set a new selection
  var lastPath = container.getLastPath(last(insertedNodes));
  var lastLength = tx.get(lastPath).length;
  selection = tx.createSelection({
    type: 'property',
    path: lastPath,
    startOffset: lastLength
  });
  args.selection = selection;
  return args;
}

module.exports = paste;
<|endoftext|>


<commit_before>var util = require('util');
var BaseAdapter = require(__dirname + '/../base_adapter');

var LocalAdapter = function(fs) {
    this.fs = fs;
}

util.inherits(LocalAdapter, BaseAdapter);

/**
 * Filter files already existing in the upstream.
 *
 * @param array files
 * @return array
 * @todo implement It is just passing through for now.
 */
LocalAdapter.prototype.filterExisting = function(files) {
    return files;
};

module.exports = function(container) {
    return new LocalAdapter(container.node.fs);
};
<commit_msg>Implemented local adapter filterExisting.<commit_after>var util = require('util');
var Q = require('q');
var junk = require('junk');
var BaseAdapter = require(__dirname + '/../base_adapter');

var LocalAdapter = function(config, fs, glob, md5) {
    this.uploadPath = config.retrieve().options.uploadPath;
    this.fs = fs;
    this.glob = glob;
    this.md5 = md5;
};

/**
 * @todo abstract this.
 */
var filterJunk = function(files) {
    return files.filter(junk.not);
};

var transposeMd5 = function(files) {
    var sumPromises = [];
    files.forEach(function(file) {
        sumPromises.push(this.md5.computeFromFile(file));
    }.bind(this));
    return Q.all(sumPromises)
        .then(function(sums) {
            return files.map(function(entry, i) {
                return {
                    name: entry,
                    hash: sums[i]
                };
            });
        });
};

util.inherits(LocalAdapter, BaseAdapter);

/**
 * Filter files already existing in the upstream.
 *
 * @param array files
 * @return array
 */
LocalAdapter.prototype.filterExisting = function(files) {
    var uploadPath = this.uploadPath;
    return Q.nfcall(this.glob, uploadPath + '/**/*', {nodir: true})
        .then(filterJunk)
        .then(transposeMd5.bind(this))
        .then(function(entries) {
            return files.filter(function(file) {
                return !entries.some(function(entry) {
                    return entry.name.substr(uploadPath.length + 1) === file.name && entry.hash === file.hash;
                });
            });
        });
};

module.exports = function(container) {
    return new LocalAdapter(
        container.config,
        container.node.fs,
        container.glob,
        container.md5
    );
};
<|endoftext|>