diff --git a/package.json b/package.json index 33fa21a..78f09a2 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,5 @@ "scripts": { "build": "gulp", "test": "node test/index" - }, - "dependencies": { - "shaven": "1.3.0" } } diff --git a/src/lib/renderers/svg-text.js b/src/lib/renderers/svg-text.js index d8450d7..7bde6ba 100644 --- a/src/lib/renderers/svg-text.js +++ b/src/lib/renderers/svg-text.js @@ -1,4 +1,4 @@ -var shaven = require('shaven').default; +var shaven = require('../vendor/shaven').default; var SVG = require('../svg'); var constants = require('../constants'); diff --git a/src/lib/vendor/shaven/buildTransformString.js b/src/lib/vendor/shaven/buildTransformString.js new file mode 100644 index 0000000..22994dc --- /dev/null +++ b/src/lib/vendor/shaven/buildTransformString.js @@ -0,0 +1,22 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +// Create transform string from list transform objects + +exports.default = function (transformObjects) { + + return transformObjects.map(function (transformation) { + var values = []; + + if (transformation.type === 'rotate' && transformation.degrees) { + values.push(transformation.degrees); + } + if (transformation.x) values.push(transformation.x); + if (transformation.y) values.push(transformation.y); + + return transformation.type + '(' + values + ')'; + }).join(' '); +}; \ No newline at end of file diff --git a/src/lib/vendor/shaven/defaults.js b/src/lib/vendor/shaven/defaults.js new file mode 100644 index 0000000..7cf0a8e --- /dev/null +++ b/src/lib/vendor/shaven/defaults.js @@ -0,0 +1,13 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = { + namespace: 'xhtml', + autoNamespacing: true, + escapeHTML: true, + quotationMark: '"', + quoteAttributes: true, + convertTransformArray: true +}; \ No newline at end of file diff --git a/src/lib/vendor/shaven/escape.js b/src/lib/vendor/shaven/escape.js new file mode 100644 index 0000000..bc91b19 --- /dev/null +++ b/src/lib/vendor/shaven/escape.js @@ -0,0 +1,14 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.attribute = attribute; +exports.HTML = HTML; +function attribute(string) { + return string || string === 0 ? String(string).replace(/&/g, '&').replace(/"/g, '"') : ''; +} + +function HTML(string) { + return String(string).replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(//g, '>'); +} \ No newline at end of file diff --git a/src/lib/vendor/shaven/index.js b/src/lib/vendor/shaven/index.js new file mode 100644 index 0000000..119671c --- /dev/null +++ b/src/lib/vendor/shaven/index.js @@ -0,0 +1,2 @@ +// vendored shaven 1.3.0 due to published package.json including an outdated node engine +module.exports = require('./server'); diff --git a/src/lib/vendor/shaven/mapAttributeValue.js b/src/lib/vendor/shaven/mapAttributeValue.js new file mode 100644 index 0000000..1f18432 --- /dev/null +++ b/src/lib/vendor/shaven/mapAttributeValue.js @@ -0,0 +1,33 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _buildTransformString = require('./buildTransformString'); + +var _buildTransformString2 = _interopRequireDefault(_buildTransformString); + +var _stringifyStyleObject = require('./stringifyStyleObject'); + +var _stringifyStyleObject2 = _interopRequireDefault(_stringifyStyleObject); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (key, value) { + if (value === undefined) { + return ''; + } + + if (key === 'style' && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') { + return (0, _stringifyStyleObject2.default)(value); + } + + if (key === 'transform' && Array.isArray(value)) { + return (0, _buildTransformString2.default)(value); + } + + return value; +}; \ No newline at end of file diff --git a/src/lib/vendor/shaven/parseSugarString.js b/src/lib/vendor/shaven/parseSugarString.js new file mode 100644 index 0000000..ab9c5d0 --- /dev/null +++ b/src/lib/vendor/shaven/parseSugarString.js @@ -0,0 +1,29 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (sugarString) { + var tags = sugarString.match(/^[\w-]+/); + var properties = { + tag: tags ? tags[0] : 'div' + }; + var ids = sugarString.match(/#([\w-]+)/); + var classes = sugarString.match(/\.[\w-]+/g); + var references = sugarString.match(/\$([\w-]+)/); + + if (ids) properties.id = ids[1]; + + if (classes) { + properties.class = classes.join(' ').replace(/\./g, ''); + } + + if (references) properties.reference = references[1]; + + if (sugarString.endsWith('&') || sugarString.endsWith('!')) { + properties.escapeHTML = false; + } + + return properties; +}; \ No newline at end of file diff --git a/src/lib/vendor/shaven/server.js b/src/lib/vendor/shaven/server.js new file mode 100644 index 0000000..600166b --- /dev/null +++ b/src/lib/vendor/shaven/server.js @@ -0,0 +1,215 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +exports.default = shaven; + +var _parseSugarString = require('./parseSugarString'); + +var _parseSugarString2 = _interopRequireDefault(_parseSugarString); + +var _escape = require('./escape'); + +var escape = _interopRequireWildcard(_escape); + +var _defaults = require('./defaults'); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _mapAttributeValue = require('./mapAttributeValue'); + +var _mapAttributeValue2 = _interopRequireDefault(_mapAttributeValue); + +var _assert = require('assert'); + +var _assert2 = _interopRequireDefault(_assert); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function shaven(arrayOrObject) { + var isArray = Array.isArray(arrayOrObject); + var objType = typeof arrayOrObject === 'undefined' ? 'undefined' : _typeof(arrayOrObject); + + if (!isArray && objType !== 'object') { + throw new Error('Argument must be either an array or an object ' + 'and not ' + JSON.stringify(arrayOrObject)); + } + + if (isArray && arrayOrObject.length === 0) { + // Ignore empty arrays + return {}; + } + + var config = {}; + var elementArray = []; + + if (Array.isArray(arrayOrObject)) { + elementArray = arrayOrObject.slice(0); + } else { + elementArray = arrayOrObject.elementArray.slice(0); + config = Object.assign(config, arrayOrObject); + delete config.elementArray; + } + + config = Object.assign({}, _defaults2.default, config, { + returnObject: { // Shaven object to return at last + ids: {}, + references: {} + } + }); + + function createElement(sugarString) { + var properties = (0, _parseSugarString2.default)(sugarString); + var element = { + tag: properties.tag, + attr: {}, + children: [] + }; + + if (properties.id) { + element.attr.id = properties.id; + (0, _assert2.default)(!config.returnObject.ids.hasOwnProperty(properties.id), 'Ids must be unique and "' + properties.id + '" is already assigned'); + config.returnObject.ids[properties.id] = element; + } + if (properties.class) { + element.attr.class = properties.class; + } + if (properties.reference) { + (0, _assert2.default)(!config.returnObject.ids.hasOwnProperty(properties.reference), 'References must be unique and "' + properties.id + '" is already assigned'); + config.returnObject.references[properties.reference] = element; + } + + config.escapeHTML = properties.escapeHTML != null ? properties.escapeHTML : config.escapeHTML; + + return element; + } + + function buildDom(elemArray) { + if (Array.isArray(elemArray) && elemArray.length === 0) { + // Ignore empty arrays + return {}; + } + + var index = 1; + var createdCallback = void 0; + var selfClosingHTMLTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; + // Clone to avoid mutation problems + var array = elemArray.slice(0); + + if (typeof array[0] === 'string') { + array[0] = createElement(array[0]); + } else if (Array.isArray(array[0])) { + index = 0; + } else { + throw new Error('First element of array must be a string, ' + 'or an array and not ' + JSON.stringify(array[0])); + } + + for (; index < array.length; index++) { + + // Don't render element if value is false or null + if (array[index] === false || array[index] === null) { + array[0] = false; + break; + } + + // Continue with next array value if current value is undefined or true + else if (array[index] === undefined || array[index] === true) { + continue; + } else if (typeof array[index] === 'string') { + if (config.escapeHTML) { + // eslint-disable-next-line new-cap + array[index] = escape.HTML(array[index]); + } + + array[0].children.push(array[index]); + } else if (typeof array[index] === 'number') { + + array[0].children.push(array[index]); + } else if (Array.isArray(array[index])) { + + if (Array.isArray(array[index][0])) { + array[index].reverse().forEach(function (subArray) { + // eslint-disable-line no-loop-func + array.splice(index + 1, 0, subArray); + }); + + if (index !== 0) continue; + index++; + } + + array[index] = buildDom(array[index]); + + if (array[index][0]) { + array[0].children.push(array[index][0]); + } + } else if (typeof array[index] === 'function') { + createdCallback = array[index]; + } else if (_typeof(array[index]) === 'object') { + for (var attributeKey in array[index]) { + if (!array[index].hasOwnProperty(attributeKey)) continue; + + var attributeValue = array[index][attributeKey]; + + if (array[index].hasOwnProperty(attributeKey) && attributeValue !== null && attributeValue !== false) { + array[0].attr[attributeKey] = (0, _mapAttributeValue2.default)(attributeKey, attributeValue); + } + } + } else { + throw new TypeError('"' + array[index] + '" is not allowed as a value'); + } + } + + if (array[0] !== false) { + var HTMLString = '<' + array[0].tag; + + for (var key in array[0].attr) { + if (array[0].attr.hasOwnProperty(key)) { + var _attributeValue = escape.attribute(array[0].attr[key]); + var value = _attributeValue; + + if (config.quoteAttributes || /[ "'=<>]/.test(_attributeValue)) { + value = config.quotationMark + _attributeValue + config.quotationMark; + } + + HTMLString += ' ' + key + '=' + value; + } + } + + HTMLString += '>'; + + if (!(selfClosingHTMLTags.indexOf(array[0].tag) !== -1)) { + array[0].children.forEach(function (child) { + return HTMLString += child; + }); + + HTMLString += ''; + } + + array[0] = HTMLString; + } + + // Return root element on index 0 + config.returnObject[0] = array[0]; + config.returnObject.rootElement = array[0]; + + config.returnObject.toString = function () { + return array[0]; + }; + + if (createdCallback) createdCallback(array[0]); + + return config.returnObject; + } + + return buildDom(elementArray); +} + +shaven.setDefaults = function (object) { + Object.assign(_defaults2.default, object); + return shaven; +}; diff --git a/src/lib/vendor/shaven/stringifyStyleObject.js b/src/lib/vendor/shaven/stringifyStyleObject.js new file mode 100644 index 0000000..ea4839f --- /dev/null +++ b/src/lib/vendor/shaven/stringifyStyleObject.js @@ -0,0 +1,18 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +function sanitizeProperties(key, value) { + if (value === null || value === false || value === undefined) return; + if (typeof value === 'string' || (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') return value; + + return String(value); +} + +exports.default = function (styleObject) { + return JSON.stringify(styleObject, sanitizeProperties).slice(2, -2).replace(/","/g, ';').replace(/":"/g, ':').replace(/\\"/g, '\''); +}; \ No newline at end of file