From 57c4a285d8935e040611a156b36fb6e29df5bea7 Mon Sep 17 00:00:00 2001 From: Benedict Aas Date: Thu, 29 Mar 2018 13:27:26 +0100 Subject: [PATCH] refactor: inline middle-ellipsis package as util We remove our dependency on the `middle-ellipses` package and include and expose the function in `lib/shared/utils`, alongside the regular Angular filter it exposes. This allows use of the middle ellipsis method in React. Change-Type: patch Changelog-Entry: Inline middle-ellipsis package as util. --- lib/gui/app/pages/main/main.js | 4 +- .../app/pages/main/templates/main.tpl.html | 6 +- lib/gui/app/utils/middle-ellipsis.js | 67 +++++++++++++++++++ lib/gui/app/utils/middle-ellipsis/filter.js | 39 +++++++++++ npm-shrinkwrap.json | 4 -- package.json | 1 - tests/gui/utils/middle-ellipsis.spec.js | 46 +++++++++++++ 7 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 lib/gui/app/utils/middle-ellipsis.js create mode 100644 lib/gui/app/utils/middle-ellipsis/filter.js create mode 100644 tests/gui/utils/middle-ellipsis.spec.js diff --git a/lib/gui/app/pages/main/main.js b/lib/gui/app/pages/main/main.js index 9aeba0f8..2d6ec4c9 100644 --- a/lib/gui/app/pages/main/main.js +++ b/lib/gui/app/pages/main/main.js @@ -31,7 +31,6 @@ const MainPage = angular.module(MODULE_NAME, [ 'angularMoment', require('angular-ui-router'), - require('angular-middle-ellipses'), require('angular-seconds-to-date'), require('../../components/drive-selector/drive-selector'), @@ -42,7 +41,8 @@ const MainPage = angular.module(MODULE_NAME, [ require('../../os/open-external/open-external'), require('../../os/dropzone/dropzone'), - require('../../utils/byte-size/byte-size') + require('../../utils/byte-size/byte-size'), + require('../../utils/middle-ellipsis/filter') ]) MainPage.controller('MainController', require('./controllers/main')) diff --git a/lib/gui/app/pages/main/templates/main.tpl.html b/lib/gui/app/pages/main/templates/main.tpl.html index 7b08b2e5..3f6e5959 100644 --- a/lib/gui/app/pages/main/templates/main.tpl.html +++ b/lib/gui/app/pages/main/templates/main.tpl.html @@ -24,7 +24,7 @@ {{ main.selection.getImageSize() | closestUnit }} @@ -67,8 +67,8 @@ }"> - - {{ drive.getDrivesTitle() | middleEllipses:20 }} + + {{ drive.getDrivesTitle() | middleEllipsis:20 }} {{ main.selection.getCurrentDrive().size | closestUnit }} 'My\u2026ng' + */ +module.exports = (input, limit) => { + const MIDDLE_ELLIPSIS_CHARACTER = '\u2026' + const MINIMUM_LENGTH = 3 + + // We can't provide a 100% expected result if the limit is less than 3. For example: + // + // If the limit == 2: + // Should we display the first at last character without an ellipses in the middle? + // Should we display just one character and an ellipses before or after? + // Should we display nothing at all? + // + // If the limit == 1: + // Should we display just one character? + // Should we display just an ellipses? + // Should we display nothing at all? + // + // Etc. + if (limit < MINIMUM_LENGTH) { + throw new Error('middleEllipsis: Limit should be at least 3') + } + + // Do nothing, the string doesn't need truncation. + if (input.length <= limit) { + return input + } + + /* eslint-disable no-magic-numbers */ + const lengthOfTheSidesAfterTruncation = Math.floor((limit - 1) / 2) + const finalLeftPart = input.slice(0, lengthOfTheSidesAfterTruncation) + const finalRightPart = input.slice(input.length - lengthOfTheSidesAfterTruncation) + /* eslint-enable no-magic-numbers */ + + return finalLeftPart + MIDDLE_ELLIPSIS_CHARACTER + finalRightPart +} diff --git a/lib/gui/app/utils/middle-ellipsis/filter.js b/lib/gui/app/utils/middle-ellipsis/filter.js new file mode 100644 index 00000000..8e106ff2 --- /dev/null +++ b/lib/gui/app/utils/middle-ellipsis/filter.js @@ -0,0 +1,39 @@ +/* + * Copyright 2018 resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict' + +/** + * The purpose of this module is to provide utilities + * to work with sizes in bytes. + * + * @module Etcher.Utils.MiddleEllipsis + */ + +const _ = require('lodash') +const angular = require('angular') +const middleEllipsis = require('../middle-ellipsis') + +const MODULE_NAME = 'Etcher.Utils.MiddleEllipsis' +const MiddleEllipsis = angular.module(MODULE_NAME, []) + +/* eslint-disable lodash/prefer-lodash-method */ + +MiddleEllipsis.filter('middleEllipsis', _.constant(middleEllipsis)) + +/* eslint-enable lodash/prefer-lodash-method */ + +module.exports = MODULE_NAME diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 574d3c81..ccdf405b 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -120,10 +120,6 @@ } } }, - "angular-middle-ellipses": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/angular-middle-ellipses/-/angular-middle-ellipses-1.0.0.tgz" - }, "angular-mocks": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.6.3.tgz", diff --git a/package.json b/package.json index f431ebe9..e94f0415 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "dependencies": { "angular": "1.6.3", "angular-if-state": "1.0.0", - "angular-middle-ellipses": "1.0.0", "angular-moment": "1.0.1", "angular-seconds-to-date": "1.0.0", "angular-ui-bootstrap": "2.5.0", diff --git a/tests/gui/utils/middle-ellipsis.spec.js b/tests/gui/utils/middle-ellipsis.spec.js new file mode 100644 index 00000000..5df0af41 --- /dev/null +++ b/tests/gui/utils/middle-ellipsis.spec.js @@ -0,0 +1,46 @@ + +/* + * Copyright 2018 resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict' + +const m = require('mochainon') +const middleEllipsis = require('../../../lib/gui/app/utils/middle-ellipsis') +console.log(middleEllipsis) + +describe('Browser: MiddleEllipsis', function () { + describe('.middleEllipsis()', function () { + it('should throw error if limit < 3', function () { + m.chai.expect(() => { + middleEllipsis('No', 2) + }).to.throw('middleEllipsis: Limit should be at least 3') + }) + + describe('given the input length is greater than the limit', function () { + it('should always truncate input to an odd length', function () { + const alphabet = 'abcdefghijklmnopqrstuvwxyz' + m.chai.expect(middleEllipsis(alphabet, 3)).to.have.a.lengthOf(3) + m.chai.expect(middleEllipsis(alphabet, 4)).to.have.a.lengthOf(3) + m.chai.expect(middleEllipsis(alphabet, 5)).to.have.a.lengthOf(5) + m.chai.expect(middleEllipsis(alphabet, 6)).to.have.a.lengthOf(5) + }) + }) + + it('should return the input if it is within the bounds of limit', function () { + m.chai.expect(middleEllipsis('Hello', 10)).to.equal('Hello') + }) + }) +})