UNPKG

@meanie/angular-convert

Version:

An Angular service with various conversion helpers

385 lines (330 loc) 9.82 kB
/** * @meanie/angular-convert * https://github.com/meanie/angular-convert * * Copyright (c) 2020 Adam Reis <adam@reis.nz> * License: MIT */ (function (window, angular, undefined) { 'use strict'; /** * Module definition and dependencies */ angular.module('Convert.Service', ['Convert.StringConverter.Service', 'Convert.ObjectConverter.Service', 'Convert.QueryStringConverter.Service']) /** * Factory definition */ .factory('$convert', ['$stringConverter', '$objectConverter', '$queryStringConverter', function ($stringConverter, $objectConverter, $queryStringConverter) { return { string: $stringConverter, object: $objectConverter, queryString: $queryStringConverter }; }]); })(window, window.angular); (function (window, angular, undefined) { 'use strict'; /** * Module definition and dependencies */ angular.module('Convert.ObjectConverter.Service', ['Convert.StringConverter.Service']) /** * Factory definition */ .factory('$objectConverter', ['$stringConverter', function ($stringConverter) { /** * Helper to convert object keys using a specified string converter */ function convertObjectKeys(obj, converter) { //Must have object if (!angular.isObject(obj)) { throw new TypeError('Not an object'); } //Validate case if (typeof $stringConverter[converter] === 'undefined') { throw new Error('Invalid converter: ' + converter); } //Initialize object var newObj = {}; //Loop keys for (var key in obj) { if (obj.hasOwnProperty(key)) { var newKey = $stringConverter[converter](key); newObj[newKey] = angular.copy(obj[key]); } } //Return object return newObj; } /** * Object converter */ return { /** * Convert object keys to snake case */ keysToSnakeCase: function keysToSnakeCase(obj) { return convertObjectKeys(obj, 'toSnakeCase'); }, /** * Convert object keys to snake case */ keysToCamelCase: function keysToCamelCase(obj) { return convertObjectKeys(obj, 'toCamelCase'); } }; }]); })(window, window.angular); (function (window, angular, undefined) { 'use strict'; /** * Module definition and dependencies */ angular.module('Convert.QueryStringConverter.Service', ['Convert.StringConverter.Service']) /** * Factory definition */ .factory('$queryStringConverter', ['$stringConverter', function ($stringConverter) { /** * Tries to decode an URI component without throwing an exception */ function tryDecodeURIComponent(str) { try { return decodeURIComponent(str); } catch (e) { //Fall through } } /** * Tries to encode an URI component without throwing an exception */ function tryEncodeURIComponent(str, pctEncodeSpaces) { try { return encodeURIComponent(str).replace(/%40/g, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, pctEncodeSpaces ? '%20' : '+'); } catch (e) { //Fall through } } /** * Converts a string to a specific case */ function convertToCase(str, convertCase) { switch (convertCase) { case 'snake': return $stringConverter.toSnakeCase(str); case 'camel': return $stringConverter.toCamelCase(str); } return str; } /** * Query string converter */ return { /** * Parses an escaped url query string into key-value pairs */ toObject: function toObject(s, convertCase) { var obj = {}; var kv = void 0, key = void 0, val = void 0; angular.forEach((s || '').split('&'), function (s) { if (!s) { return; } //Split key/value and decode key kv = s.replace(/\+/g, '%20').split('='); key = tryDecodeURIComponent(kv[0]); //If not defined, exit if (!angular.isDefined(key)) { return; } //Convert case and get value key = convertToCase(key, convertCase); val = angular.isDefined(kv[1]) ? tryDecodeURIComponent(kv[1]) : true; //Set property if (!hasOwnProperty.call(obj, key)) { obj[key] = val; } else if (angular.isArray(obj[key])) { obj[key].push(val); } else { obj[key] = [obj[key], val]; } }); return obj; }, /** * Convert key-value pairs object to a parametrized query string */ fromObject: function fromObject(obj, convertCase) { //No obj? if (!obj || !angular.isObject(obj)) { return ''; } //Initialize parts array var parts = []; //Loop the parameters angular.forEach(obj, function (value, key) { //Skip null/undefined values if (value === null || angular.isUndefined(value)) { return; } //Convert to array if (!angular.isArray(value)) { value = [value]; } //Loop values angular.forEach(value, function (v) { //Handle objects if (angular.isObject(v)) { if (angular.isDate(v)) { v = v.toISOString(); } else { v = angular.toJson(v); } } //Convert case? switch (convertCase) { case 'snake': key = $stringConverter.toSnakeCase(key); break; case 'camel': key = $stringConverter.toCamelCase(key); break; } //Push to parts parts.push(tryEncodeURIComponent(key) + '=' + tryEncodeURIComponent(v)); }); }); //Any parts? if (parts.length > 0) { return parts.join('&'); } //No parts return ''; } }; }]); })(window, window.angular); (function (window, angular, undefined) { 'use strict'; /** * Module definition and dependencies */ angular.module('Convert.StringConverter.Service', []) /** * Factory definition */ .factory('$stringConverter', ['$window', function ($window) { return { /** * Convert string to snake case */ toSnakeCase: function toSnakeCase(str) { if (typeof str === 'number') { return String(str); } else if (typeof str !== 'string') { return ''; } if ((str = String(str).trim()) === '') { return ''; } return str.replace(/(\s*-*\b\w|[A-Z])/g, function ($1) { $1 = $1.trim().toLowerCase().replace('-', ''); return ($1[0] === '_' ? '' : '_') + $1; }).slice(1); }, /** * Convert string to camel case */ toCamelCase: function toCamelCase(str, ucfirst) { if (typeof str === 'number') { return String(str); } else if (typeof str !== 'string') { return ''; } if ((str = String(str).trim()) === '') { return ''; } return str.replace(/_+|-+/g, ' ').replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) { if (Number(match) === 0) { return ''; } return index === 0 && !ucfirst ? match.toLowerCase() : match.toUpperCase(); }); }, /** * Convert string to proper case */ toProperCase: function toProperCase(str) { if (typeof str === 'number') { return String(str); } else if (typeof str !== 'string') { return ''; } if ((str = String(str).trim()) === '') { return ''; } return str.replace(/\b\w+/g, function (match) { return match.charAt(0).toUpperCase() + match.substr(1).toLowerCase(); }).replace(/['’”‘“][A-Z]{1}\b/g, function (match) { return match.toLowerCase(); }); }, /** * Dasherize a string */ toDasherized: function toDasherized(str) { if (typeof str === 'number') { return String(str); } else if (typeof str !== 'string') { return ''; } if ((str = String(str).trim()) === '') { return ''; } str = str.replace(/\s\(/, '-('); return str.replace(/(\s*-*\b\w|[A-Z]|_[a-z])/g, function ($1) { $1 = $1.replace('_', '-').trim().toLowerCase(); return ($1[0] === '-' ? '' : '-') + $1; }).slice(1).replace(/\(-/, '('); }, /** * Make the first letter of a string uppercase */ toUcFirst: function toUcFirst(str) { if (typeof str !== 'string' && typeof str !== 'number') { return ''; } str = String(str).trim(); if (str === '') { return ''; } return str[0].toUpperCase() + str.substr(1); }, /** * Base 64 decode URL string */ fromBase64: function fromBase64(str) { var o = str.replace('-', '+').replace('_', '/'); switch (o.length % 4) { case 0: break; case 2: o += '=='; break; case 3: o += '='; break; default: throw 'Illegal base64 url string'; } try { return decodeURIComponent($window.atob(o)); } catch (e) { //Fall through } } }; }]); })(window, window.angular);