From 125ab0ef329155c06aeeb7bfecd4c5e6f75aecdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kwa=C5=9Bniak?= Date: Mon, 1 May 2017 15:54:50 +0200 Subject: [PATCH] Refactor package (#31) * Refactor package * Upgrade packages * Fix tests * Upgrade qunit --- .bowerrc | 4 -- .eslintrc.js | 2 +- .travis.yml | 8 +-- .../mixins/{initials/index.js => initials.js} | 10 ++-- addon/mixins/initials/-private/generators.js | 59 ------------------- addon/services/ember-initials-store.js | 27 +++++++++ addon/services/initials-store.js | 20 ------- .../utils.js => utils/color-index.js} | 14 +++-- addon/utils/generators/base.js | 23 ++++++++ addon/utils/generators/svg.js | 45 ++++++++++++++ addon/utils/initials.js | 20 +++++++ app/services/ember-initials-store.js | 1 + app/services/ember-initials/initials-store.js | 1 - bower.json | 3 - index.js | 4 +- package.json | 24 ++++---- tests/test-helper.js | 2 + tests/unit/generators-test.js | 32 ---------- .../services/ember-initials-store-test.js | 34 +++++++++++ tests/unit/utils/color-index-test.js | 9 +++ tests/unit/utils/initials-test.js | 32 ++++++++++ .../shims/md5/md5-fastboot.js | 0 vendor/{ember-initials => }/shims/md5/md5.js | 0 .../shims/object-hash/object-hash-fastboot.js | 0 .../shims/object-hash/object-hash.js | 0 25 files changed, 223 insertions(+), 151 deletions(-) delete mode 100644 .bowerrc rename addon/mixins/{initials/index.js => initials.js} (89%) delete mode 100644 addon/mixins/initials/-private/generators.js create mode 100644 addon/services/ember-initials-store.js delete mode 100644 addon/services/initials-store.js rename addon/{mixins/initials/-private/utils.js => utils/color-index.js} (78%) create mode 100644 addon/utils/generators/base.js create mode 100644 addon/utils/generators/svg.js create mode 100644 addon/utils/initials.js create mode 100644 app/services/ember-initials-store.js delete mode 100644 app/services/ember-initials/initials-store.js delete mode 100644 bower.json delete mode 100644 tests/unit/generators-test.js create mode 100644 tests/unit/services/ember-initials-store-test.js create mode 100644 tests/unit/utils/color-index-test.js create mode 100644 tests/unit/utils/initials-test.js rename vendor/{ember-initials => }/shims/md5/md5-fastboot.js (100%) rename vendor/{ember-initials => }/shims/md5/md5.js (100%) rename vendor/{ember-initials => }/shims/object-hash/object-hash-fastboot.js (100%) rename vendor/{ember-initials => }/shims/object-hash/object-hash.js (100%) diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 959e169..0000000 --- a/.bowerrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "directory": "bower_components", - "analytics": false -} diff --git a/.eslintrc.js b/.eslintrc.js index 3f9c24a..ac4c402 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { root: true, parserOptions: { - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'module' }, extends: 'eslint:recommended', diff --git a/.travis.yml b/.travis.yml index f2a44f8..5cb8e15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ sudo: false cache: directories: - $HOME/.npm - - $HOME/.cache # includes bowers cache env: # we recommend testing LTS's and latest stable release (bonus points to beta/canary) @@ -25,14 +24,11 @@ matrix: before_install: - npm config set spin false - - npm install -g bower - - bower --version - - npm install phantomjs-prebuilt - - node_modules/phantomjs-prebuilt/bin/phantomjs --version + - npm install -g phantomjs-prebuilt + - phantomjs --version install: - npm install - - bower install script: # Usually, it's ok to finish the test scenario without reverting diff --git a/addon/mixins/initials/index.js b/addon/mixins/initials.js similarity index 89% rename from addon/mixins/initials/index.js rename to addon/mixins/initials.js index b678572..959c060 100644 --- a/addon/mixins/initials/index.js +++ b/addon/mixins/initials.js @@ -1,12 +1,12 @@ import Ember from 'ember'; -import { colorIndex } from './-private/utils'; -import { generateInitials } from './-private/generators'; +import ColorIndex from '../utils/color-index'; +import Initials from '../utils/initials'; export default Ember.Mixin.create({ tagName: 'img', attributeBindings: ['width', 'height', 'src', 'onError'], - initialsStore: Ember.inject.service('ember-initials/initials-store'), + initialsStore: Ember.inject.service('ember-initials-store'), defaultName: '?', defaultBackground: '#dd6a58', @@ -47,7 +47,7 @@ export default Ember.Mixin.create({ if (this.get('seedText') === this.get('defaultName')) { return this.get('defaultBackground'); } else { - let index = colorIndex(this.get('seedText'), this.get('colors.length')); + let index = ColorIndex(this.get('seedText'), this.get('colors.length')); return this.get('colors')[index]; } }), @@ -80,7 +80,7 @@ export default Ember.Mixin.create({ return { width: 100, height: 100, - initials: generateInitials(this.get('name') || this.get('defaultName')), + initials: Initials(this.get('name') || this.get('defaultName')), initialsColor: this.get('textColor'), textStyles: Ember.assign(this._textStyles(), this.get('textStyles')), backgroundStyles: Ember.assign(this._backgroundStyles(), this.get('backgroundStyles')), diff --git a/addon/mixins/initials/-private/generators.js b/addon/mixins/initials/-private/generators.js deleted file mode 100644 index f48b085..0000000 --- a/addon/mixins/initials/-private/generators.js +++ /dev/null @@ -1,59 +0,0 @@ -import Ember from 'ember'; - -function _generateElement(name, styles = {}, attrs = {}) { - return Ember.$(name).attr(attrs).css(styles); -} - -function generateTextElement(text, color, styles = {}) { - return _generateElement('', styles, { - y: '50%', - x: '50%', - dy: '0.35em', - 'text-anchor': 'middle', - 'pointer-events': 'auto', - fill: color, - }).html(text); -} - -function generateSvgElement(width, height, styles = {}) { - return _generateElement('', styles, { - width, - height, - xmlns: 'http://www.w3.org/2000/svg', - 'pointer-events': 'none', - 'viewBox': '0 0 100 100' - }); -} - -function capitalizedFirstLetter(word) { - return word ? word[0].toUpperCase() : ''; -} - -export function revokeImage(url) { - URL.revokeObjectURL(url); -} - -export function generateImage(properties) { - let textElement = generateTextElement(properties.initials, properties.initialsColor, properties.textStyles); - let svgElement = generateSvgElement(properties.width, properties.height, properties.backgroundStyles); - - svgElement.append(textElement); - let finalElement = Ember.$('
').append(svgElement); - let blob = new Blob([finalElement.html()], { type: "image/svg+xml" }); - return URL.createObjectURL(blob); -} - -export function generateInitials(name) { - let initials = name ? name.trim() : ''; - let letters = initials.split(' '); - - if (letters.length > 1) { - let first = capitalizedFirstLetter(letters.shift()); - let last = capitalizedFirstLetter(letters.pop()); - initials = first + last; - } else if (letters.length === 1) { - initials = capitalizedFirstLetter(letters.shift()); - } - - return initials; -} diff --git a/addon/services/ember-initials-store.js b/addon/services/ember-initials-store.js new file mode 100644 index 0000000..0c4aec7 --- /dev/null +++ b/addon/services/ember-initials-store.js @@ -0,0 +1,27 @@ +import Ember from 'ember'; +import hash from 'object-hash'; +import SvgGenerator from '../utils/generators/svg'; + +const { computed, Service } = Ember; + +export default Service.extend({ + initials: {}, + + generator: computed(function() { + return new SvgGenerator; + }), + + removeAll() { + Object.keys(this.get(`initials`)).forEach((key) => this.get('generator').revoke(key)) + this.set('initials', {}); + }, + + initialsFor(properties) { + let key = hash(properties); + return this.get(`initials`)[key] || this._create(key, properties); + }, + + _create(key, properties) { + return this.get('initials')[key] = this.get('generator').generate(properties); + } +}); diff --git a/addon/services/initials-store.js b/addon/services/initials-store.js deleted file mode 100644 index a2cdf26..0000000 --- a/addon/services/initials-store.js +++ /dev/null @@ -1,20 +0,0 @@ -import Ember from 'ember'; -import hash from 'object-hash'; -import { generateImage } from '../mixins/initials/-private/generators'; - -export default Ember.Service.extend({ - initials: {}, - - removeCache() { - this.set('initials', {}); - }, - - initialsFor(properties) { - let key = hash(properties); - return this.get(`initials`)[key] || this._create(key, properties); - }, - - _create(key, properties) { - return this.get('initials')[key] = generateImage(properties); - } -}); diff --git a/addon/mixins/initials/-private/utils.js b/addon/utils/color-index.js similarity index 78% rename from addon/mixins/initials/-private/utils.js rename to addon/utils/color-index.js index ed84e03..c7180f2 100644 --- a/addon/mixins/initials/-private/utils.js +++ b/addon/utils/color-index.js @@ -1,4 +1,11 @@ -export function hashCode(string) { +export default function (seedText, colorsLength) { + let code = hashCode(seedText); + return Math.abs(Math.floor(code % colorsLength)); +} + +// Private + +function hashCode(string) { let hash = 0; if (string.length === 0) return hash; @@ -11,8 +18,3 @@ export function hashCode(string) { return hash; } - -export function colorIndex(seedText, colorsLength) { - let code = hashCode(seedText); - return Math.abs(Math.floor(code % colorsLength)); -} diff --git a/addon/utils/generators/base.js b/addon/utils/generators/base.js new file mode 100644 index 0000000..6a1251a --- /dev/null +++ b/addon/utils/generators/base.js @@ -0,0 +1,23 @@ +// This is an Initials Image Generator Interface +// You have to implement these methods if you want to create your own generator + +// revoke(url) { +// should revoke image from browser cache +// } + +// generate(properties) { +// should return generated image url +// } + +export default class { + constructor() { + this._implement(this.revoke, 'revoke'); + this._implement(this.generate, 'generate'); + } + + _implement(fn, name) { + if (typeof fn !== "function" || fn.length !== 1) { + throw `Base Generator: '${name}' function has to be implemented with exactly one argument!` + } + } +} diff --git a/addon/utils/generators/svg.js b/addon/utils/generators/svg.js new file mode 100644 index 0000000..a850dcb --- /dev/null +++ b/addon/utils/generators/svg.js @@ -0,0 +1,45 @@ +import Ember from 'ember'; +import Base from './base'; + +export default class extends Base { + revoke(url) { + URL.revokeObjectURL(url); + } + + generate(properties) { + let textElement = this._generateTextElement(properties.initials, properties.initialsColor, properties.textStyles); + let svgElement = this._generateSvgElement(properties.width, properties.height, properties.backgroundStyles); + + svgElement.append(textElement); + let finalElement = Ember.$('
').append(svgElement); + let blob = new Blob([finalElement.html()], { type: "image/svg+xml" }); + return URL.createObjectURL(blob); + } + + // Private + + _generateTextElement(text, color, styles = {}) { + return this._generateElement('', styles, { + y: '50%', + x: '50%', + dy: '0.35em', + 'text-anchor': 'middle', + 'pointer-events': 'auto', + fill: color, + }).html(text); + } + + _generateElement(name, styles = {}, attrs = {}) { + return Ember.$(name).attr(attrs).css(styles); + } + + _generateSvgElement(width, height, styles = {}) { + return this._generateElement('', styles, { + width, + height, + xmlns: 'http://www.w3.org/2000/svg', + 'pointer-events': 'none', + 'viewBox': '0 0 100 100' + }); + } +} diff --git a/addon/utils/initials.js b/addon/utils/initials.js new file mode 100644 index 0000000..d4287cb --- /dev/null +++ b/addon/utils/initials.js @@ -0,0 +1,20 @@ +export default function(name) { + let initials = name ? name.trim() : ''; + let letters = initials.split(' '); + + if (letters.length > 1) { + let first = capitalizedFirstLetter(letters.shift()); + let last = capitalizedFirstLetter(letters.pop()); + initials = first + last; + } else if (letters.length === 1) { + initials = capitalizedFirstLetter(letters.shift()); + } + + return initials; +} + +// Private + +function capitalizedFirstLetter(word) { + return word ? word[0].toUpperCase() : ''; +} diff --git a/app/services/ember-initials-store.js b/app/services/ember-initials-store.js new file mode 100644 index 0000000..d9f181b --- /dev/null +++ b/app/services/ember-initials-store.js @@ -0,0 +1 @@ +export { default } from 'ember-initials/services/ember-initials-store'; diff --git a/app/services/ember-initials/initials-store.js b/app/services/ember-initials/initials-store.js deleted file mode 100644 index cd59d8d..0000000 --- a/app/services/ember-initials/initials-store.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'ember-initials/services/initials-store'; diff --git a/bower.json b/bower.json deleted file mode 100644 index a0a1834..0000000 --- a/bower.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "ember-initials" -} diff --git a/index.js b/index.js index 12e4ec3..fc6a8b8 100644 --- a/index.js +++ b/index.js @@ -12,12 +12,12 @@ module.exports = { this._super.included(app); app.import('vendor/ember-initials/md5.js'); - app.import('vendor/ember-initials/shims/md5/' + shimFor('md5'), { + app.import('vendor/shims/md5/' + shimFor('md5'), { type: 'vendor' }); app.import('vendor/ember-initials/object_hash.js'); - app.import('vendor/ember-initials/shims/object-hash/' + shimFor('object-hash'), { + app.import('vendor/shims/object-hash/' + shimFor('object-hash'), { type: 'vendor' }); }, diff --git a/package.json b/package.json index 6320e74..a4fdf31 100644 --- a/package.json +++ b/package.json @@ -34,22 +34,22 @@ "devDependencies": { "bootstrap-sass": "^3.3.7", "broccoli-asset-rev": "2.5.0", - "ember-ajax": "2.5.6", - "ember-bootstrap": "1.0.0-alpha.9", - "ember-cli": "2.12.1", + "ember-ajax": "^3.0.0", + "ember-bootstrap": "1.0.0-alpha.12", + "ember-cli": "2.13.0", "ember-cli-app-version": "3.0.0", "ember-cli-dependency-checker": "^1.3.0", "ember-cli-eslint": "^3.0.0", - "ember-cli-fastboot": "1.0.0-beta.16", + "ember-cli-fastboot": "1.0.0-beta.18", "ember-cli-favicon": "1.0.0-beta.4", "ember-cli-github-pages": "0.1.2", "ember-cli-htmlbars": "^1.1.1", - "ember-cli-htmlbars-inline-precompile": "^0.3.6", + "ember-cli-htmlbars-inline-precompile": "^0.4.0", "ember-cli-inject-live-reload": "^1.4.1", - "ember-cli-qunit": "^3.1.0", + "ember-cli-qunit": "^4.0.0", "ember-cli-release": "^1.0.0-beta.2", - "ember-cli-sass": "6.1.2", - "ember-cli-shims": "^1.0.2", + "ember-cli-sass": "6.1.3", + "ember-cli-shims": "^1.1.0", "ember-cli-sri": "^2.1.0", "ember-cli-test-loader": "^2.1.0", "ember-cli-uglify": "^1.2.0", @@ -60,14 +60,14 @@ "ember-load-initializers": "^1.0.0", "ember-resolver": "^4.1.0", "ember-scroll-to": "0.6.4", - "ember-source": "~2.12.0", - "loader.js": "4.2.3" + "ember-source": "~2.13.0", + "loader.js": "4.3.0" }, "dependencies": { "blueimp-md5": "^2.7.0", - "broccoli-funnel": "1.1.0", + "broccoli-funnel": "1.2.0", "broccoli-merge-trees": "2.0.0", - "ember-cli-babel": "^5.2.4", + "ember-cli-babel": "^6.1.0", "object-hash": "^1.1.8" }, "fastbootDependencies": [ diff --git a/tests/test-helper.js b/tests/test-helper.js index 6d2a75c..d4c7e83 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,4 +1,6 @@ import resolver from './helpers/resolver'; import { setResolver } from 'ember-qunit'; +import { start } from 'ember-cli-qunit'; setResolver(resolver); +start(); diff --git a/tests/unit/generators-test.js b/tests/unit/generators-test.js deleted file mode 100644 index 845182f..0000000 --- a/tests/unit/generators-test.js +++ /dev/null @@ -1,32 +0,0 @@ -import { module, test } from 'qunit'; -import { generateInitials } from 'ember-initials/mixins/initials/-private/generators'; - -module('Unit | Private | Generators'); - -test('initials generator', function(assert) { - let name; - - name = 'John Doe'; - assert.equal(generateInitials(name), 'JD'); - - name = 'Ľatin Ćhars'; - assert.equal(generateInitials(name), 'ĽĆ'); - - name = 'small letters'; - assert.equal(generateInitials(name), 'SL'); - - name = 'BIG LETTERS'; - assert.equal(generateInitials(name), 'BL'); - - name = '.@d &^*'; - assert.equal(generateInitials(name), '.&'); - - name = 'one'; - assert.equal(generateInitials(name), 'O'); - - name = 'Two'; - assert.equal(generateInitials(name), 'T'); - - name = 'ćma'; - assert.equal(generateInitials(name), 'Ć'); -}); diff --git a/tests/unit/services/ember-initials-store-test.js b/tests/unit/services/ember-initials-store-test.js new file mode 100644 index 0000000..d68a595 --- /dev/null +++ b/tests/unit/services/ember-initials-store-test.js @@ -0,0 +1,34 @@ +import { moduleFor, test } from 'ember-qunit'; +import Base from 'ember-initials/utils/generators/base'; + +moduleFor('service:ember-initials-store', 'Unit | Service | initials store'); + +test('it exists', function(assert) { + let service = this.subject(); + assert.ok(service); +}); + +test('it uses image generator', function(assert) { + let service = this.subject(); + assert.ok(service.get('generator') instanceof Base); +}); + +test('initialsFor', function(assert) { + let service = this.subject(); + service.set('initials', {}); + + let properties = { width: 100, height: 100, initials: "SC", initialsColor: "red" }; + assert.ok(service.initialsFor(properties)); + assert.equal(Object.keys(service.get('initials')).length, 1); + + assert.ok(service.initialsFor(properties)); + assert.equal(Object.keys(service.get('initials')).length, 1); +}); + +test('removeAll', function(assert) { + let service = this.subject(); + service.set('initials', {a: 1, b: 2}); + + service.removeAll(); + assert.equal(Object.keys(service.get('initials')).length, 0); +}); diff --git a/tests/unit/utils/color-index-test.js b/tests/unit/utils/color-index-test.js new file mode 100644 index 0000000..f1fc7bb --- /dev/null +++ b/tests/unit/utils/color-index-test.js @@ -0,0 +1,9 @@ +import { module, test } from 'qunit'; +import ColorIndex from 'ember-initials/utils/color-index'; + +module('Unit | Utils | Color Index'); + +test('color index', function(assert) { + let text = 'Ember Initials' + assert.equal(ColorIndex(text, 27), 6); +}); diff --git a/tests/unit/utils/initials-test.js b/tests/unit/utils/initials-test.js new file mode 100644 index 0000000..65824da --- /dev/null +++ b/tests/unit/utils/initials-test.js @@ -0,0 +1,32 @@ +import { module, test } from 'qunit'; +import Initials from 'ember-initials/utils/initials'; + +module('Unit | Utils | Initials'); + +test('initials generator', function(assert) { + let name; + + name = 'John Doe'; + assert.equal(Initials(name), 'JD'); + + name = 'Ľatin Ćhars'; + assert.equal(Initials(name), 'ĽĆ'); + + name = 'small letters'; + assert.equal(Initials(name), 'SL'); + + name = 'BIG LETTERS'; + assert.equal(Initials(name), 'BL'); + + name = '.@d &^*'; + assert.equal(Initials(name), '.&'); + + name = 'one'; + assert.equal(Initials(name), 'O'); + + name = 'Two'; + assert.equal(Initials(name), 'T'); + + name = 'ćma'; + assert.equal(Initials(name), 'Ć'); +}); diff --git a/vendor/ember-initials/shims/md5/md5-fastboot.js b/vendor/shims/md5/md5-fastboot.js similarity index 100% rename from vendor/ember-initials/shims/md5/md5-fastboot.js rename to vendor/shims/md5/md5-fastboot.js diff --git a/vendor/ember-initials/shims/md5/md5.js b/vendor/shims/md5/md5.js similarity index 100% rename from vendor/ember-initials/shims/md5/md5.js rename to vendor/shims/md5/md5.js diff --git a/vendor/ember-initials/shims/object-hash/object-hash-fastboot.js b/vendor/shims/object-hash/object-hash-fastboot.js similarity index 100% rename from vendor/ember-initials/shims/object-hash/object-hash-fastboot.js rename to vendor/shims/object-hash/object-hash-fastboot.js diff --git a/vendor/ember-initials/shims/object-hash/object-hash.js b/vendor/shims/object-hash/object-hash.js similarity index 100% rename from vendor/ember-initials/shims/object-hash/object-hash.js rename to vendor/shims/object-hash/object-hash.js