From 020926dd895ba12a7b3182698c75bf4d18db011b Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Sat, 22 Apr 2023 11:55:20 +0800 Subject: [PATCH] =?UTF-8?q?feats:=20=E6=B7=BB=E5=8A=A0=20holder.js=20?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wwwroot/plugs/holder/holder.js | 3063 +++++++++++++++++ .../wwwroot/plugs/holder/holder.min.js | 14 + .../wwwroot/plugs/holder/holder.js | 3063 +++++++++++++++++ .../wwwroot/plugs/holder/holder.min.js | 14 + 文件下载/holder-v2.9.8.zip | Bin 0 -> 156658 bytes .../Bootstrap4/plugs/holder/holder.js | 3063 +++++++++++++++++ .../Bootstrap4/plugs/holder/holder.min.js | 14 + 静态站点/Bootstrap5/pages/test.css | 0 静态站点/Bootstrap5/pages/test.html | 25 + 静态站点/Bootstrap5/pages/test.js | 1 + .../Bootstrap5/plugs/holder/holder.js | 3063 +++++++++++++++++ .../Bootstrap5/plugs/holder/holder.min.js | 14 + 12 files changed, 12334 insertions(+) create mode 100644 BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.js create mode 100644 BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.min.js create mode 100644 BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.js create mode 100644 BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.min.js create mode 100644 文件下载/holder-v2.9.8.zip create mode 100644 静态站点/Bootstrap4/plugs/holder/holder.js create mode 100644 静态站点/Bootstrap4/plugs/holder/holder.min.js create mode 100644 静态站点/Bootstrap5/pages/test.css create mode 100644 静态站点/Bootstrap5/pages/test.html create mode 100644 静态站点/Bootstrap5/pages/test.js create mode 100644 静态站点/Bootstrap5/plugs/holder/holder.js create mode 100644 静态站点/Bootstrap5/plugs/holder/holder.min.js diff --git a/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.js b/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.js new file mode 100644 index 0000000..db1e43b --- /dev/null +++ b/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.js @@ -0,0 +1,3063 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +(function (window) { + if (!window.document) return; + var document = window.document; + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + if (!document.querySelectorAll) { + document.querySelectorAll = function (selectors) { + var style = document.createElement('style'), elements = [], element; + document.documentElement.firstChild.appendChild(style); + document._qsa = []; + + style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}'; + window.scrollBy(0, 0); + style.parentNode.removeChild(style); + + while (document._qsa.length) { + element = document._qsa.shift(); + element.style.removeAttribute('x-qsa'); + elements.push(element); + } + document._qsa = null; + return elements; + }; + } + + if (!document.querySelector) { + document.querySelector = function (selectors) { + var elements = document.querySelectorAll(selectors); + return (elements.length) ? elements[0] : null; + }; + } + + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (classNames) { + classNames = String(classNames).replace(/^|\s+/g, '.'); + return document.querySelectorAll(classNames); + }; + } + + //https://github.com/inexorabletash/polyfill + // ES5 15.2.3.14 Object.keys ( O ) + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys + if (!Object.keys) { + Object.keys = function (o) { + if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); } + var ret = [], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + ret.push(p); + } + } + return ret; + }; + } + + // ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] ) + // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun /*, thisp */) { + if (this === void 0 || this === null) { throw TypeError(); } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { throw TypeError(); } + + var thisp = arguments[1], i; + for (i = 0; i < len; i++) { + if (i in t) { + fun.call(thisp, t[i], i, t); + } + } + }; + } + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + (function (global) { + var B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + global.atob = global.atob || function (input) { + input = String(input); + var position = 0, + output = [], + buffer = 0, bits = 0, n; + + input = input.replace(/\s/g, ''); + if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); } + if ((input.length % 4) === 1) { throw Error('InvalidCharacterError'); } + if (/[^+/0-9A-Za-z]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + n = B64_ALPHABET.indexOf(input.charAt(position)); + buffer = (buffer << 6) | n; + bits += 6; + + if (bits === 24) { + output.push(String.fromCharCode((buffer >> 16) & 0xFF)); + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + bits = 0; + buffer = 0; + } + position += 1; + } + + if (bits === 12) { + buffer = buffer >> 4; + output.push(String.fromCharCode(buffer & 0xFF)); + } else if (bits === 18) { + buffer = buffer >> 2; + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + } + + return output.join(''); + }; + + global.btoa = global.btoa || function (input) { + input = String(input); + var position = 0, + out = [], + o1, o2, o3, + e1, e2, e3, e4; + + if (/[^\x00-\xFF]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + o1 = input.charCodeAt(position++); + o2 = input.charCodeAt(position++); + o3 = input.charCodeAt(position++); + + // 111111 112222 222233 333333 + e1 = o1 >> 2; + e2 = ((o1 & 0x3) << 4) | (o2 >> 4); + e3 = ((o2 & 0xf) << 2) | (o3 >> 6); + e4 = o3 & 0x3f; + + if (position === input.length + 2) { + e3 = 64; e4 = 64; + } + else if (position === input.length + 1) { + e4 = 64; + } + + out.push(B64_ALPHABET.charAt(e1), + B64_ALPHABET.charAt(e2), + B64_ALPHABET.charAt(e3), + B64_ALPHABET.charAt(e4)); + } + + return out.join(''); + }; + }(window)); + + //https://gist.github.com/jimeh/332357 + if (!Object.prototype.hasOwnProperty){ + /*jshint -W001, -W103 */ + Object.prototype.hasOwnProperty = function(prop) { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + }; + /*jshint +W001, +W103 */ + } + + // @license http://opensource.org/licenses/MIT + // copyright Paul Irish 2015 + + + // Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill + // github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js + // as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values + + // if you want values similar to what you'd get with real perf.now, place this towards the head of the page + // but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed + + + (function(){ + + if ('performance' in window === false) { + window.performance = {}; + } + + Date.now = (Date.now || function () { // thanks IE8 + return new Date().getTime(); + }); + + if ('now' in window.performance === false){ + + var nowOffset = Date.now(); + + if (performance.timing && performance.timing.navigationStart){ + nowOffset = performance.timing.navigationStart; + } + + window.performance.now = function now(){ + return Date.now() - nowOffset; + }; + } + + })(); + + //requestAnimationFrame polyfill for older Firefox/Chrome versions + if (!window.requestAnimationFrame) { + if (window.webkitRequestAnimationFrame && window.webkitCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-webkit.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return webkitRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.webkitCancelAnimationFrame; + }(window)); + } else if (window.mozRequestAnimationFrame && window.mozCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-moz.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return mozRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.mozCancelAnimationFrame; + }(window)); + } else { + (function (global) { + global.requestAnimationFrame = function (callback) { + return global.setTimeout(callback, 1000 / 60); + }; + + global.cancelAnimationFrame = global.clearTimeout; + })(window); + } + } +})(this); + +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Holder"] = factory(); + else + root["Holder"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - https://imsky.co + */ + + module.exports = __webpack_require__(1); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - http://imsky.co + */ + + //Libraries and functions + var onDomReady = __webpack_require__(2); + var querystring = __webpack_require__(3); + + var SceneGraph = __webpack_require__(6); + var utils = __webpack_require__(7); + var SVG = __webpack_require__(8); + var DOM = __webpack_require__(9); + var Color = __webpack_require__(10); + var constants = __webpack_require__(11); + + var svgRenderer = __webpack_require__(12); + var sgCanvasRenderer = __webpack_require__(15); + + var extend = utils.extend; + var dimensionCheck = utils.dimensionCheck; + + //Constants and definitions + var SVG_NS = constants.svg_ns; + + var Holder = { + version: constants.version, + + /** + * Adds a theme to default settings + * + * @param {string} name Theme name + * @param {Object} theme Theme object, with foreground, background, size, font, and fontweight properties. + */ + addTheme: function(name, theme) { + name != null && theme != null && (App.settings.themes[name] = theme); + delete App.vars.cache.themeKeys; + return this; + }, + + /** + * Appends a placeholder to an element + * + * @param {string} src Placeholder URL string + * @param el A selector or a reference to a DOM node + */ + addImage: function(src, el) { + //todo: use jquery fallback if available for all QSA references + var nodes = DOM.getNodeArray(el); + nodes.forEach(function (node) { + var img = DOM.newEl('img'); + var domProps = {}; + domProps[App.setup.dataAttr] = src; + DOM.setAttr(img, domProps); + node.appendChild(img); + }); + return this; + }, + + /** + * Sets whether or not an image is updated on resize. + * If an image is set to be updated, it is immediately rendered. + * + * @param {Object} el Image DOM element + * @param {Boolean} value Resizable update flag value + */ + setResizeUpdate: function(el, value) { + if (el.holderData) { + el.holderData.resizeUpdate = !!value; + if (el.holderData.resizeUpdate) { + updateResizableElements(el); + } + } + }, + + /** + * Runs Holder with options. By default runs Holder on all images with "holder.js" in their source attributes. + * + * @param {Object} userOptions Options object, can contain domain, themes, images, and bgnodes properties + */ + run: function(userOptions) { + //todo: split processing into separate queues + userOptions = userOptions || {}; + var engineSettings = {}; + var options = extend(App.settings, userOptions); + + App.vars.preempted = true; + App.vars.dataAttr = options.dataAttr || App.setup.dataAttr; + + engineSettings.renderer = options.renderer ? options.renderer : App.setup.renderer; + if (App.setup.renderers.join(',').indexOf(engineSettings.renderer) === -1) { + engineSettings.renderer = App.setup.supportsSVG ? 'svg' : (App.setup.supportsCanvas ? 'canvas' : 'html'); + } + + var images = DOM.getNodeArray(options.images); + var bgnodes = DOM.getNodeArray(options.bgnodes); + var stylenodes = DOM.getNodeArray(options.stylenodes); + var objects = DOM.getNodeArray(options.objects); + + engineSettings.stylesheets = []; + engineSettings.svgXMLStylesheet = true; + engineSettings.noFontFallback = !!options.noFontFallback; + engineSettings.noBackgroundSize = !!options.noBackgroundSize; + + stylenodes.forEach(function (styleNode) { + if (styleNode.attributes.rel && styleNode.attributes.href && styleNode.attributes.rel.value == 'stylesheet') { + var href = styleNode.attributes.href.value; + //todo: write isomorphic relative-to-absolute URL function + var proxyLink = DOM.newEl('a'); + proxyLink.href = href; + var stylesheetURL = proxyLink.protocol + '//' + proxyLink.host + proxyLink.pathname + proxyLink.search; + engineSettings.stylesheets.push(stylesheetURL); + } + }); + + bgnodes.forEach(function (bgNode) { + //Skip processing background nodes if getComputedStyle is unavailable, since only modern browsers would be able to use canvas or SVG to render to background + if (!global.getComputedStyle) return; + var backgroundImage = global.getComputedStyle(bgNode, null).getPropertyValue('background-image'); + var dataBackgroundImage = bgNode.getAttribute('data-background-src'); + var rawURL = dataBackgroundImage || backgroundImage; + + var holderURL = null; + var holderString = options.domain + '/'; + var holderStringIndex = rawURL.indexOf(holderString); + + if (holderStringIndex === 0) { + holderURL = rawURL; + } else if (holderStringIndex === 1 && rawURL[0] === '?') { + holderURL = rawURL.slice(1); + } else { + var fragment = rawURL.substr(holderStringIndex).match(/([^\"]*)"?\)/); + if (fragment !== null) { + holderURL = fragment[1]; + } else if (rawURL.indexOf('url(') === 0) { + throw 'Holder: unable to parse background URL: ' + rawURL; + } + } + + if (holderURL) { + var holderFlags = parseURL(holderURL, options); + if (holderFlags) { + prepareDOMElement({ + mode: 'background', + el: bgNode, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + }); + + objects.forEach(function (object) { + var objectAttr = {}; + + try { + objectAttr.data = object.getAttribute('data'); + objectAttr.dataSrc = object.getAttribute(App.vars.dataAttr); + } catch (e) {} + + var objectHasSrcURL = objectAttr.data != null && objectAttr.data.indexOf(options.domain) === 0; + var objectHasDataSrcURL = objectAttr.dataSrc != null && objectAttr.dataSrc.indexOf(options.domain) === 0; + + if (objectHasSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.data, object); + } else if (objectHasDataSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.dataSrc, object); + } + }); + + images.forEach(function (image) { + var imageAttr = {}; + + try { + imageAttr.src = image.getAttribute('src'); + imageAttr.dataSrc = image.getAttribute(App.vars.dataAttr); + imageAttr.rendered = image.getAttribute('data-holder-rendered'); + } catch (e) {} + + var imageHasSrc = imageAttr.src != null; + var imageHasDataSrcURL = imageAttr.dataSrc != null && imageAttr.dataSrc.indexOf(options.domain) === 0; + var imageRendered = imageAttr.rendered != null && imageAttr.rendered == 'true'; + + if (imageHasSrc) { + if (imageAttr.src.indexOf(options.domain) === 0) { + prepareImageElement(options, engineSettings, imageAttr.src, image); + } else if (imageHasDataSrcURL) { + //Image has a valid data-src and an invalid src + if (imageRendered) { + //If the placeholder has already been render, re-render it + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } else { + //If the placeholder has not been rendered, check if the image exists and render a fallback if it doesn't + (function(src, options, engineSettings, dataSrc, image) { + utils.imageExists(src, function(exists) { + if (!exists) { + prepareImageElement(options, engineSettings, dataSrc, image); + } + }); + })(imageAttr.src, options, engineSettings, imageAttr.dataSrc, image); + } + } + } else if (imageHasDataSrcURL) { + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } + }); + + return this; + } + }; + + var App = { + settings: { + domain: 'holder.js', + images: 'img', + objects: 'object', + bgnodes: 'body .holderjs', + stylenodes: 'head link.holderjs', + themes: { + 'gray': { + bg: '#EEEEEE', + fg: '#AAAAAA' + }, + 'social': { + bg: '#3a5a97', + fg: '#FFFFFF' + }, + 'industrial': { + bg: '#434A52', + fg: '#C2F200' + }, + 'sky': { + bg: '#0D8FDB', + fg: '#FFFFFF' + }, + 'vine': { + bg: '#39DBAC', + fg: '#1E292C' + }, + 'lava': { + bg: '#F8591A', + fg: '#1C2846' + } + } + }, + defaults: { + size: 10, + units: 'pt', + scale: 1 / 16 + } + }; + + /** + * Processes provided source attribute and sets up the appropriate rendering workflow + * + * @private + * @param options Instance options from Holder.run + * @param renderSettings Instance configuration + * @param src Image URL + * @param el Image DOM element + */ + function prepareImageElement(options, engineSettings, src, el) { + var holderFlags = parseURL(src.substr(src.lastIndexOf(options.domain)), options); + if (holderFlags) { + prepareDOMElement({ + mode: null, + el: el, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + + /** + * Processes a Holder URL and extracts configuration from query string + * + * @private + * @param url URL + * @param instanceOptions Instance options from Holder.run + */ + function parseURL(url, instanceOptions) { + var holder = { + theme: extend(App.settings.themes.gray, null), + stylesheets: instanceOptions.stylesheets, + instanceOptions: instanceOptions + }; + + var firstQuestionMark = url.indexOf('?'); + var parts = [url]; + + if (firstQuestionMark !== -1) { + parts = [url.slice(0, firstQuestionMark), url.slice(firstQuestionMark + 1)]; + } + + var basics = parts[0].split('/'); + + holder.holderURL = url; + + var dimensions = basics[1]; + var dimensionData = dimensions.match(/([\d]+p?)x([\d]+p?)/); + + if (!dimensionData) return false; + + holder.fluid = dimensions.indexOf('p') !== -1; + + holder.dimensions = { + width: dimensionData[1].replace('p', '%'), + height: dimensionData[2].replace('p', '%') + }; + + if (parts.length === 2) { + var options = querystring.parse(parts[1]); + + // Dimensions + + if (utils.truthy(options.ratio)) { + holder.fluid = true; + var ratioWidth = parseFloat(holder.dimensions.width.replace('%', '')); + var ratioHeight = parseFloat(holder.dimensions.height.replace('%', '')); + + ratioHeight = Math.floor(100 * (ratioHeight / ratioWidth)); + ratioWidth = 100; + + holder.dimensions.width = ratioWidth + '%'; + holder.dimensions.height = ratioHeight + '%'; + } + + holder.auto = utils.truthy(options.auto); + + // Colors + + if (options.bg) { + holder.theme.bg = utils.parseColor(options.bg); + } + + if (options.fg) { + holder.theme.fg = utils.parseColor(options.fg); + } + + //todo: add automatic foreground to themes without foreground + if (options.bg && !options.fg) { + holder.autoFg = true; + } + + if (options.theme && holder.instanceOptions.themes.hasOwnProperty(options.theme)) { + holder.theme = extend(holder.instanceOptions.themes[options.theme], null); + } + + // Text + + if (options.text) { + holder.text = options.text; + } + + if (options.textmode) { + holder.textmode = options.textmode; + } + + if (options.size && parseFloat(options.size)) { + holder.size = parseFloat(options.size); + } + + if (options.font) { + holder.font = options.font; + } + + if (options.align) { + holder.align = options.align; + } + + if (options.lineWrap) { + holder.lineWrap = options.lineWrap; + } + + holder.nowrap = utils.truthy(options.nowrap); + + // Miscellaneous + + holder.outline = utils.truthy(options.outline); + + if (utils.truthy(options.random)) { + App.vars.cache.themeKeys = App.vars.cache.themeKeys || Object.keys(holder.instanceOptions.themes); + var _theme = App.vars.cache.themeKeys[0 | Math.random() * App.vars.cache.themeKeys.length]; + holder.theme = extend(holder.instanceOptions.themes[_theme], null); + } + } + + return holder; + } + + /** + * Modifies the DOM to fit placeholders and sets up resizable image callbacks (for fluid and automatically sized placeholders) + * + * @private + * @param settings DOM prep settings + */ + function prepareDOMElement(prepSettings) { + var mode = prepSettings.mode; + var el = prepSettings.el; + var flags = prepSettings.flags; + var _engineSettings = prepSettings.engineSettings; + var dimensions = flags.dimensions, + theme = flags.theme; + var dimensionsCaption = dimensions.width + 'x' + dimensions.height; + mode = mode == null ? (flags.fluid ? 'fluid' : 'image') : mode; + var holderTemplateRe = /holder_([a-z]+)/g; + var dimensionsInText = false; + + if (flags.text != null) { + theme.text = flags.text; + + // SVG embedding doesn't parse Unicode properly + if (el.nodeName.toLowerCase() === 'object') { + var textLines = theme.text.split('\\n'); + for (var k = 0; k < textLines.length; k++) { + textLines[k] = utils.encodeHtmlEntity(textLines[k]); + } + theme.text = textLines.join('\\n'); + } + } + + if (theme.text) { + var holderTemplateMatches = theme.text.match(holderTemplateRe); + + if (holderTemplateMatches !== null) { + //todo: optimize template replacement + holderTemplateMatches.forEach(function (match) { + if (match === 'holder_dimensions') { + theme.text = theme.text.replace(match, dimensionsCaption); + } + }); + } + } + + var holderURL = flags.holderURL; + var engineSettings = extend(_engineSettings, null); + + if (flags.font) { + /* + If external fonts are used in a placeholder rendered with SVG, Holder falls back to canvas. + + This is done because Firefox and Chrome disallow embedded SVGs from referencing external assets. + The workaround is either to change the placeholder tag from to or to use the canvas renderer. + */ + theme.font = flags.font; + if (!engineSettings.noFontFallback && el.nodeName.toLowerCase() === 'img' && App.setup.supportsCanvas && engineSettings.renderer === 'svg') { + engineSettings = extend(engineSettings, { + renderer: 'canvas' + }); + } + } + + //Chrome and Opera require a quick 10ms re-render if web fonts are used with canvas + if (flags.font && engineSettings.renderer == 'canvas') { + engineSettings.reRender = true; + } + + if (mode == 'background') { + if (el.getAttribute('data-background-src') == null) { + DOM.setAttr(el, { + 'data-background-src': holderURL + }); + } + } else { + var domProps = {}; + domProps[App.vars.dataAttr] = holderURL; + DOM.setAttr(el, domProps); + } + + flags.theme = theme; + + //todo consider using all renderSettings in holderData + el.holderData = { + flags: flags, + engineSettings: engineSettings + }; + + if (mode == 'image' || mode == 'fluid') { + DOM.setAttr(el, { + 'alt': theme.text ? (dimensionsInText ? theme.text : theme.text + ' [' + dimensionsCaption + ']') : dimensionsCaption + }); + } + + var renderSettings = { + mode: mode, + el: el, + holderSettings: { + dimensions: dimensions, + theme: theme, + flags: flags + }, + engineSettings: engineSettings + }; + + if (mode == 'image') { + if (!flags.auto) { + el.style.width = dimensions.width + 'px'; + el.style.height = dimensions.height + 'px'; + } + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + render(renderSettings); + + if (flags.textmode == 'exact') { + el.holderData.resizeUpdate = true; + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } else if (mode == 'background' && engineSettings.renderer != 'html') { + render(renderSettings); + } else if (mode == 'fluid') { + el.holderData.resizeUpdate = true; + + if (dimensions.height.slice(-1) == '%') { + el.style.height = dimensions.height; + } else if (flags.auto == null || !flags.auto) { + el.style.height = dimensions.height + 'px'; + } + if (dimensions.width.slice(-1) == '%') { + el.style.width = dimensions.width; + } else if (flags.auto == null || !flags.auto) { + el.style.width = dimensions.width + 'px'; + } + if (el.style.display == 'inline' || el.style.display === '' || el.style.display == 'none') { + el.style.display = 'block'; + } + + setInitialDimensions(el); + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } + + /** + * Core function that takes output from renderers and sets it as the source or background-image of the target element + * + * @private + * @param renderSettings Renderer settings + */ + function render(renderSettings) { + var image = null; + var mode = renderSettings.mode; + var el = renderSettings.el; + var holderSettings = renderSettings.holderSettings; + var engineSettings = renderSettings.engineSettings; + + switch (engineSettings.renderer) { + case 'svg': + if (!App.setup.supportsSVG) return; + break; + case 'canvas': + if (!App.setup.supportsCanvas) return; + break; + default: + return; + } + + //todo: move generation of scene up to flag generation to reduce extra object creation + var scene = { + width: holderSettings.dimensions.width, + height: holderSettings.dimensions.height, + theme: holderSettings.theme, + flags: holderSettings.flags + }; + + var sceneGraph = buildSceneGraph(scene); + + function getRenderedImage() { + var image = null; + switch (engineSettings.renderer) { + case 'canvas': + image = sgCanvasRenderer(sceneGraph, renderSettings); + break; + case 'svg': + image = svgRenderer(sceneGraph, renderSettings); + break; + default: + throw 'Holder: invalid renderer: ' + engineSettings.renderer; + } + + return image; + } + + image = getRenderedImage(); + + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + + //todo: add canvas rendering + if (mode == 'background') { + el.style.backgroundImage = 'url(' + image + ')'; + + if (!engineSettings.noBackgroundSize) { + el.style.backgroundSize = scene.width + 'px ' + scene.height + 'px'; + } + } else { + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + if (engineSettings.reRender) { + global.setTimeout(function () { + var image = getRenderedImage(); + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + //todo: refactor this code into a function + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + }, 150); + } + } + //todo: account for re-rendering + DOM.setAttr(el, { + 'data-holder-rendered': true + }); + } + + /** + * Core function that takes a Holder scene description and builds a scene graph + * + * @private + * @param scene Holder scene object + */ + //todo: make this function reusable + //todo: merge app defaults and setup properties into the scene argument + function buildSceneGraph(scene) { + var fontSize = App.defaults.size; + if (parseFloat(scene.theme.size)) { + fontSize = scene.theme.size; + } else if (parseFloat(scene.flags.size)) { + fontSize = scene.flags.size; + } + + scene.font = { + family: scene.theme.font ? scene.theme.font : 'Arial, Helvetica, Open Sans, sans-serif', + size: textSize(scene.width, scene.height, fontSize, App.defaults.scale), + units: scene.theme.units ? scene.theme.units : App.defaults.units, + weight: scene.theme.fontweight ? scene.theme.fontweight : 'bold' + }; + + scene.text = scene.theme.text || Math.floor(scene.width) + 'x' + Math.floor(scene.height); + + scene.noWrap = scene.theme.nowrap || scene.flags.nowrap; + + scene.align = scene.theme.align || scene.flags.align || 'center'; + + switch (scene.flags.textmode) { + case 'literal': + scene.text = scene.flags.dimensions.width + 'x' + scene.flags.dimensions.height; + break; + case 'exact': + if (!scene.flags.exactDimensions) break; + scene.text = Math.floor(scene.flags.exactDimensions.width) + 'x' + Math.floor(scene.flags.exactDimensions.height); + break; + } + + var lineWrap = scene.flags.lineWrap || App.setup.lineWrapRatio; + var sceneMargin = scene.width * lineWrap; + var maxLineWidth = sceneMargin; + + var sceneGraph = new SceneGraph({ + width: scene.width, + height: scene.height + }); + + var Shape = sceneGraph.Shape; + + var holderBg = new Shape.Rect('holderBg', { + fill: scene.theme.bg + }); + + holderBg.resize(scene.width, scene.height); + sceneGraph.root.add(holderBg); + + if (scene.flags.outline) { + var outlineColor = new Color(holderBg.properties.fill); + outlineColor = outlineColor.lighten(outlineColor.lighterThan('7f7f7f') ? -0.1 : 0.1); + holderBg.properties.outline = { + fill: outlineColor.toHex(true), + width: 2 + }; + } + + var holderTextColor = scene.theme.fg; + + if (scene.flags.autoFg) { + var holderBgColor = new Color(holderBg.properties.fill); + var lightColor = new Color('fff'); + var darkColor = new Color('000', { + 'alpha': 0.285714 + }); + + holderTextColor = holderBgColor.blendAlpha(holderBgColor.lighterThan('7f7f7f') ? darkColor : lightColor).toHex(true); + } + + var holderTextGroup = new Shape.Group('holderTextGroup', { + text: scene.text, + align: scene.align, + font: scene.font, + fill: holderTextColor + }); + + holderTextGroup.moveTo(null, null, 1); + sceneGraph.root.add(holderTextGroup); + + var tpdata = holderTextGroup.textPositionData = stagingRenderer(sceneGraph); + if (!tpdata) { + throw 'Holder: staging fallback not supported yet.'; + } + holderTextGroup.properties.leading = tpdata.boundingBox.height; + + var textNode = null; + var line = null; + + function finalizeLine(parent, line, width, height) { + line.width = width; + line.height = height; + parent.width = Math.max(parent.width, line.width); + parent.height += line.height; + } + + if (tpdata.lineCount > 1) { + var offsetX = 0; + var offsetY = 0; + var lineIndex = 0; + var lineKey; + line = new Shape.Group('line' + lineIndex); + + //Double margin so that left/right-aligned next is not flush with edge of image + if (scene.align === 'left' || scene.align === 'right') { + maxLineWidth = scene.width * (1 - (1 - lineWrap) * 2); + } + + for (var i = 0; i < tpdata.words.length; i++) { + var word = tpdata.words[i]; + textNode = new Shape.Text(word.text); + var newline = word.text == '\\n'; + if (!scene.noWrap && (offsetX + word.width >= maxLineWidth || newline === true)) { + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + offsetX = 0; + offsetY += holderTextGroup.properties.leading; + lineIndex += 1; + line = new Shape.Group('line' + lineIndex); + line.y = offsetY; + } + if (newline === true) { + continue; + } + textNode.moveTo(offsetX, 0); + offsetX += tpdata.spaceWidth + word.width; + line.add(textNode); + } + + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo(scene.width - line.width, null, null); + } + + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo((holderTextGroup.width - line.width) / 2, null, null); + } + + holderTextGroup.moveTo((scene.width - holderTextGroup.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - holderTextGroup.height) / 2, null); + + //If the text exceeds vertical space, move it down so the first line is visible + if ((scene.height - holderTextGroup.height) / 2 < 0) { + holderTextGroup.moveTo(null, 0, null); + } + } else { + textNode = new Shape.Text(scene.text); + line = new Shape.Group('line0'); + line.add(textNode); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + holderTextGroup.moveTo((scene.width - tpdata.boundingBox.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - tpdata.boundingBox.height) / 2, null); + } + + //todo: renderlist + return sceneGraph; + } + + /** + * Adaptive text sizing function + * + * @private + * @param width Parent width + * @param height Parent height + * @param fontSize Requested text size + * @param scale Proportional scale of text + */ + function textSize(width, height, fontSize, scale) { + var stageWidth = parseInt(width, 10); + var stageHeight = parseInt(height, 10); + + var bigSide = Math.max(stageWidth, stageHeight); + var smallSide = Math.min(stageWidth, stageHeight); + + var newHeight = 0.8 * Math.min(smallSide, bigSide * scale); + return Math.round(Math.max(fontSize, newHeight)); + } + + /** + * Iterates over resizable (fluid or auto) placeholders and renders them + * + * @private + * @param element Optional element selector, specified only if a specific element needs to be re-rendered + */ + function updateResizableElements(element) { + var images; + if (element == null || element.nodeType == null) { + images = App.vars.resizableImages; + } else { + images = [element]; + } + for (var i = 0, l = images.length; i < l; i++) { + var el = images[i]; + if (el.holderData) { + var flags = el.holderData.flags; + var dimensions = dimensionCheck(el); + if (dimensions) { + if (!el.holderData.resizeUpdate) { + continue; + } + + if (flags.fluid && flags.auto) { + var fluidConfig = el.holderData.fluidConfig; + switch (fluidConfig.mode) { + case 'width': + dimensions.height = dimensions.width / fluidConfig.ratio; + break; + case 'height': + dimensions.width = dimensions.height * fluidConfig.ratio; + break; + } + } + + var settings = { + mode: 'image', + holderSettings: { + dimensions: dimensions, + theme: flags.theme, + flags: flags + }, + el: el, + engineSettings: el.holderData.engineSettings + }; + + if (flags.textmode == 'exact') { + flags.exactDimensions = dimensions; + settings.holderSettings.dimensions = flags.dimensions; + } + + render(settings); + } else { + setInvisible(el); + } + } + } + } + + /** + * Sets up aspect ratio metadata for fluid placeholders, in order to preserve proportions when resizing + * + * @private + * @param el Image DOM element + */ + function setInitialDimensions(el) { + if (el.holderData) { + var dimensions = dimensionCheck(el); + if (dimensions) { + var flags = el.holderData.flags; + + var fluidConfig = { + fluidHeight: flags.dimensions.height.slice(-1) == '%', + fluidWidth: flags.dimensions.width.slice(-1) == '%', + mode: null, + initialDimensions: dimensions + }; + + if (fluidConfig.fluidWidth && !fluidConfig.fluidHeight) { + fluidConfig.mode = 'width'; + fluidConfig.ratio = fluidConfig.initialDimensions.width / parseFloat(flags.dimensions.height); + } else if (!fluidConfig.fluidWidth && fluidConfig.fluidHeight) { + fluidConfig.mode = 'height'; + fluidConfig.ratio = parseFloat(flags.dimensions.width) / fluidConfig.initialDimensions.height; + } + + el.holderData.fluidConfig = fluidConfig; + } else { + setInvisible(el); + } + } + } + + /** + * Iterates through all current invisible images, and if they're visible, renders them and removes them from further checks. Runs every animation frame. + * + * @private + */ + function visibilityCheck() { + var renderableImages = []; + var keys = Object.keys(App.vars.invisibleImages); + var el; + + keys.forEach(function (key) { + el = App.vars.invisibleImages[key]; + if (dimensionCheck(el) && el.nodeName.toLowerCase() == 'img') { + renderableImages.push(el); + delete App.vars.invisibleImages[key]; + } + }); + + if (renderableImages.length) { + Holder.run({ + images: renderableImages + }); + } + + // Done to prevent 100% CPU usage via aggressive calling of requestAnimationFrame + setTimeout(function () { + global.requestAnimationFrame(visibilityCheck); + }, 10); + } + + /** + * Starts checking for invisible placeholders if not doing so yet. Does nothing otherwise. + * + * @private + */ + function startVisibilityCheck() { + if (!App.vars.visibilityCheckStarted) { + global.requestAnimationFrame(visibilityCheck); + App.vars.visibilityCheckStarted = true; + } + } + + /** + * Sets a unique ID for an image detected to be invisible and adds it to the map of invisible images checked by visibilityCheck + * + * @private + * @param el Invisible DOM element + */ + function setInvisible(el) { + if (!el.holderData.invisibleId) { + App.vars.invisibleId += 1; + App.vars.invisibleImages['i' + App.vars.invisibleId] = el; + el.holderData.invisibleId = App.vars.invisibleId; + } + } + + //todo: see if possible to convert stagingRenderer to use HTML only + var stagingRenderer = (function() { + var svg = null, + stagingText = null, + stagingTextNode = null; + return function(graph) { + var rootNode = graph.root; + if (App.setup.supportsSVG) { + var firstTimeSetup = false; + var tnode = function(text) { + return document.createTextNode(text); + }; + if (svg == null || svg.parentNode !== document.body) { + firstTimeSetup = true; + } + + svg = SVG.initSVG(svg, rootNode.properties.width, rootNode.properties.height); + //Show staging element before staging + svg.style.display = 'block'; + + if (firstTimeSetup) { + stagingText = DOM.newEl('text', SVG_NS); + stagingTextNode = tnode(null); + DOM.setAttr(stagingText, { + x: 0 + }); + stagingText.appendChild(stagingTextNode); + svg.appendChild(stagingText); + document.body.appendChild(svg); + svg.style.visibility = 'hidden'; + svg.style.position = 'absolute'; + svg.style.top = '-100%'; + svg.style.left = '-100%'; + //todo: workaround for zero-dimension tag in Opera 12 + //svg.setAttribute('width', 0); + //svg.setAttribute('height', 0); + } + + var holderTextGroup = rootNode.children.holderTextGroup; + var htgProps = holderTextGroup.properties; + DOM.setAttr(stagingText, { + 'y': htgProps.font.size, + 'style': utils.cssProps({ + 'font-weight': htgProps.font.weight, + 'font-size': htgProps.font.size + htgProps.font.units, + 'font-family': htgProps.font.family + }) + }); + + //Unescape HTML entities to get approximately the right width + var txt = DOM.newEl('textarea'); + txt.innerHTML = htgProps.text; + stagingTextNode.nodeValue = txt.value; + + //Get bounding box for the whole string (total width and height) + var stagingTextBBox = stagingText.getBBox(); + + //Get line count and split the string into words + var lineCount = Math.ceil(stagingTextBBox.width / rootNode.properties.width); + var words = htgProps.text.split(' '); + var newlines = htgProps.text.match(/\\n/g); + lineCount += newlines == null ? 0 : newlines.length; + + //Get bounding box for the string with spaces removed + stagingTextNode.nodeValue = htgProps.text.replace(/[ ]+/g, ''); + var computedNoSpaceLength = stagingText.getComputedTextLength(); + + //Compute average space width + var diffLength = stagingTextBBox.width - computedNoSpaceLength; + var spaceWidth = Math.round(diffLength / Math.max(1, words.length - 1)); + + //Get widths for every word with space only if there is more than one line + var wordWidths = []; + if (lineCount > 1) { + stagingTextNode.nodeValue = ''; + for (var i = 0; i < words.length; i++) { + if (words[i].length === 0) continue; + stagingTextNode.nodeValue = utils.decodeHtmlEntity(words[i]); + var bbox = stagingText.getBBox(); + wordWidths.push({ + text: words[i], + width: bbox.width + }); + } + } + + //Hide staging element after staging + svg.style.display = 'none'; + + return { + spaceWidth: spaceWidth, + lineCount: lineCount, + boundingBox: stagingTextBBox, + words: wordWidths + }; + } else { + //todo: canvas fallback for measuring text on android 2.3 + return false; + } + }; + })(); + + //Helpers + + /** + * Prevents a function from being called too often, waits until a timer elapses to call it again + * + * @param fn Function to call + */ + function debounce(fn) { + if (!App.vars.debounceTimer) fn.call(this); + if (App.vars.debounceTimer) global.clearTimeout(App.vars.debounceTimer); + App.vars.debounceTimer = global.setTimeout(function() { + App.vars.debounceTimer = null; + fn.call(this); + }, App.setup.debounce); + } + + /** + * Holder-specific resize/orientation change callback, debounced to prevent excessive execution + */ + function resizeEvent() { + debounce(function() { + updateResizableElements(null); + }); + } + + //Set up flags + + for (var flag in App.flags) { + if (!App.flags.hasOwnProperty(flag)) continue; + App.flags[flag].match = function(val) { + return val.match(this.regex); + }; + } + + //Properties set once on setup + + App.setup = { + renderer: 'html', + debounce: 100, + ratio: 1, + supportsCanvas: false, + supportsSVG: false, + lineWrapRatio: 0.9, + dataAttr: 'data-src', + renderers: ['html', 'canvas', 'svg'] + }; + + //Properties modified during runtime + + App.vars = { + preempted: false, + resizableImages: [], + invisibleImages: {}, + invisibleId: 0, + visibilityCheckStarted: false, + debounceTimer: null, + cache: {} + }; + + //Pre-flight + + (function() { + var canvas = DOM.newEl('canvas'); + + if (canvas.getContext) { + if (canvas.toDataURL('image/png').indexOf('data:image/png') != -1) { + App.setup.renderer = 'canvas'; + App.setup.supportsCanvas = true; + } + } + + if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect) { + App.setup.renderer = 'svg'; + App.setup.supportsSVG = true; + } + })(); + + //Starts checking for invisible placeholders + startVisibilityCheck(); + + if (onDomReady) { + onDomReady(function() { + if (!App.vars.preempted) { + Holder.run(); + } + if (global.addEventListener) { + global.addEventListener('resize', resizeEvent, false); + global.addEventListener('orientationchange', resizeEvent, false); + } else { + global.attachEvent('onresize', resizeEvent); + } + + if (typeof global.Turbolinks == 'object') { + global.document.addEventListener('page:change', function() { + Holder.run(); + }); + } + }); + } + + module.exports = Holder; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /*! + * onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license + * + * Specially modified to work with Holder.js + */ + + function _onDomReady(win) { + //Lazy loading fix for Firefox < 3.6 + //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html + if (document.readyState == null && document.addEventListener) { + document.addEventListener("DOMContentLoaded", function DOMContentLoaded() { + document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); + document.readyState = "complete"; + }, false); + document.readyState = "loading"; + } + + var doc = win.document, + docElem = doc.documentElement, + + LOAD = "load", + FALSE = false, + ONLOAD = "on"+LOAD, + COMPLETE = "complete", + READYSTATE = "readyState", + ATTACHEVENT = "attachEvent", + DETACHEVENT = "detachEvent", + ADDEVENTLISTENER = "addEventListener", + DOMCONTENTLOADED = "DOMContentLoaded", + ONREADYSTATECHANGE = "onreadystatechange", + REMOVEEVENTLISTENER = "removeEventListener", + + // W3C Event model + w3c = ADDEVENTLISTENER in doc, + _top = FALSE, + + // isReady: Is the DOM ready to be used? Set to true once it occurs. + isReady = FALSE, + + // Callbacks pending execution until DOM is ready + callbacks = []; + + // Handle when the DOM is ready + function ready( fn ) { + if ( !isReady ) { + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !doc.body ) { + return defer( ready ); + } + + // Remember that the DOM is ready + isReady = true; + + // Execute all callbacks + while ( fn = callbacks.shift() ) { + defer( fn ); + } + } + } + + // The ready event handler + function completed( event ) { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) { + detach(); + ready(); + } + } + + // Clean-up method for dom ready events + function detach() { + if ( w3c ) { + doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE ); + } else { + doc[DETACHEVENT]( ONREADYSTATECHANGE, completed ); + win[DETACHEVENT]( ONLOAD, completed ); + } + } + + // Defers a function, scheduling it to run after the current call stack has cleared. + function defer( fn, wait ) { + // Allow 0 to be passed + setTimeout( fn, +wait >= 0 ? wait : 1 ); + } + + // Attach the listeners: + + // Catch cases where onDomReady is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( doc[READYSTATE] === COMPLETE ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + defer( ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( w3c ) { + // Use the handy event callback + doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + + // A fallback to window.onload, that will always work + win[ADDEVENTLISTENER]( LOAD, completed, FALSE ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed ); + + // A fallback to window.onload, that will always work + win[ATTACHEVENT]( ONLOAD, completed ); + + // If IE and not a frame + // continually check to see if the document is ready + try { + _top = win.frameElement == null && docElem; + } catch(e) {} + + if ( _top && _top.doScroll ) { + (function doScrollCheck() { + if ( !isReady ) { + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + _top.doScroll("left"); + } catch(e) { + return defer( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + ready(); + } + })(); + } + } + + function onDomReady( fn ) { + // If DOM is ready, execute the function (async), otherwise wait + isReady ? defer( fn ) : callbacks.push( fn ); + } + + // Add version + onDomReady.version = "1.4.0"; + // Add method to check if DOM is ready + onDomReady.isReady = function(){ + return isReady; + }; + + return onDomReady; + } + + module.exports = typeof window !== "undefined" && _onDomReady(window); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + //Modified version of component/querystring + //Changes: updated dependencies, dot notation parsing, JSHint fixes + //Fork at https://github.com/imsky/querystring + + /** + * Module dependencies. + */ + + var encode = encodeURIComponent; + var decode = decodeURIComponent; + var trim = __webpack_require__(4); + var type = __webpack_require__(5); + + var arrayRegex = /(\w+)\[(\d+)\]/; + var objectRegex = /\w+\.\w+/; + + /** + * Parse the given query `str`. + * + * @param {String} str + * @return {Object} + * @api public + */ + + exports.parse = function(str){ + if ('string' !== typeof str) return {}; + + str = trim(str); + if ('' === str) return {}; + if ('?' === str.charAt(0)) str = str.slice(1); + + var obj = {}; + var pairs = str.split('&'); + for (var i = 0; i < pairs.length; i++) { + var parts = pairs[i].split('='); + var key = decode(parts[0]); + var m, ctx, prop; + + if (m = arrayRegex.exec(key)) { + obj[m[1]] = obj[m[1]] || []; + obj[m[1]][m[2]] = decode(parts[1]); + continue; + } + + if (m = objectRegex.test(key)) { + m = key.split('.'); + ctx = obj; + + while (m.length) { + prop = m.shift(); + + if (!prop.length) continue; + + if (!ctx[prop]) { + ctx[prop] = {}; + } else if (ctx[prop] && typeof ctx[prop] !== 'object') { + break; + } + + if (!m.length) { + ctx[prop] = decode(parts[1]); + } + + ctx = ctx[prop]; + } + + continue; + } + + obj[parts[0]] = null == parts[1] ? '' : decode(parts[1]); + } + + return obj; + }; + + /** + * Stringify the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api public + */ + + exports.stringify = function(obj){ + if (!obj) return ''; + var pairs = []; + + for (var key in obj) { + var value = obj[key]; + + if ('array' == type(value)) { + for (var i = 0; i < value.length; ++i) { + pairs.push(encode(key + '[' + i + ']') + '=' + encode(value[i])); + } + continue; + } + + pairs.push(encode(key) + '=' + encode(obj[key])); + } + + return pairs.join('&'); + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + + exports = module.exports = trim; + + function trim(str){ + return str.replace(/^\s*|\s*$/g, ''); + } + + exports.left = function(str){ + return str.replace(/^\s*/, ''); + }; + + exports.right = function(str){ + return str.replace(/\s*$/, ''); + }; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + /** + * toString ref. + */ + + var toString = Object.prototype.toString; + + /** + * Return the type of `val`. + * + * @param {Mixed} val + * @return {String} + * @api public + */ + + module.exports = function(val){ + switch (toString.call(val)) { + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object Error]': return 'error'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val !== val) return 'nan'; + if (val && val.nodeType === 1) return 'element'; + + val = val.valueOf + ? val.valueOf() + : Object.prototype.valueOf.apply(val) + + return typeof val; + }; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + + var SceneGraph = function(sceneProperties) { + var nodeCount = 1; + + //todo: move merge to helpers section + function merge(parent, child) { + for (var prop in child) { + parent[prop] = child[prop]; + } + return parent; + } + + var SceneNode = function(name) { + nodeCount++; + this.parent = null; + this.children = {}; + this.id = nodeCount; + this.name = 'n' + nodeCount; + if (typeof name !== 'undefined') { + this.name = name; + } + this.x = this.y = this.z = 0; + this.width = this.height = 0; + }; + + SceneNode.prototype.resize = function(width, height) { + if (width != null) { + this.width = width; + } + if (height != null) { + this.height = height; + } + }; + + SceneNode.prototype.moveTo = function(x, y, z) { + this.x = x != null ? x : this.x; + this.y = y != null ? y : this.y; + this.z = z != null ? z : this.z; + }; + + SceneNode.prototype.add = function(child) { + var name = child.name; + if (typeof this.children[name] === 'undefined') { + this.children[name] = child; + child.parent = this; + } else { + throw 'SceneGraph: child already exists: ' + name; + } + }; + + var RootNode = function() { + SceneNode.call(this, 'root'); + this.properties = sceneProperties; + }; + + RootNode.prototype = new SceneNode(); + + var Shape = function(name, props) { + SceneNode.call(this, name); + this.properties = { + 'fill': '#000000' + }; + if (typeof props !== 'undefined') { + merge(this.properties, props); + } else if (typeof name !== 'undefined' && typeof name !== 'string') { + throw 'SceneGraph: invalid node name'; + } + }; + + Shape.prototype = new SceneNode(); + + var Group = function() { + Shape.apply(this, arguments); + this.type = 'group'; + }; + + Group.prototype = new Shape(); + + var Rect = function() { + Shape.apply(this, arguments); + this.type = 'rect'; + }; + + Rect.prototype = new Shape(); + + var Text = function(text) { + Shape.call(this); + this.type = 'text'; + this.properties.text = text; + }; + + Text.prototype = new Shape(); + + var root = new RootNode(); + + this.Shape = { + 'Rect': Rect, + 'Text': Text, + 'Group': Group + }; + + this.root = root; + return this; + }; + + module.exports = SceneGraph; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Shallow object clone and merge + * + * @param a Object A + * @param b Object B + * @returns {Object} New object with all of A's properties, and all of B's properties, overwriting A's properties + */ + exports.extend = function(a, b) { + var c = {}; + for (var x in a) { + if (a.hasOwnProperty(x)) { + c[x] = a[x]; + } + } + if (b != null) { + for (var y in b) { + if (b.hasOwnProperty(y)) { + c[y] = b[y]; + } + } + } + return c; + }; + + /** + * Takes a k/v list of CSS properties and returns a rule + * + * @param props CSS properties object + */ + exports.cssProps = function(props) { + var ret = []; + for (var p in props) { + if (props.hasOwnProperty(p)) { + ret.push(p + ':' + props[p]); + } + } + return ret.join(';'); + }; + + /** + * Encodes HTML entities in a string + * + * @param str Input string + */ + exports.encodeHtmlEntity = function(str) { + var buf = []; + var charCode = 0; + for (var i = str.length - 1; i >= 0; i--) { + charCode = str.charCodeAt(i); + if (charCode > 128) { + buf.unshift(['&#', charCode, ';'].join('')); + } else { + buf.unshift(str[i]); + } + } + return buf.join(''); + }; + + /** + * Checks if an image exists + * + * @param src URL of image + * @param callback Callback to call once image status has been found + */ + exports.imageExists = function(src, callback) { + var image = new Image(); + image.onerror = function() { + callback.call(this, false); + }; + image.onload = function() { + callback.call(this, true); + }; + image.src = src; + }; + + /** + * Decodes HTML entities in a string + * + * @param str Input string + */ + exports.decodeHtmlEntity = function(str) { + return str.replace(/&#(\d+);/g, function(match, dec) { + return String.fromCharCode(dec); + }); + }; + + + /** + * Returns an element's dimensions if it's visible, `false` otherwise. + * + * @param el DOM element + */ + exports.dimensionCheck = function(el) { + var dimensions = { + height: el.clientHeight, + width: el.clientWidth + }; + + if (dimensions.height && dimensions.width) { + return dimensions; + } else { + return false; + } + }; + + + /** + * Returns true if value is truthy or if it is "semantically truthy" + * @param val + */ + exports.truthy = function(val) { + if (typeof val === 'string') { + return val === 'true' || val === 'yes' || val === '1' || val === 'on' || val === '✓'; + } + return !!val; + }; + + /** + * Parses input into a well-formed CSS color + * @param val + */ + exports.parseColor = function(val) { + var hexre = /(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i; + var rgbre = /^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/; + var rgbare = /^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/; + + var match = val.match(hexre); + var retval; + + if (match !== null) { + retval = match[1] || match[2]; + if (retval[0] !== '#') { + return '#' + retval; + } else { + return retval; + } + } + + match = val.match(rgbre); + + if (match !== null) { + retval = 'rgb(' + match.slice(1).join(',') + ')'; + return retval; + } + + match = val.match(rgbare); + + if (match !== null) { + const normalizeAlpha = function (a) { return '0.' + a.split('.')[1]; }; + const fixedMatch = match.slice(1).map(function (e, i) { + return (i === 3) ? normalizeAlpha(e) : e; + }); + retval = 'rgba(' + fixedMatch.join(',') + ')'; + return retval; + } + + return null; + }; + + /** + * Provides the correct scaling ratio for canvas drawing operations on HiDPI screens (e.g. Retina displays) + */ + exports.canvasRatio = function () { + var devicePixelRatio = 1; + var backingStoreRatio = 1; + + if (global.document) { + var canvas = global.document.createElement('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + devicePixelRatio = global.devicePixelRatio || 1; + backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + } + } + + return devicePixelRatio / backingStoreRatio; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {var DOM = __webpack_require__(9); + + var SVG_NS = 'http://www.w3.org/2000/svg'; + var NODE_TYPE_COMMENT = 8; + + /** + * Generic SVG element creation function + * + * @param svg SVG context, set to null if new + * @param width Document width + * @param height Document height + */ + exports.initSVG = function(svg, width, height) { + var defs, style, initialize = false; + + if (svg && svg.querySelector) { + style = svg.querySelector('style'); + if (style === null) { + initialize = true; + } + } else { + svg = DOM.newEl('svg', SVG_NS); + initialize = true; + } + + if (initialize) { + defs = DOM.newEl('defs', SVG_NS); + style = DOM.newEl('style', SVG_NS); + DOM.setAttr(style, { + 'type': 'text/css' + }); + defs.appendChild(style); + svg.appendChild(defs); + } + + //IE throws an exception if this is set and Chrome requires it to be set + if (svg.webkitMatchesSelector) { + svg.setAttribute('xmlns', SVG_NS); + } + + //Remove comment nodes + for (var i = 0; i < svg.childNodes.length; i++) { + if (svg.childNodes[i].nodeType === NODE_TYPE_COMMENT) { + svg.removeChild(svg.childNodes[i]); + } + } + + //Remove CSS + while (style.childNodes.length) { + style.removeChild(style.childNodes[0]); + } + + DOM.setAttr(svg, { + 'width': width, + 'height': height, + 'viewBox': '0 0 ' + width + ' ' + height, + 'preserveAspectRatio': 'none' + }); + + return svg; + }; + + /** + * Converts serialized SVG to a string suitable for data URI use + * @param svgString Serialized SVG string + * @param [base64] Use base64 encoding for data URI + */ + exports.svgStringToDataURI = function() { + var rawPrefix = 'data:image/svg+xml;charset=UTF-8,'; + var base64Prefix = 'data:image/svg+xml;charset=UTF-8;base64,'; + + return function(svgString, base64) { + if (base64) { + return base64Prefix + btoa(global.unescape(encodeURIComponent(svgString))); + } else { + return rawPrefix + encodeURIComponent(svgString); + } + }; + }(); + + /** + * Returns serialized SVG with XML processing instructions + * + * @param svg SVG context + * @param stylesheets CSS stylesheets to include + */ + exports.serializeSVG = function(svg, engineSettings) { + if (!global.XMLSerializer) return; + var serializer = new XMLSerializer(); + var svgCSS = ''; + var stylesheets = engineSettings.stylesheets; + + //External stylesheets: Processing Instruction method + if (engineSettings.svgXMLStylesheet) { + var xml = DOM.createXML(); + //Add directives + for (var i = stylesheets.length - 1; i >= 0; i--) { + var csspi = xml.createProcessingInstruction('xml-stylesheet', 'href="' + stylesheets[i] + '" rel="stylesheet"'); + xml.insertBefore(csspi, xml.firstChild); + } + + xml.removeChild(xml.documentElement); + svgCSS = serializer.serializeToString(xml); + } + + var svgText = serializer.serializeToString(svg); + svgText = svgText.replace(/\&(\#[0-9]{2,}\;)/g, '&$1'); + return svgCSS + svgText; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Generic new DOM element function + * + * @param tag Tag to create + * @param namespace Optional namespace value + */ + exports.newEl = function(tag, namespace) { + if (!global.document) return; + + if (namespace == null) { + return global.document.createElement(tag); + } else { + return global.document.createElementNS(namespace, tag); + } + }; + + /** + * Generic setAttribute function + * + * @param el Reference to DOM element + * @param attrs Object with attribute keys and values + */ + exports.setAttr = function (el, attrs) { + for (var a in attrs) { + el.setAttribute(a, attrs[a]); + } + }; + + /** + * Creates a XML document + * @private + */ + exports.createXML = function() { + if (!global.DOMParser) return; + return new DOMParser().parseFromString('', 'application/xml'); + }; + + /** + * Converts a value into an array of DOM nodes + * + * @param val A string, a NodeList, a Node, or an HTMLCollection + */ + exports.getNodeArray = function(val) { + var retval = null; + if (typeof(val) == 'string') { + retval = document.querySelectorAll(val); + } else if (global.NodeList && val instanceof global.NodeList) { + retval = val; + } else if (global.Node && val instanceof global.Node) { + retval = [val]; + } else if (global.HTMLCollection && val instanceof global.HTMLCollection) { + retval = val; + } else if (val instanceof Array) { + retval = val; + } else if (val === null) { + retval = []; + } + + retval = Array.prototype.slice.call(retval); + + return retval; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + + var Color = function(color, options) { + //todo: support rgba, hsla, and rrggbbaa notation + //todo: use CIELAB internally + //todo: add clamp function (with sign) + if (typeof color !== 'string') return; + + this.original = color; + + if (color.charAt(0) === '#') { + color = color.slice(1); + } + + if (/[^a-f0-9]+/i.test(color)) return; + + if (color.length === 3) { + color = color.replace(/./g, '$&$&'); + } + + if (color.length !== 6) return; + + this.alpha = 1; + + if (options && options.alpha) { + this.alpha = options.alpha; + } + + this.set(parseInt(color, 16)); + }; + + //todo: jsdocs + Color.rgb2hex = function(r, g, b) { + function format (decimal) { + var hex = (decimal | 0).toString(16); + if (decimal < 16) { + hex = '0' + hex; + } + return hex; + } + + return [r, g, b].map(format).join(''); + }; + + //todo: jsdocs + Color.hsl2rgb = function (h, s, l) { + var H = h / 60; + var C = (1 - Math.abs(2 * l - 1)) * s; + var X = C * (1 - Math.abs(parseInt(H) % 2 - 1)); + var m = l - (C / 2); + + var r = 0, g = 0, b = 0; + + if (H >= 0 && H < 1) { + r = C; + g = X; + } else if (H >= 1 && H < 2) { + r = X; + g = C; + } else if (H >= 2 && H < 3) { + g = C; + b = X; + } else if (H >= 3 && H < 4) { + g = X; + b = C; + } else if (H >= 4 && H < 5) { + r = X; + b = C; + } else if (H >= 5 && H < 6) { + r = C; + b = X; + } + + r += m; + g += m; + b += m; + + r = parseInt(r * 255); + g = parseInt(g * 255); + b = parseInt(b * 255); + + return [r, g, b]; + }; + + /** + * Sets the color from a raw RGB888 integer + * @param raw RGB888 representation of color + */ + //todo: refactor into a static method + //todo: factor out individual color spaces + //todo: add HSL, CIELAB, and CIELUV + Color.prototype.set = function (val) { + this.raw = val; + + var r = (this.raw & 0xFF0000) >> 16; + var g = (this.raw & 0x00FF00) >> 8; + var b = (this.raw & 0x0000FF); + + // BT.709 + var y = 0.2126 * r + 0.7152 * g + 0.0722 * b; + var u = -0.09991 * r - 0.33609 * g + 0.436 * b; + var v = 0.615 * r - 0.55861 * g - 0.05639 * b; + + this.rgb = { + r: r, + g: g, + b: b + }; + + this.yuv = { + y: y, + u: u, + v: v + }; + + return this; + }; + + /** + * Lighten or darken a color + * @param multiplier Amount to lighten or darken (-1 to 1) + */ + Color.prototype.lighten = function(multiplier) { + var cm = Math.min(1, Math.max(0, Math.abs(multiplier))) * (multiplier < 0 ? -1 : 1); + var bm = (255 * cm) | 0; + var cr = Math.min(255, Math.max(0, this.rgb.r + bm)); + var cg = Math.min(255, Math.max(0, this.rgb.g + bm)); + var cb = Math.min(255, Math.max(0, this.rgb.b + bm)); + var hex = Color.rgb2hex(cr, cg, cb); + return new Color(hex); + }; + + /** + * Output color in hex format + * @param addHash Add a hash character to the beginning of the output + */ + Color.prototype.toHex = function(addHash) { + return (addHash ? '#' : '') + this.raw.toString(16); + }; + + /** + * Returns whether or not current color is lighter than another color + * @param color Color to compare against + */ + Color.prototype.lighterThan = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + return this.yuv.y > color.yuv.y; + }; + + /** + * Returns the result of mixing current color with another color + * @param color Color to mix with + * @param multiplier How much to mix with the other color + */ + /* + Color.prototype.mix = function (color, multiplier) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var r = this.rgb.r; + var g = this.rgb.g; + var b = this.rgb.b; + var a = this.alpha; + + var m = typeof multiplier !== 'undefined' ? multiplier : 0.5; + + //todo: write a lerp function + r = r + m * (color.rgb.r - r); + g = g + m * (color.rgb.g - g); + b = b + m * (color.rgb.b - b); + a = a + m * (color.alpha - a); + + return new Color(Color.rgbToHex(r, g, b), { + 'alpha': a + }); + }; + */ + + /** + * Returns the result of blending another color on top of current color with alpha + * @param color Color to blend on top of current color, i.e. "Ca" + */ + //todo: see if .blendAlpha can be merged into .mix + Color.prototype.blendAlpha = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var Ca = color; + var Cb = this; + + //todo: write alpha blending function + var r = Ca.alpha * Ca.rgb.r + (1 - Ca.alpha) * Cb.rgb.r; + var g = Ca.alpha * Ca.rgb.g + (1 - Ca.alpha) * Cb.rgb.g; + var b = Ca.alpha * Ca.rgb.b + (1 - Ca.alpha) * Cb.rgb.b; + + return new Color(Color.rgb2hex(r, g, b)); + }; + + module.exports = Color; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports) { + + module.exports = { + 'version': '2.9.7', + 'svg_ns': 'http://www.w3.org/2000/svg' + }; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + var shaven = __webpack_require__(13); + + var SVG = __webpack_require__(8); + var constants = __webpack_require__(11); + var utils = __webpack_require__(7); + + var SVG_NS = constants.svg_ns; + + var templates = { + 'element': function (options) { + var tag = options.tag; + var content = options.content || ''; + delete options.tag; + delete options.content; + return [tag, content, options]; + } + }; + + //todo: deprecate tag arg, infer tag from shape object + function convertShape (shape, tag) { + return templates.element({ + 'tag': tag, + 'width': shape.width, + 'height': shape.height, + 'fill': shape.properties.fill + }); + } + + function textCss (properties) { + return utils.cssProps({ + 'fill': properties.fill, + 'font-weight': properties.font.weight, + 'font-family': properties.font.family + ', monospace', + 'font-size': properties.font.size + properties.font.units + }); + } + + function outlinePath (bgWidth, bgHeight, outlineWidth) { + var outlineOffsetWidth = outlineWidth / 2; + + return [ + 'M', outlineOffsetWidth, outlineOffsetWidth, + 'H', bgWidth - outlineOffsetWidth, + 'V', bgHeight - outlineOffsetWidth, + 'H', outlineOffsetWidth, + 'V', 0, + 'M', 0, outlineOffsetWidth, + 'L', bgWidth, bgHeight - outlineOffsetWidth, + 'M', 0, bgHeight - outlineOffsetWidth, + 'L', bgWidth, outlineOffsetWidth + ].join(' '); + } + + module.exports = function (sceneGraph, renderSettings) { + var engineSettings = renderSettings.engineSettings; + var stylesheets = engineSettings.stylesheets; + var stylesheetXml = stylesheets.map(function (stylesheet) { + return ''; + }).join('\n'); + + var holderId = 'holder_' + Number(new Date()).toString(16); + + var root = sceneGraph.root; + var textGroup = root.children.holderTextGroup; + + var css = '#' + holderId + ' text { ' + textCss(textGroup.properties) + ' } '; + + // push text down to be equally vertically aligned with canvas renderer + textGroup.y += textGroup.textPositionData.boundingBox.height * 0.8; + + var wordTags = []; + + Object.keys(textGroup.children).forEach(function (lineKey) { + var line = textGroup.children[lineKey]; + + Object.keys(line.children).forEach(function (wordKey) { + var word = line.children[wordKey]; + var x = textGroup.x + line.x + word.x; + var y = textGroup.y + line.y + word.y; + var wordTag = templates.element({ + 'tag': 'text', + 'content': word.properties.text, + 'x': x, + 'y': y + }); + + wordTags.push(wordTag); + }); + }); + + var text = templates.element({ + 'tag': 'g', + 'content': wordTags + }); + + var outline = null; + + if (root.children.holderBg.properties.outline) { + var outlineProperties = root.children.holderBg.properties.outline; + outline = templates.element({ + 'tag': 'path', + 'd': outlinePath(root.children.holderBg.width, root.children.holderBg.height, outlineProperties.width), + 'stroke-width': outlineProperties.width, + 'stroke': outlineProperties.fill, + 'fill': 'none' + }); + } + + var bg = convertShape(root.children.holderBg, 'rect'); + + var sceneContent = []; + + sceneContent.push(bg); + if (outlineProperties) { + sceneContent.push(outline); + } + sceneContent.push(text); + + var scene = templates.element({ + 'tag': 'g', + 'id': holderId, + 'content': sceneContent + }); + + var style = templates.element({ + 'tag': 'style', + //todo: figure out how to add CDATA directive + 'content': css, + 'type': 'text/css' + }); + + var defs = templates.element({ + 'tag': 'defs', + 'content': style + }); + + var svg = templates.element({ + 'tag': 'svg', + 'content': [defs, scene], + 'width': root.properties.width, + 'height': root.properties.height, + 'xmlns': SVG_NS, + 'viewBox': [0, 0, root.properties.width, root.properties.height].join(' '), + 'preserveAspectRatio': 'none' + }); + + var output = shaven(svg); + + if (/\&(x)?#[0-9A-Fa-f]/.test(output[0])) { + output[0] = output[0].replace(/&#/gm, '&#'); + } + + output = stylesheetXml + output[0]; + + var svgString = SVG.svgStringToDataURI(output, renderSettings.mode === 'background'); + return svgString; + }; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + var escape = __webpack_require__(14) + + // TODO: remove namespace + + module.exports = function shaven (array, namespace, returnObject) { + + 'use strict' + + var i = 1 + var doesEscape = true + var HTMLString + var attributeKey + var callback + var key + + + returnObject = returnObject || {} + + + function createElement (sugarString) { + + var tags = sugarString.match(/^[\w-]+/) + var element = { + tag: tags ? tags[0] : 'div', + attr: {}, + children: [] + } + var id = sugarString.match(/#([\w-]+)/) + var reference = sugarString.match(/\$([\w-]+)/) + var classNames = sugarString.match(/\.[\w-]+/g) + + + // Assign id if is set + if (id) { + element.attr.id = id[1] + + // Add element to the return object + returnObject[id[1]] = element + } + + if (reference) + returnObject[reference[1]] = element + + if (classNames) + element.attr.class = classNames.join(' ').replace(/\./g, '') + + if (sugarString.match(/&$/g)) + doesEscape = false + + return element + } + + function replacer (key, value) { + + if (value === null || value === false || value === undefined) + return + + if (typeof value !== 'string' && typeof value !== 'object') + return String(value) + + return value + } + + function escapeAttribute (string) { + return (string || string === 0) ? + String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') : + '' + } + + function escapeHTML (string) { + return String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + } + + + if (typeof array[0] === 'string') + array[0] = createElement(array[0]) + + else if (Array.isArray(array[0])) + i = 0 + + else + throw new Error( + 'First element of array must be a string, ' + + 'or an array and not ' + JSON.stringify(array[0]) + ) + + + for (; i < array.length; i++) { + + // Don't render element if value is false or null + if (array[i] === false || array[i] === null) { + array[0] = false + break + } + + // Continue with next array value if current value is undefined or true + else if (array[i] === undefined || array[i] === true) { + continue + } + + else if (typeof array[i] === 'string') { + if (doesEscape) + array[i] = escapeHTML(array[i]) + + array[0].children.push(array[i]) + } + + else if (typeof array[i] === 'number') { + + array[0].children.push(array[i]) + } + + else if (Array.isArray(array[i])) { + + if (Array.isArray(array[i][0])) { + array[i].reverse().forEach(function (subArray) { + array.splice(i + 1, 0, subArray) + }) + + if (i !== 0) + continue + i++ + } + + shaven(array[i], namespace, returnObject) + + if (array[i][0]) + array[0].children.push(array[i][0]) + } + + else if (typeof array[i] === 'function') + callback = array[i] + + + else if (typeof array[i] === 'object') { + for (attributeKey in array[i]) + if (array[i].hasOwnProperty(attributeKey)) + if (array[i][attributeKey] !== null && + array[i][attributeKey] !== false) + if (attributeKey === 'style' && + typeof array[i][attributeKey] === 'object') + array[0].attr[attributeKey] = JSON + .stringify(array[i][attributeKey], replacer) + .slice(2, -2) + .replace(/","/g, ';') + .replace(/":"/g, ':') + .replace(/\\"/g, '\'') + + else + array[0].attr[attributeKey] = array[i][attributeKey] + } + + else + throw new TypeError('"' + array[i] + '" is not allowed as a value.') + } + + + if (array[0] !== false) { + + HTMLString = '<' + array[0].tag + + for (key in array[0].attr) + if (array[0].attr.hasOwnProperty(key)) + HTMLString += ' ' + key + '="' + + escapeAttribute(array[0].attr[key]) + '"' + + HTMLString += '>' + + array[0].children.forEach(function (child) { + HTMLString += child + }) + + HTMLString += '' + + array[0] = HTMLString + } + + // Return root element on index 0 + returnObject[0] = array[0] + + if (callback) + callback(array[0]) + + // returns object containing all elements with an id and the root element + return returnObject + } + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + + /*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + + 'use strict'; + + /** + * Module variables. + * @private + */ + + var matchHtmlRegExp = /["'&<>]/; + + /** + * Module exports. + * @public + */ + + module.exports = escapeHtml; + + /** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + + function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; + } + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + var DOM = __webpack_require__(9); + var utils = __webpack_require__(7); + + module.exports = (function() { + var canvas = DOM.newEl('canvas'); + var ctx = null; + + return function(sceneGraph) { + if (ctx == null) { + ctx = canvas.getContext('2d'); + } + + var dpr = utils.canvasRatio(); + var root = sceneGraph.root; + canvas.width = dpr * root.properties.width; + canvas.height = dpr * root.properties.height ; + ctx.textBaseline = 'middle'; + + var bg = root.children.holderBg; + var bgWidth = dpr * bg.width; + var bgHeight = dpr * bg.height; + //todo: parametrize outline width (e.g. in scene object) + var outlineWidth = 2; + var outlineOffsetWidth = outlineWidth / 2; + + ctx.fillStyle = bg.properties.fill; + ctx.fillRect(0, 0, bgWidth, bgHeight); + + if (bg.properties.outline) { + //todo: abstract this into a method + ctx.strokeStyle = bg.properties.outline.fill; + ctx.lineWidth = bg.properties.outline.width; + ctx.moveTo(outlineOffsetWidth, outlineOffsetWidth); + // TL, TR, BR, BL + ctx.lineTo(bgWidth - outlineOffsetWidth, outlineOffsetWidth); + ctx.lineTo(bgWidth - outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, outlineOffsetWidth); + // Diagonals + ctx.moveTo(0, outlineOffsetWidth); + ctx.lineTo(bgWidth, bgHeight - outlineOffsetWidth); + ctx.moveTo(0, bgHeight - outlineOffsetWidth); + ctx.lineTo(bgWidth, outlineOffsetWidth); + ctx.stroke(); + } + + var textGroup = root.children.holderTextGroup; + ctx.font = textGroup.properties.font.weight + ' ' + (dpr * textGroup.properties.font.size) + textGroup.properties.font.units + ' ' + textGroup.properties.font.family + ', monospace'; + ctx.fillStyle = textGroup.properties.fill; + + for (var lineKey in textGroup.children) { + var line = textGroup.children[lineKey]; + for (var wordKey in line.children) { + var word = line.children[wordKey]; + var x = dpr * (textGroup.x + line.x + word.x); + var y = dpr * (textGroup.y + line.y + word.y + (textGroup.properties.leading / 2)); + + ctx.fillText(word.properties.text, x, y); + } + } + + return canvas.toDataURL('image/png'); + }; + })(); + +/***/ }) +/******/ ]) +}); +; +(function(ctx, isMeteorPackage) { + if (isMeteorPackage) { + Holder = ctx.Holder; + } +})(this, typeof Meteor !== 'undefined' && typeof Package !== 'undefined'); diff --git a/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.min.js b/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.min.js new file mode 100644 index 0000000..6935bf1 --- /dev/null +++ b/BlazorStudy.Bootstrap4Study/wwwroot/plugs/holder/holder.min.js @@ -0,0 +1,14 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +!function(e){if(e.document){var t=e.document;t.querySelectorAll||(t.querySelectorAll=function(n){var r,i=t.createElement("style"),a=[];for(t.documentElement.firstChild.appendChild(i),t._qsa=[],i.styleSheet.cssText=n+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",e.scrollBy(0,0),i.parentNode.removeChild(i);t._qsa.length;)r=t._qsa.shift(),r.style.removeAttribute("x-qsa"),a.push(r);return t._qsa=null,a}),t.querySelector||(t.querySelector=function(e){var n=t.querySelectorAll(e);return n.length?n[0]:null}),t.getElementsByClassName||(t.getElementsByClassName=function(e){return e=String(e).replace(/^|\s+/g,"."),t.querySelectorAll(e)}),Object.keys||(Object.keys=function(e){if(e!==Object(e))throw TypeError("Object.keys called on non-object");var t,n=[];for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.push(t);return n}),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError();var r,i=arguments[1];for(r=0;n>r;r++)r in t&&e.call(i,t[r],r,t)}),function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";e.atob=e.atob||function(e){e=String(e);var n,r=0,i=[],a=0,o=0;if(e=e.replace(/\s/g,""),e.length%4===0&&(e=e.replace(/=+$/,"")),e.length%4===1)throw Error("InvalidCharacterError");if(/[^+\/0-9A-Za-z]/.test(e))throw Error("InvalidCharacterError");for(;r>16&255)),i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a)),o=0,a=0),r+=1;return 12===o?(a>>=4,i.push(String.fromCharCode(255&a))):18===o&&(a>>=2,i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a))),i.join("")},e.btoa=e.btoa||function(e){e=String(e);var n,r,i,a,o,s,l,h=0,u=[];if(/[^\x00-\xFF]/.test(e))throw Error("InvalidCharacterError");for(;h>2,o=(3&n)<<4|r>>4,s=(15&r)<<2|i>>6,l=63&i,h===e.length+2?(s=64,l=64):h===e.length+1&&(l=64),u.push(t.charAt(a),t.charAt(o),t.charAt(s),t.charAt(l));return u.join("")}}(e),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(e){var t=this.__proto__||this.constructor.prototype;return e in this&&(!(e in t)||t[e]!==this[e])}),function(){if("performance"in e==!1&&(e.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in e.performance==!1){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),e.performance.now=function(){return Date.now()-t}}}(),e.requestAnimationFrame||(e.webkitRequestAnimationFrame&&e.webkitCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return webkitRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.webkitCancelAnimationFrame}(e):e.mozRequestAnimationFrame&&e.mozCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return mozRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.mozCancelAnimationFrame}(e):!function(e){e.requestAnimationFrame=function(t){return e.setTimeout(t,1e3/60)},e.cancelAnimationFrame=e.clearTimeout}(e))}}(this),function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Holder=t():e.Holder=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){(function(t){function r(e,t,n,r){var o=i(n.substr(n.lastIndexOf(e.domain)),e);o&&a({mode:null,el:r,flags:o,engineSettings:t})}function i(e,t){var n={theme:T(O.settings.themes.gray,null),stylesheets:t.stylesheets,instanceOptions:t},r=e.indexOf("?"),i=[e];-1!==r&&(i=[e.slice(0,r),e.slice(r+1)]);var a=i[0].split("/");n.holderURL=e;var o=a[1],s=o.match(/([\d]+p?)x([\d]+p?)/);if(!s)return!1;if(n.fluid=-1!==o.indexOf("p"),n.dimensions={width:s[1].replace("p","%"),height:s[2].replace("p","%")},2===i.length){var l=v.parse(i[1]);if(w.truthy(l.ratio)){n.fluid=!0;var h=parseFloat(n.dimensions.width.replace("%","")),u=parseFloat(n.dimensions.height.replace("%",""));u=Math.floor(100*(u/h)),h=100,n.dimensions.width=h+"%",n.dimensions.height=u+"%"}if(n.auto=w.truthy(l.auto),l.bg&&(n.theme.bg=w.parseColor(l.bg)),l.fg&&(n.theme.fg=w.parseColor(l.fg)),l.bg&&!l.fg&&(n.autoFg=!0),l.theme&&n.instanceOptions.themes.hasOwnProperty(l.theme)&&(n.theme=T(n.instanceOptions.themes[l.theme],null)),l.text&&(n.text=l.text),l.textmode&&(n.textmode=l.textmode),l.size&&parseFloat(l.size)&&(n.size=parseFloat(l.size)),l.font&&(n.font=l.font),l.align&&(n.align=l.align),l.lineWrap&&(n.lineWrap=l.lineWrap),n.nowrap=w.truthy(l.nowrap),n.outline=w.truthy(l.outline),w.truthy(l.random)){O.vars.cache.themeKeys=O.vars.cache.themeKeys||Object.keys(n.instanceOptions.themes);var d=O.vars.cache.themeKeys[0|Math.random()*O.vars.cache.themeKeys.length];n.theme=T(n.instanceOptions.themes[d],null)}}return n}function a(e){var t=e.mode,n=e.el,r=e.flags,i=e.engineSettings,a=r.dimensions,s=r.theme,l=a.width+"x"+a.height;t=null==t?r.fluid?"fluid":"image":t;var d=/holder_([a-z]+)/g,c=!1;if(null!=r.text&&(s.text=r.text,"object"===n.nodeName.toLowerCase())){for(var f=s.text.split("\\n"),p=0;p1){var b,x=0,A=0,C=0;w=new s.Group("line"+C),("left"===e.align||"right"===e.align)&&(a=e.width*(1-2*(1-r)));for(var E=0;E=a||k===!0)&&(t(g,w,x,g.properties.leading),g.add(w),x=0,A+=g.properties.leading,C+=1,w=new s.Group("line"+C),w.y=A),k!==!0&&(v.moveTo(x,0),x+=m.spaceWidth+T.width,w.add(v))}if(t(g,w,x,g.properties.leading),g.add(w),"left"===e.align)g.moveTo(e.width-i,null,null);else if("right"===e.align){for(b in g.children)w=g.children[b],w.moveTo(e.width-w.width,null,null);g.moveTo(0-(e.width-i),null,null)}else{for(b in g.children)w=g.children[b],w.moveTo((g.width-w.width)/2,null,null);g.moveTo((e.width-g.width)/2,null,null)}g.moveTo(null,(e.height-g.height)/2,null),(e.height-g.height)/2<0&&g.moveTo(null,0,null)}else v=new s.Text(e.text),w=new s.Group("line0"),w.add(v),g.add(w),"left"===e.align?g.moveTo(e.width-i,null,null):"right"===e.align?g.moveTo(0-(e.width-i),null,null):g.moveTo((e.width-m.boundingBox.width)/2,null,null),g.moveTo(null,(e.height-m.boundingBox.height)/2,null);return o}function l(e,t,n,r){var i=parseInt(e,10),a=parseInt(t,10),o=Math.max(i,a),s=Math.min(i,a),l=.8*Math.min(s,o*r);return Math.round(Math.max(n,l))}function h(e){var t;t=null==e||null==e.nodeType?O.vars.resizableImages:[e];for(var n=0,r=t.length;r>n;n++){var i=t[n];if(i.holderData){var a=i.holderData.flags,s=k(i);if(s){if(!i.holderData.resizeUpdate)continue;if(a.fluid&&a.auto){var l=i.holderData.fluidConfig;switch(l.mode){case"width":s.height=s.width/l.ratio;break;case"height":s.width=s.height*l.ratio}}var h={mode:"image",holderSettings:{dimensions:s,theme:a.theme,flags:a},el:i,engineSettings:i.holderData.engineSettings};"exact"==a.textmode&&(a.exactDimensions=s,h.holderSettings.dimensions=a.dimensions),o(h)}else f(i)}}}function u(e){if(e.holderData){var t=k(e);if(t){var n=e.holderData.flags,r={fluidHeight:"%"==n.dimensions.height.slice(-1),fluidWidth:"%"==n.dimensions.width.slice(-1),mode:null,initialDimensions:t};r.fluidWidth&&!r.fluidHeight?(r.mode="width",r.ratio=r.initialDimensions.width/parseFloat(n.dimensions.height)):!r.fluidWidth&&r.fluidHeight&&(r.mode="height",r.ratio=parseFloat(n.dimensions.width)/r.initialDimensions.height),e.holderData.fluidConfig=r}else f(e)}}function d(){var e,n=[],r=Object.keys(O.vars.invisibleImages);r.forEach(function(t){e=O.vars.invisibleImages[t],k(e)&&"img"==e.nodeName.toLowerCase()&&(n.push(e),delete O.vars.invisibleImages[t])}),n.length&&j.run({images:n}),setTimeout(function(){t.requestAnimationFrame(d)},10)}function c(){O.vars.visibilityCheckStarted||(t.requestAnimationFrame(d),O.vars.visibilityCheckStarted=!0)}function f(e){e.holderData.invisibleId||(O.vars.invisibleId+=1,O.vars.invisibleImages["i"+O.vars.invisibleId]=e,e.holderData.invisibleId=O.vars.invisibleId)}function p(e){O.vars.debounceTimer||e.call(this),O.vars.debounceTimer&&t.clearTimeout(O.vars.debounceTimer),O.vars.debounceTimer=t.setTimeout(function(){O.vars.debounceTimer=null,e.call(this)},O.setup.debounce)}function g(){p(function(){h(null)})}var m=n(2),v=n(3),y=n(6),w=n(7),b=n(8),x=n(9),S=n(10),A=n(11),C=n(12),E=n(15),T=w.extend,k=w.dimensionCheck,F=A.svg_ns,j={version:A.version,addTheme:function(e,t){return null!=e&&null!=t&&(O.settings.themes[e]=t),delete O.vars.cache.themeKeys,this},addImage:function(e,t){var n=x.getNodeArray(t);return n.forEach(function(t){var n=x.newEl("img"),r={};r[O.setup.dataAttr]=e,x.setAttr(n,r),t.appendChild(n)}),this},setResizeUpdate:function(e,t){e.holderData&&(e.holderData.resizeUpdate=!!t,e.holderData.resizeUpdate&&h(e))},run:function(e){e=e||{};var n={},o=T(O.settings,e);O.vars.preempted=!0,O.vars.dataAttr=o.dataAttr||O.setup.dataAttr,n.renderer=o.renderer?o.renderer:O.setup.renderer,-1===O.setup.renderers.join(",").indexOf(n.renderer)&&(n.renderer=O.setup.supportsSVG?"svg":O.setup.supportsCanvas?"canvas":"html");var s=x.getNodeArray(o.images),l=x.getNodeArray(o.bgnodes),h=x.getNodeArray(o.stylenodes),u=x.getNodeArray(o.objects);return n.stylesheets=[],n.svgXMLStylesheet=!0,n.noFontFallback=!!o.noFontFallback,n.noBackgroundSize=!!o.noBackgroundSize,h.forEach(function(e){if(e.attributes.rel&&e.attributes.href&&"stylesheet"==e.attributes.rel.value){var t=e.attributes.href.value,r=x.newEl("a");r.href=t;var i=r.protocol+"//"+r.host+r.pathname+r.search;n.stylesheets.push(i)}}),l.forEach(function(e){if(t.getComputedStyle){var r=t.getComputedStyle(e,null).getPropertyValue("background-image"),s=e.getAttribute("data-background-src"),l=s||r,h=null,u=o.domain+"/",d=l.indexOf(u);if(0===d)h=l;else if(1===d&&"?"===l[0])h=l.slice(1);else{var c=l.substr(d).match(/([^\"]*)"?\)/);if(null!==c)h=c[1];else if(0===l.indexOf("url("))throw"Holder: unable to parse background URL: "+l}if(h){var f=i(h,o);f&&a({mode:"background",el:e,flags:f,engineSettings:n})}}}),u.forEach(function(e){var t={};try{t.data=e.getAttribute("data"),t.dataSrc=e.getAttribute(O.vars.dataAttr)}catch(i){}var a=null!=t.data&&0===t.data.indexOf(o.domain),s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain);a?r(o,n,t.data,e):s&&r(o,n,t.dataSrc,e)}),s.forEach(function(e){var t={};try{t.src=e.getAttribute("src"),t.dataSrc=e.getAttribute(O.vars.dataAttr),t.rendered=e.getAttribute("data-holder-rendered")}catch(i){}var a=null!=t.src,s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain),l=null!=t.rendered&&"true"==t.rendered;a?0===t.src.indexOf(o.domain)?r(o,n,t.src,e):s&&(l?r(o,n,t.dataSrc,e):!function(e,t,n,i,a){w.imageExists(e,function(e){e||r(t,n,i,a)})}(t.src,o,n,t.dataSrc,e)):s&&r(o,n,t.dataSrc,e)}),this}},O={settings:{domain:"holder.js",images:"img",objects:"object",bgnodes:"body .holderjs",stylenodes:"head link.holderjs",themes:{gray:{bg:"#EEEEEE",fg:"#AAAAAA"},social:{bg:"#3a5a97",fg:"#FFFFFF"},industrial:{bg:"#434A52",fg:"#C2F200"},sky:{bg:"#0D8FDB",fg:"#FFFFFF"},vine:{bg:"#39DBAC",fg:"#1E292C"},lava:{bg:"#F8591A",fg:"#1C2846"}}},defaults:{size:10,units:"pt",scale:1/16}},z=function(){var e=null,t=null,n=null;return function(r){var i=r.root;if(O.setup.supportsSVG){var a=!1,o=function(e){return document.createTextNode(e)};(null==e||e.parentNode!==document.body)&&(a=!0),e=b.initSVG(e,i.properties.width,i.properties.height),e.style.display="block",a&&(t=x.newEl("text",F),n=o(null),x.setAttr(t,{x:0}),t.appendChild(n),e.appendChild(t),document.body.appendChild(e),e.style.visibility="hidden",e.style.position="absolute",e.style.top="-100%",e.style.left="-100%");var s=i.children.holderTextGroup,l=s.properties;x.setAttr(t,{y:l.font.size,style:w.cssProps({"font-weight":l.font.weight,"font-size":l.font.size+l.font.units,"font-family":l.font.family})});var h=x.newEl("textarea");h.innerHTML=l.text,n.nodeValue=h.value;var u=t.getBBox(),d=Math.ceil(u.width/i.properties.width),c=l.text.split(" "),f=l.text.match(/\\n/g);d+=null==f?0:f.length,n.nodeValue=l.text.replace(/[ ]+/g,"");var p=t.getComputedTextLength(),g=u.width-p,m=Math.round(g/Math.max(1,c.length-1)),v=[];if(d>1){n.nodeValue="";for(var y=0;y=0?t:1)}function a(e){x?i(e):S.push(e)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function C(){document.removeEventListener("DOMContentLoaded",C,!1),document.readyState="complete"},!1),document.readyState="loading");var o=e.document,s=o.documentElement,l="load",h=!1,u="on"+l,d="complete",c="readyState",f="attachEvent",p="detachEvent",g="addEventListener",m="DOMContentLoaded",v="onreadystatechange",y="removeEventListener",w=g in o,b=h,x=h,S=[];if(o[c]===d)i(t);else if(w)o[g](m,n,h),e[g](l,n,h);else{o[f](v,n),e[f](u,n);try{b=null==e.frameElement&&s}catch(A){}b&&b.doScroll&&!function E(){if(!x){try{b.doScroll("left")}catch(e){return i(E,50)}r(),t()}}()}return a.version="1.4.0",a.isReady=function(){return x},a}e.exports="undefined"!=typeof window&&n(window)},function(e,t,n){var r=encodeURIComponent,i=decodeURIComponent,a=n(4),o=n(5),s=/(\w+)\[(\d+)\]/,l=/\w+\.\w+/;t.parse=function(e){if("string"!=typeof e)return{};if(e=a(e),""===e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t={},n=e.split("&"),r=0;r=0;r--)n=e.charCodeAt(r),t.unshift(n>128?["&#",n,";"].join(""):e[r]);return t.join("")},t.imageExists=function(e,t){var n=new Image;n.onerror=function(){t.call(this,!1)},n.onload=function(){t.call(this,!0)},n.src=e},t.decodeHtmlEntity=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})},t.dimensionCheck=function(e){var t={height:e.clientHeight,width:e.clientWidth};return t.height&&t.width?t:!1},t.truthy=function(e){return"string"==typeof e?"true"===e||"yes"===e||"1"===e||"on"===e||"✓"===e:!!e},t.parseColor=function(e){var t,n=/(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i,r=/^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,i=/^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/,a=e.match(n);if(null!==a)return t=a[1]||a[2],"#"!==t[0]?"#"+t:t;if(a=e.match(r),null!==a)return t="rgb("+a.slice(1).join(",")+")";if(a=e.match(i),null!==a){const o=function(e){return"0."+e.split(".")[1]},s=a.slice(1).map(function(e,t){return 3===t?o(e):e});return t="rgba("+s.join(",")+")"}return null},t.canvasRatio=function(){var t=1,n=1;if(e.document){var r=e.document.createElement("canvas");if(r.getContext){var i=r.getContext("2d");t=e.devicePixelRatio||1,n=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1}}return t/n}}).call(t,function(){return this}())},function(e,t,n){(function(e){var r=n(9),i="http://www.w3.org/2000/svg",a=8;t.initSVG=function(e,t,n){var o,s,l=!1;e&&e.querySelector?(s=e.querySelector("style"),null===s&&(l=!0)):(e=r.newEl("svg",i),l=!0),l&&(o=r.newEl("defs",i),s=r.newEl("style",i),r.setAttr(s,{type:"text/css"}),o.appendChild(s),e.appendChild(o)),e.webkitMatchesSelector&&e.setAttribute("xmlns",i);for(var h=0;h=0;l--){var h=s.createProcessingInstruction("xml-stylesheet",'href="'+o[l]+'" rel="stylesheet"');s.insertBefore(h,s.firstChild)}s.removeChild(s.documentElement),a=i.serializeToString(s)}var u=i.serializeToString(t);return u=u.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),a+u}}}).call(t,function(){return this}())},function(e,t){(function(e){t.newEl=function(t,n){return e.document?null==n?e.document.createElement(t):e.document.createElementNS(n,t):void 0},t.setAttr=function(e,t){for(var n in t)e.setAttribute(n,t[n])},t.createXML=function(){return e.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0},t.getNodeArray=function(t){var n=null;return"string"==typeof t?n=document.querySelectorAll(t):e.NodeList&&t instanceof e.NodeList?n=t:e.Node&&t instanceof e.Node?n=[t]:e.HTMLCollection&&t instanceof e.HTMLCollection?n=t:t instanceof Array?n=t:null===t&&(n=[]),n=Array.prototype.slice.call(n)}}).call(t,function(){return this}())},function(e,t){var n=function(e,t){"string"==typeof e&&(this.original=e,"#"===e.charAt(0)&&(e=e.slice(1)),/[^a-f0-9]+/i.test(e)||(3===e.length&&(e=e.replace(/./g,"$&$&")),6===e.length&&(this.alpha=1,t&&t.alpha&&(this.alpha=t.alpha),this.set(parseInt(e,16)))))};n.rgb2hex=function(e,t,n){function r(e){var t=(0|e).toString(16);return 16>e&&(t="0"+t),t}return[e,t,n].map(r).join("")},n.hsl2rgb=function(e,t,n){var r=e/60,i=(1-Math.abs(2*n-1))*t,a=i*(1-Math.abs(parseInt(r)%2-1)),o=n-i/2,s=0,l=0,h=0;return r>=0&&1>r?(s=i,l=a):r>=1&&2>r?(s=a,l=i):r>=2&&3>r?(l=i,h=a):r>=3&&4>r?(l=a,h=i):r>=4&&5>r?(s=a,h=i):r>=5&&6>r&&(s=i,h=a),s+=o,l+=o,h+=o,s=parseInt(255*s),l=parseInt(255*l),h=parseInt(255*h),[s,l,h]},n.prototype.set=function(e){this.raw=e;var t=(16711680&this.raw)>>16,n=(65280&this.raw)>>8,r=255&this.raw,i=.2126*t+.7152*n+.0722*r,a=-.09991*t-.33609*n+.436*r,o=.615*t-.55861*n-.05639*r;return this.rgb={r:t,g:n,b:r},this.yuv={y:i,u:a,v:o},this},n.prototype.lighten=function(e){var t=Math.min(1,Math.max(0,Math.abs(e)))*(0>e?-1:1),r=255*t|0,i=Math.min(255,Math.max(0,this.rgb.r+r)),a=Math.min(255,Math.max(0,this.rgb.g+r)),o=Math.min(255,Math.max(0,this.rgb.b+r)),s=n.rgb2hex(i,a,o);return new n(s)},n.prototype.toHex=function(e){return(e?"#":"")+this.raw.toString(16)},n.prototype.lighterThan=function(e){return e instanceof n||(e=new n(e)),this.yuv.y>e.yuv.y},n.prototype.blendAlpha=function(e){e instanceof n||(e=new n(e));var t=e,r=this,i=t.alpha*t.rgb.r+(1-t.alpha)*r.rgb.r,a=t.alpha*t.rgb.g+(1-t.alpha)*r.rgb.g,o=t.alpha*t.rgb.b+(1-t.alpha)*r.rgb.b;return new n(n.rgb2hex(i,a,o))},e.exports=n},function(e,t){e.exports={version:"2.9.7",svg_ns:"http://www.w3.org/2000/svg"}},function(e,t,n){function r(e,t){return d.element({tag:t,width:e.width,height:e.height,fill:e.properties.fill})}function i(e){return h.cssProps({fill:e.fill,"font-weight":e.font.weight,"font-family":e.font.family+", monospace","font-size":e.font.size+e.font.units})}function a(e,t,n){var r=n/2;return["M",r,r,"H",e-r,"V",t-r,"H",r,"V",0,"M",0,r,"L",e,t-r,"M",0,t-r,"L",e,r].join(" ")}var o=n(13),s=n(8),l=n(11),h=n(7),u=l.svg_ns,d={element:function(e){var t=e.tag,n=e.content||"";return delete e.tag,delete e.content,[t,n,e]}};e.exports=function(e,t){var n=t.engineSettings,l=n.stylesheets,h=l.map(function(e){return''}).join("\n"),c="holder_"+Number(new Date).toString(16),f=e.root,p=f.children.holderTextGroup,g="#"+c+" text { "+i(p.properties)+" } ";p.y+=.8*p.textPositionData.boundingBox.height;var m=[];Object.keys(p.children).forEach(function(e){var t=p.children[e];Object.keys(t.children).forEach(function(e){var n=t.children[e],r=p.x+t.x+n.x,i=p.y+t.y+n.y,a=d.element({tag:"text",content:n.properties.text,x:r,y:i});m.push(a)})});var v=d.element({tag:"g",content:m}),y=null;if(f.children.holderBg.properties.outline){var w=f.children.holderBg.properties.outline;y=d.element({tag:"path",d:a(f.children.holderBg.width,f.children.holderBg.height,w.width),"stroke-width":w.width,stroke:w.fill,fill:"none"})}var b=r(f.children.holderBg,"rect"),x=[];x.push(b),w&&x.push(y),x.push(v);var S=d.element({tag:"g",id:c,content:x}),A=d.element({tag:"style",content:g,type:"text/css"}),C=d.element({tag:"defs",content:A}),E=d.element({tag:"svg",content:[C,S],width:f.properties.width,height:f.properties.height,xmlns:u,viewBox:[0,0,f.properties.width,f.properties.height].join(" "),preserveAspectRatio:"none"}),T=o(E);/\&(x)?#[0-9A-Fa-f]/.test(T[0])&&(T[0]=T[0].replace(/&#/gm,"&#")),T=h+T[0];var k=s.svgStringToDataURI(T,"background"===t.mode);return k}},function(e,t,n){n(14);e.exports=function r(e,t,n){"use strict";function i(e){var t=e.match(/^[\w-]+/),r={tag:t?t[0]:"div",attr:{},children:[]},i=e.match(/#([\w-]+)/),a=e.match(/\$([\w-]+)/),o=e.match(/\.[\w-]+/g);return i&&(r.attr.id=i[1],n[i[1]]=r),a&&(n[a[1]]=r),o&&(r.attr["class"]=o.join(" ").replace(/\./g,"")),e.match(/&$/g)&&(f=!1),r}function a(e,t){return null!==t&&t!==!1&&void 0!==t?"string"!=typeof t&&"object"!=typeof t?String(t):t:void 0}function o(e){return e||0===e?String(e).replace(/&/g,"&").replace(/"/g,"""):""}function s(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}var l,h,u,d,c=1,f=!0;if(n=n||{},"string"==typeof e[0])e[0]=i(e[0]);else{if(!Array.isArray(e[0]))throw new Error("First element of array must be a string, or an array and not "+JSON.stringify(e[0]));c=0}for(;c",e[0]=l}return n[0]=e[0],u&&u(e[0]),n}},function(e,t){"use strict";function n(e){var t=""+e,n=r.exec(t);if(!n)return t;var i,a="",o=0,s=0;for(o=n.index;o]/;e.exports=n},function(e,t,n){var r=n(9),i=n(7);e.exports=function(){var e=r.newEl("canvas"),t=null;return function(n){null==t&&(t=e.getContext("2d"));var r=i.canvasRatio(),a=n.root;e.width=r*a.properties.width,e.height=r*a.properties.height,t.textBaseline="middle";var o=a.children.holderBg,s=r*o.width,l=r*o.height,h=2,u=h/2;t.fillStyle=o.properties.fill,t.fillRect(0,0,s,l),o.properties.outline&&(t.strokeStyle=o.properties.outline.fill,t.lineWidth=o.properties.outline.width,t.moveTo(u,u),t.lineTo(s-u,u),t.lineTo(s-u,l-u),t.lineTo(u,l-u),t.lineTo(u,u),t.moveTo(0,u),t.lineTo(s,l-u),t.moveTo(0,l-u),t.lineTo(s,u),t.stroke());var d=a.children.holderTextGroup;t.font=d.properties.font.weight+" "+r*d.properties.font.size+d.properties.font.units+" "+d.properties.font.family+", monospace",t.fillStyle=d.properties.fill;for(var c in d.children){var f=d.children[c];for(var p in f.children){var g=f.children[p],m=r*(d.x+f.x+g.x),v=r*(d.y+f.y+g.y+d.properties.leading/2); + +t.fillText(g.properties.text,m,v)}}return e.toDataURL("image/png")}}()}])}),function(e,t){t&&(Holder=e.Holder)}(this,"undefined"!=typeof Meteor&&"undefined"!=typeof Package); \ No newline at end of file diff --git a/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.js b/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.js new file mode 100644 index 0000000..db1e43b --- /dev/null +++ b/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.js @@ -0,0 +1,3063 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +(function (window) { + if (!window.document) return; + var document = window.document; + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + if (!document.querySelectorAll) { + document.querySelectorAll = function (selectors) { + var style = document.createElement('style'), elements = [], element; + document.documentElement.firstChild.appendChild(style); + document._qsa = []; + + style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}'; + window.scrollBy(0, 0); + style.parentNode.removeChild(style); + + while (document._qsa.length) { + element = document._qsa.shift(); + element.style.removeAttribute('x-qsa'); + elements.push(element); + } + document._qsa = null; + return elements; + }; + } + + if (!document.querySelector) { + document.querySelector = function (selectors) { + var elements = document.querySelectorAll(selectors); + return (elements.length) ? elements[0] : null; + }; + } + + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (classNames) { + classNames = String(classNames).replace(/^|\s+/g, '.'); + return document.querySelectorAll(classNames); + }; + } + + //https://github.com/inexorabletash/polyfill + // ES5 15.2.3.14 Object.keys ( O ) + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys + if (!Object.keys) { + Object.keys = function (o) { + if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); } + var ret = [], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + ret.push(p); + } + } + return ret; + }; + } + + // ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] ) + // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun /*, thisp */) { + if (this === void 0 || this === null) { throw TypeError(); } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { throw TypeError(); } + + var thisp = arguments[1], i; + for (i = 0; i < len; i++) { + if (i in t) { + fun.call(thisp, t[i], i, t); + } + } + }; + } + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + (function (global) { + var B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + global.atob = global.atob || function (input) { + input = String(input); + var position = 0, + output = [], + buffer = 0, bits = 0, n; + + input = input.replace(/\s/g, ''); + if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); } + if ((input.length % 4) === 1) { throw Error('InvalidCharacterError'); } + if (/[^+/0-9A-Za-z]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + n = B64_ALPHABET.indexOf(input.charAt(position)); + buffer = (buffer << 6) | n; + bits += 6; + + if (bits === 24) { + output.push(String.fromCharCode((buffer >> 16) & 0xFF)); + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + bits = 0; + buffer = 0; + } + position += 1; + } + + if (bits === 12) { + buffer = buffer >> 4; + output.push(String.fromCharCode(buffer & 0xFF)); + } else if (bits === 18) { + buffer = buffer >> 2; + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + } + + return output.join(''); + }; + + global.btoa = global.btoa || function (input) { + input = String(input); + var position = 0, + out = [], + o1, o2, o3, + e1, e2, e3, e4; + + if (/[^\x00-\xFF]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + o1 = input.charCodeAt(position++); + o2 = input.charCodeAt(position++); + o3 = input.charCodeAt(position++); + + // 111111 112222 222233 333333 + e1 = o1 >> 2; + e2 = ((o1 & 0x3) << 4) | (o2 >> 4); + e3 = ((o2 & 0xf) << 2) | (o3 >> 6); + e4 = o3 & 0x3f; + + if (position === input.length + 2) { + e3 = 64; e4 = 64; + } + else if (position === input.length + 1) { + e4 = 64; + } + + out.push(B64_ALPHABET.charAt(e1), + B64_ALPHABET.charAt(e2), + B64_ALPHABET.charAt(e3), + B64_ALPHABET.charAt(e4)); + } + + return out.join(''); + }; + }(window)); + + //https://gist.github.com/jimeh/332357 + if (!Object.prototype.hasOwnProperty){ + /*jshint -W001, -W103 */ + Object.prototype.hasOwnProperty = function(prop) { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + }; + /*jshint +W001, +W103 */ + } + + // @license http://opensource.org/licenses/MIT + // copyright Paul Irish 2015 + + + // Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill + // github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js + // as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values + + // if you want values similar to what you'd get with real perf.now, place this towards the head of the page + // but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed + + + (function(){ + + if ('performance' in window === false) { + window.performance = {}; + } + + Date.now = (Date.now || function () { // thanks IE8 + return new Date().getTime(); + }); + + if ('now' in window.performance === false){ + + var nowOffset = Date.now(); + + if (performance.timing && performance.timing.navigationStart){ + nowOffset = performance.timing.navigationStart; + } + + window.performance.now = function now(){ + return Date.now() - nowOffset; + }; + } + + })(); + + //requestAnimationFrame polyfill for older Firefox/Chrome versions + if (!window.requestAnimationFrame) { + if (window.webkitRequestAnimationFrame && window.webkitCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-webkit.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return webkitRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.webkitCancelAnimationFrame; + }(window)); + } else if (window.mozRequestAnimationFrame && window.mozCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-moz.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return mozRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.mozCancelAnimationFrame; + }(window)); + } else { + (function (global) { + global.requestAnimationFrame = function (callback) { + return global.setTimeout(callback, 1000 / 60); + }; + + global.cancelAnimationFrame = global.clearTimeout; + })(window); + } + } +})(this); + +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Holder"] = factory(); + else + root["Holder"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - https://imsky.co + */ + + module.exports = __webpack_require__(1); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - http://imsky.co + */ + + //Libraries and functions + var onDomReady = __webpack_require__(2); + var querystring = __webpack_require__(3); + + var SceneGraph = __webpack_require__(6); + var utils = __webpack_require__(7); + var SVG = __webpack_require__(8); + var DOM = __webpack_require__(9); + var Color = __webpack_require__(10); + var constants = __webpack_require__(11); + + var svgRenderer = __webpack_require__(12); + var sgCanvasRenderer = __webpack_require__(15); + + var extend = utils.extend; + var dimensionCheck = utils.dimensionCheck; + + //Constants and definitions + var SVG_NS = constants.svg_ns; + + var Holder = { + version: constants.version, + + /** + * Adds a theme to default settings + * + * @param {string} name Theme name + * @param {Object} theme Theme object, with foreground, background, size, font, and fontweight properties. + */ + addTheme: function(name, theme) { + name != null && theme != null && (App.settings.themes[name] = theme); + delete App.vars.cache.themeKeys; + return this; + }, + + /** + * Appends a placeholder to an element + * + * @param {string} src Placeholder URL string + * @param el A selector or a reference to a DOM node + */ + addImage: function(src, el) { + //todo: use jquery fallback if available for all QSA references + var nodes = DOM.getNodeArray(el); + nodes.forEach(function (node) { + var img = DOM.newEl('img'); + var domProps = {}; + domProps[App.setup.dataAttr] = src; + DOM.setAttr(img, domProps); + node.appendChild(img); + }); + return this; + }, + + /** + * Sets whether or not an image is updated on resize. + * If an image is set to be updated, it is immediately rendered. + * + * @param {Object} el Image DOM element + * @param {Boolean} value Resizable update flag value + */ + setResizeUpdate: function(el, value) { + if (el.holderData) { + el.holderData.resizeUpdate = !!value; + if (el.holderData.resizeUpdate) { + updateResizableElements(el); + } + } + }, + + /** + * Runs Holder with options. By default runs Holder on all images with "holder.js" in their source attributes. + * + * @param {Object} userOptions Options object, can contain domain, themes, images, and bgnodes properties + */ + run: function(userOptions) { + //todo: split processing into separate queues + userOptions = userOptions || {}; + var engineSettings = {}; + var options = extend(App.settings, userOptions); + + App.vars.preempted = true; + App.vars.dataAttr = options.dataAttr || App.setup.dataAttr; + + engineSettings.renderer = options.renderer ? options.renderer : App.setup.renderer; + if (App.setup.renderers.join(',').indexOf(engineSettings.renderer) === -1) { + engineSettings.renderer = App.setup.supportsSVG ? 'svg' : (App.setup.supportsCanvas ? 'canvas' : 'html'); + } + + var images = DOM.getNodeArray(options.images); + var bgnodes = DOM.getNodeArray(options.bgnodes); + var stylenodes = DOM.getNodeArray(options.stylenodes); + var objects = DOM.getNodeArray(options.objects); + + engineSettings.stylesheets = []; + engineSettings.svgXMLStylesheet = true; + engineSettings.noFontFallback = !!options.noFontFallback; + engineSettings.noBackgroundSize = !!options.noBackgroundSize; + + stylenodes.forEach(function (styleNode) { + if (styleNode.attributes.rel && styleNode.attributes.href && styleNode.attributes.rel.value == 'stylesheet') { + var href = styleNode.attributes.href.value; + //todo: write isomorphic relative-to-absolute URL function + var proxyLink = DOM.newEl('a'); + proxyLink.href = href; + var stylesheetURL = proxyLink.protocol + '//' + proxyLink.host + proxyLink.pathname + proxyLink.search; + engineSettings.stylesheets.push(stylesheetURL); + } + }); + + bgnodes.forEach(function (bgNode) { + //Skip processing background nodes if getComputedStyle is unavailable, since only modern browsers would be able to use canvas or SVG to render to background + if (!global.getComputedStyle) return; + var backgroundImage = global.getComputedStyle(bgNode, null).getPropertyValue('background-image'); + var dataBackgroundImage = bgNode.getAttribute('data-background-src'); + var rawURL = dataBackgroundImage || backgroundImage; + + var holderURL = null; + var holderString = options.domain + '/'; + var holderStringIndex = rawURL.indexOf(holderString); + + if (holderStringIndex === 0) { + holderURL = rawURL; + } else if (holderStringIndex === 1 && rawURL[0] === '?') { + holderURL = rawURL.slice(1); + } else { + var fragment = rawURL.substr(holderStringIndex).match(/([^\"]*)"?\)/); + if (fragment !== null) { + holderURL = fragment[1]; + } else if (rawURL.indexOf('url(') === 0) { + throw 'Holder: unable to parse background URL: ' + rawURL; + } + } + + if (holderURL) { + var holderFlags = parseURL(holderURL, options); + if (holderFlags) { + prepareDOMElement({ + mode: 'background', + el: bgNode, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + }); + + objects.forEach(function (object) { + var objectAttr = {}; + + try { + objectAttr.data = object.getAttribute('data'); + objectAttr.dataSrc = object.getAttribute(App.vars.dataAttr); + } catch (e) {} + + var objectHasSrcURL = objectAttr.data != null && objectAttr.data.indexOf(options.domain) === 0; + var objectHasDataSrcURL = objectAttr.dataSrc != null && objectAttr.dataSrc.indexOf(options.domain) === 0; + + if (objectHasSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.data, object); + } else if (objectHasDataSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.dataSrc, object); + } + }); + + images.forEach(function (image) { + var imageAttr = {}; + + try { + imageAttr.src = image.getAttribute('src'); + imageAttr.dataSrc = image.getAttribute(App.vars.dataAttr); + imageAttr.rendered = image.getAttribute('data-holder-rendered'); + } catch (e) {} + + var imageHasSrc = imageAttr.src != null; + var imageHasDataSrcURL = imageAttr.dataSrc != null && imageAttr.dataSrc.indexOf(options.domain) === 0; + var imageRendered = imageAttr.rendered != null && imageAttr.rendered == 'true'; + + if (imageHasSrc) { + if (imageAttr.src.indexOf(options.domain) === 0) { + prepareImageElement(options, engineSettings, imageAttr.src, image); + } else if (imageHasDataSrcURL) { + //Image has a valid data-src and an invalid src + if (imageRendered) { + //If the placeholder has already been render, re-render it + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } else { + //If the placeholder has not been rendered, check if the image exists and render a fallback if it doesn't + (function(src, options, engineSettings, dataSrc, image) { + utils.imageExists(src, function(exists) { + if (!exists) { + prepareImageElement(options, engineSettings, dataSrc, image); + } + }); + })(imageAttr.src, options, engineSettings, imageAttr.dataSrc, image); + } + } + } else if (imageHasDataSrcURL) { + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } + }); + + return this; + } + }; + + var App = { + settings: { + domain: 'holder.js', + images: 'img', + objects: 'object', + bgnodes: 'body .holderjs', + stylenodes: 'head link.holderjs', + themes: { + 'gray': { + bg: '#EEEEEE', + fg: '#AAAAAA' + }, + 'social': { + bg: '#3a5a97', + fg: '#FFFFFF' + }, + 'industrial': { + bg: '#434A52', + fg: '#C2F200' + }, + 'sky': { + bg: '#0D8FDB', + fg: '#FFFFFF' + }, + 'vine': { + bg: '#39DBAC', + fg: '#1E292C' + }, + 'lava': { + bg: '#F8591A', + fg: '#1C2846' + } + } + }, + defaults: { + size: 10, + units: 'pt', + scale: 1 / 16 + } + }; + + /** + * Processes provided source attribute and sets up the appropriate rendering workflow + * + * @private + * @param options Instance options from Holder.run + * @param renderSettings Instance configuration + * @param src Image URL + * @param el Image DOM element + */ + function prepareImageElement(options, engineSettings, src, el) { + var holderFlags = parseURL(src.substr(src.lastIndexOf(options.domain)), options); + if (holderFlags) { + prepareDOMElement({ + mode: null, + el: el, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + + /** + * Processes a Holder URL and extracts configuration from query string + * + * @private + * @param url URL + * @param instanceOptions Instance options from Holder.run + */ + function parseURL(url, instanceOptions) { + var holder = { + theme: extend(App.settings.themes.gray, null), + stylesheets: instanceOptions.stylesheets, + instanceOptions: instanceOptions + }; + + var firstQuestionMark = url.indexOf('?'); + var parts = [url]; + + if (firstQuestionMark !== -1) { + parts = [url.slice(0, firstQuestionMark), url.slice(firstQuestionMark + 1)]; + } + + var basics = parts[0].split('/'); + + holder.holderURL = url; + + var dimensions = basics[1]; + var dimensionData = dimensions.match(/([\d]+p?)x([\d]+p?)/); + + if (!dimensionData) return false; + + holder.fluid = dimensions.indexOf('p') !== -1; + + holder.dimensions = { + width: dimensionData[1].replace('p', '%'), + height: dimensionData[2].replace('p', '%') + }; + + if (parts.length === 2) { + var options = querystring.parse(parts[1]); + + // Dimensions + + if (utils.truthy(options.ratio)) { + holder.fluid = true; + var ratioWidth = parseFloat(holder.dimensions.width.replace('%', '')); + var ratioHeight = parseFloat(holder.dimensions.height.replace('%', '')); + + ratioHeight = Math.floor(100 * (ratioHeight / ratioWidth)); + ratioWidth = 100; + + holder.dimensions.width = ratioWidth + '%'; + holder.dimensions.height = ratioHeight + '%'; + } + + holder.auto = utils.truthy(options.auto); + + // Colors + + if (options.bg) { + holder.theme.bg = utils.parseColor(options.bg); + } + + if (options.fg) { + holder.theme.fg = utils.parseColor(options.fg); + } + + //todo: add automatic foreground to themes without foreground + if (options.bg && !options.fg) { + holder.autoFg = true; + } + + if (options.theme && holder.instanceOptions.themes.hasOwnProperty(options.theme)) { + holder.theme = extend(holder.instanceOptions.themes[options.theme], null); + } + + // Text + + if (options.text) { + holder.text = options.text; + } + + if (options.textmode) { + holder.textmode = options.textmode; + } + + if (options.size && parseFloat(options.size)) { + holder.size = parseFloat(options.size); + } + + if (options.font) { + holder.font = options.font; + } + + if (options.align) { + holder.align = options.align; + } + + if (options.lineWrap) { + holder.lineWrap = options.lineWrap; + } + + holder.nowrap = utils.truthy(options.nowrap); + + // Miscellaneous + + holder.outline = utils.truthy(options.outline); + + if (utils.truthy(options.random)) { + App.vars.cache.themeKeys = App.vars.cache.themeKeys || Object.keys(holder.instanceOptions.themes); + var _theme = App.vars.cache.themeKeys[0 | Math.random() * App.vars.cache.themeKeys.length]; + holder.theme = extend(holder.instanceOptions.themes[_theme], null); + } + } + + return holder; + } + + /** + * Modifies the DOM to fit placeholders and sets up resizable image callbacks (for fluid and automatically sized placeholders) + * + * @private + * @param settings DOM prep settings + */ + function prepareDOMElement(prepSettings) { + var mode = prepSettings.mode; + var el = prepSettings.el; + var flags = prepSettings.flags; + var _engineSettings = prepSettings.engineSettings; + var dimensions = flags.dimensions, + theme = flags.theme; + var dimensionsCaption = dimensions.width + 'x' + dimensions.height; + mode = mode == null ? (flags.fluid ? 'fluid' : 'image') : mode; + var holderTemplateRe = /holder_([a-z]+)/g; + var dimensionsInText = false; + + if (flags.text != null) { + theme.text = flags.text; + + // SVG embedding doesn't parse Unicode properly + if (el.nodeName.toLowerCase() === 'object') { + var textLines = theme.text.split('\\n'); + for (var k = 0; k < textLines.length; k++) { + textLines[k] = utils.encodeHtmlEntity(textLines[k]); + } + theme.text = textLines.join('\\n'); + } + } + + if (theme.text) { + var holderTemplateMatches = theme.text.match(holderTemplateRe); + + if (holderTemplateMatches !== null) { + //todo: optimize template replacement + holderTemplateMatches.forEach(function (match) { + if (match === 'holder_dimensions') { + theme.text = theme.text.replace(match, dimensionsCaption); + } + }); + } + } + + var holderURL = flags.holderURL; + var engineSettings = extend(_engineSettings, null); + + if (flags.font) { + /* + If external fonts are used in a placeholder rendered with SVG, Holder falls back to canvas. + + This is done because Firefox and Chrome disallow embedded SVGs from referencing external assets. + The workaround is either to change the placeholder tag from to or to use the canvas renderer. + */ + theme.font = flags.font; + if (!engineSettings.noFontFallback && el.nodeName.toLowerCase() === 'img' && App.setup.supportsCanvas && engineSettings.renderer === 'svg') { + engineSettings = extend(engineSettings, { + renderer: 'canvas' + }); + } + } + + //Chrome and Opera require a quick 10ms re-render if web fonts are used with canvas + if (flags.font && engineSettings.renderer == 'canvas') { + engineSettings.reRender = true; + } + + if (mode == 'background') { + if (el.getAttribute('data-background-src') == null) { + DOM.setAttr(el, { + 'data-background-src': holderURL + }); + } + } else { + var domProps = {}; + domProps[App.vars.dataAttr] = holderURL; + DOM.setAttr(el, domProps); + } + + flags.theme = theme; + + //todo consider using all renderSettings in holderData + el.holderData = { + flags: flags, + engineSettings: engineSettings + }; + + if (mode == 'image' || mode == 'fluid') { + DOM.setAttr(el, { + 'alt': theme.text ? (dimensionsInText ? theme.text : theme.text + ' [' + dimensionsCaption + ']') : dimensionsCaption + }); + } + + var renderSettings = { + mode: mode, + el: el, + holderSettings: { + dimensions: dimensions, + theme: theme, + flags: flags + }, + engineSettings: engineSettings + }; + + if (mode == 'image') { + if (!flags.auto) { + el.style.width = dimensions.width + 'px'; + el.style.height = dimensions.height + 'px'; + } + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + render(renderSettings); + + if (flags.textmode == 'exact') { + el.holderData.resizeUpdate = true; + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } else if (mode == 'background' && engineSettings.renderer != 'html') { + render(renderSettings); + } else if (mode == 'fluid') { + el.holderData.resizeUpdate = true; + + if (dimensions.height.slice(-1) == '%') { + el.style.height = dimensions.height; + } else if (flags.auto == null || !flags.auto) { + el.style.height = dimensions.height + 'px'; + } + if (dimensions.width.slice(-1) == '%') { + el.style.width = dimensions.width; + } else if (flags.auto == null || !flags.auto) { + el.style.width = dimensions.width + 'px'; + } + if (el.style.display == 'inline' || el.style.display === '' || el.style.display == 'none') { + el.style.display = 'block'; + } + + setInitialDimensions(el); + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } + + /** + * Core function that takes output from renderers and sets it as the source or background-image of the target element + * + * @private + * @param renderSettings Renderer settings + */ + function render(renderSettings) { + var image = null; + var mode = renderSettings.mode; + var el = renderSettings.el; + var holderSettings = renderSettings.holderSettings; + var engineSettings = renderSettings.engineSettings; + + switch (engineSettings.renderer) { + case 'svg': + if (!App.setup.supportsSVG) return; + break; + case 'canvas': + if (!App.setup.supportsCanvas) return; + break; + default: + return; + } + + //todo: move generation of scene up to flag generation to reduce extra object creation + var scene = { + width: holderSettings.dimensions.width, + height: holderSettings.dimensions.height, + theme: holderSettings.theme, + flags: holderSettings.flags + }; + + var sceneGraph = buildSceneGraph(scene); + + function getRenderedImage() { + var image = null; + switch (engineSettings.renderer) { + case 'canvas': + image = sgCanvasRenderer(sceneGraph, renderSettings); + break; + case 'svg': + image = svgRenderer(sceneGraph, renderSettings); + break; + default: + throw 'Holder: invalid renderer: ' + engineSettings.renderer; + } + + return image; + } + + image = getRenderedImage(); + + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + + //todo: add canvas rendering + if (mode == 'background') { + el.style.backgroundImage = 'url(' + image + ')'; + + if (!engineSettings.noBackgroundSize) { + el.style.backgroundSize = scene.width + 'px ' + scene.height + 'px'; + } + } else { + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + if (engineSettings.reRender) { + global.setTimeout(function () { + var image = getRenderedImage(); + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + //todo: refactor this code into a function + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + }, 150); + } + } + //todo: account for re-rendering + DOM.setAttr(el, { + 'data-holder-rendered': true + }); + } + + /** + * Core function that takes a Holder scene description and builds a scene graph + * + * @private + * @param scene Holder scene object + */ + //todo: make this function reusable + //todo: merge app defaults and setup properties into the scene argument + function buildSceneGraph(scene) { + var fontSize = App.defaults.size; + if (parseFloat(scene.theme.size)) { + fontSize = scene.theme.size; + } else if (parseFloat(scene.flags.size)) { + fontSize = scene.flags.size; + } + + scene.font = { + family: scene.theme.font ? scene.theme.font : 'Arial, Helvetica, Open Sans, sans-serif', + size: textSize(scene.width, scene.height, fontSize, App.defaults.scale), + units: scene.theme.units ? scene.theme.units : App.defaults.units, + weight: scene.theme.fontweight ? scene.theme.fontweight : 'bold' + }; + + scene.text = scene.theme.text || Math.floor(scene.width) + 'x' + Math.floor(scene.height); + + scene.noWrap = scene.theme.nowrap || scene.flags.nowrap; + + scene.align = scene.theme.align || scene.flags.align || 'center'; + + switch (scene.flags.textmode) { + case 'literal': + scene.text = scene.flags.dimensions.width + 'x' + scene.flags.dimensions.height; + break; + case 'exact': + if (!scene.flags.exactDimensions) break; + scene.text = Math.floor(scene.flags.exactDimensions.width) + 'x' + Math.floor(scene.flags.exactDimensions.height); + break; + } + + var lineWrap = scene.flags.lineWrap || App.setup.lineWrapRatio; + var sceneMargin = scene.width * lineWrap; + var maxLineWidth = sceneMargin; + + var sceneGraph = new SceneGraph({ + width: scene.width, + height: scene.height + }); + + var Shape = sceneGraph.Shape; + + var holderBg = new Shape.Rect('holderBg', { + fill: scene.theme.bg + }); + + holderBg.resize(scene.width, scene.height); + sceneGraph.root.add(holderBg); + + if (scene.flags.outline) { + var outlineColor = new Color(holderBg.properties.fill); + outlineColor = outlineColor.lighten(outlineColor.lighterThan('7f7f7f') ? -0.1 : 0.1); + holderBg.properties.outline = { + fill: outlineColor.toHex(true), + width: 2 + }; + } + + var holderTextColor = scene.theme.fg; + + if (scene.flags.autoFg) { + var holderBgColor = new Color(holderBg.properties.fill); + var lightColor = new Color('fff'); + var darkColor = new Color('000', { + 'alpha': 0.285714 + }); + + holderTextColor = holderBgColor.blendAlpha(holderBgColor.lighterThan('7f7f7f') ? darkColor : lightColor).toHex(true); + } + + var holderTextGroup = new Shape.Group('holderTextGroup', { + text: scene.text, + align: scene.align, + font: scene.font, + fill: holderTextColor + }); + + holderTextGroup.moveTo(null, null, 1); + sceneGraph.root.add(holderTextGroup); + + var tpdata = holderTextGroup.textPositionData = stagingRenderer(sceneGraph); + if (!tpdata) { + throw 'Holder: staging fallback not supported yet.'; + } + holderTextGroup.properties.leading = tpdata.boundingBox.height; + + var textNode = null; + var line = null; + + function finalizeLine(parent, line, width, height) { + line.width = width; + line.height = height; + parent.width = Math.max(parent.width, line.width); + parent.height += line.height; + } + + if (tpdata.lineCount > 1) { + var offsetX = 0; + var offsetY = 0; + var lineIndex = 0; + var lineKey; + line = new Shape.Group('line' + lineIndex); + + //Double margin so that left/right-aligned next is not flush with edge of image + if (scene.align === 'left' || scene.align === 'right') { + maxLineWidth = scene.width * (1 - (1 - lineWrap) * 2); + } + + for (var i = 0; i < tpdata.words.length; i++) { + var word = tpdata.words[i]; + textNode = new Shape.Text(word.text); + var newline = word.text == '\\n'; + if (!scene.noWrap && (offsetX + word.width >= maxLineWidth || newline === true)) { + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + offsetX = 0; + offsetY += holderTextGroup.properties.leading; + lineIndex += 1; + line = new Shape.Group('line' + lineIndex); + line.y = offsetY; + } + if (newline === true) { + continue; + } + textNode.moveTo(offsetX, 0); + offsetX += tpdata.spaceWidth + word.width; + line.add(textNode); + } + + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo(scene.width - line.width, null, null); + } + + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo((holderTextGroup.width - line.width) / 2, null, null); + } + + holderTextGroup.moveTo((scene.width - holderTextGroup.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - holderTextGroup.height) / 2, null); + + //If the text exceeds vertical space, move it down so the first line is visible + if ((scene.height - holderTextGroup.height) / 2 < 0) { + holderTextGroup.moveTo(null, 0, null); + } + } else { + textNode = new Shape.Text(scene.text); + line = new Shape.Group('line0'); + line.add(textNode); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + holderTextGroup.moveTo((scene.width - tpdata.boundingBox.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - tpdata.boundingBox.height) / 2, null); + } + + //todo: renderlist + return sceneGraph; + } + + /** + * Adaptive text sizing function + * + * @private + * @param width Parent width + * @param height Parent height + * @param fontSize Requested text size + * @param scale Proportional scale of text + */ + function textSize(width, height, fontSize, scale) { + var stageWidth = parseInt(width, 10); + var stageHeight = parseInt(height, 10); + + var bigSide = Math.max(stageWidth, stageHeight); + var smallSide = Math.min(stageWidth, stageHeight); + + var newHeight = 0.8 * Math.min(smallSide, bigSide * scale); + return Math.round(Math.max(fontSize, newHeight)); + } + + /** + * Iterates over resizable (fluid or auto) placeholders and renders them + * + * @private + * @param element Optional element selector, specified only if a specific element needs to be re-rendered + */ + function updateResizableElements(element) { + var images; + if (element == null || element.nodeType == null) { + images = App.vars.resizableImages; + } else { + images = [element]; + } + for (var i = 0, l = images.length; i < l; i++) { + var el = images[i]; + if (el.holderData) { + var flags = el.holderData.flags; + var dimensions = dimensionCheck(el); + if (dimensions) { + if (!el.holderData.resizeUpdate) { + continue; + } + + if (flags.fluid && flags.auto) { + var fluidConfig = el.holderData.fluidConfig; + switch (fluidConfig.mode) { + case 'width': + dimensions.height = dimensions.width / fluidConfig.ratio; + break; + case 'height': + dimensions.width = dimensions.height * fluidConfig.ratio; + break; + } + } + + var settings = { + mode: 'image', + holderSettings: { + dimensions: dimensions, + theme: flags.theme, + flags: flags + }, + el: el, + engineSettings: el.holderData.engineSettings + }; + + if (flags.textmode == 'exact') { + flags.exactDimensions = dimensions; + settings.holderSettings.dimensions = flags.dimensions; + } + + render(settings); + } else { + setInvisible(el); + } + } + } + } + + /** + * Sets up aspect ratio metadata for fluid placeholders, in order to preserve proportions when resizing + * + * @private + * @param el Image DOM element + */ + function setInitialDimensions(el) { + if (el.holderData) { + var dimensions = dimensionCheck(el); + if (dimensions) { + var flags = el.holderData.flags; + + var fluidConfig = { + fluidHeight: flags.dimensions.height.slice(-1) == '%', + fluidWidth: flags.dimensions.width.slice(-1) == '%', + mode: null, + initialDimensions: dimensions + }; + + if (fluidConfig.fluidWidth && !fluidConfig.fluidHeight) { + fluidConfig.mode = 'width'; + fluidConfig.ratio = fluidConfig.initialDimensions.width / parseFloat(flags.dimensions.height); + } else if (!fluidConfig.fluidWidth && fluidConfig.fluidHeight) { + fluidConfig.mode = 'height'; + fluidConfig.ratio = parseFloat(flags.dimensions.width) / fluidConfig.initialDimensions.height; + } + + el.holderData.fluidConfig = fluidConfig; + } else { + setInvisible(el); + } + } + } + + /** + * Iterates through all current invisible images, and if they're visible, renders them and removes them from further checks. Runs every animation frame. + * + * @private + */ + function visibilityCheck() { + var renderableImages = []; + var keys = Object.keys(App.vars.invisibleImages); + var el; + + keys.forEach(function (key) { + el = App.vars.invisibleImages[key]; + if (dimensionCheck(el) && el.nodeName.toLowerCase() == 'img') { + renderableImages.push(el); + delete App.vars.invisibleImages[key]; + } + }); + + if (renderableImages.length) { + Holder.run({ + images: renderableImages + }); + } + + // Done to prevent 100% CPU usage via aggressive calling of requestAnimationFrame + setTimeout(function () { + global.requestAnimationFrame(visibilityCheck); + }, 10); + } + + /** + * Starts checking for invisible placeholders if not doing so yet. Does nothing otherwise. + * + * @private + */ + function startVisibilityCheck() { + if (!App.vars.visibilityCheckStarted) { + global.requestAnimationFrame(visibilityCheck); + App.vars.visibilityCheckStarted = true; + } + } + + /** + * Sets a unique ID for an image detected to be invisible and adds it to the map of invisible images checked by visibilityCheck + * + * @private + * @param el Invisible DOM element + */ + function setInvisible(el) { + if (!el.holderData.invisibleId) { + App.vars.invisibleId += 1; + App.vars.invisibleImages['i' + App.vars.invisibleId] = el; + el.holderData.invisibleId = App.vars.invisibleId; + } + } + + //todo: see if possible to convert stagingRenderer to use HTML only + var stagingRenderer = (function() { + var svg = null, + stagingText = null, + stagingTextNode = null; + return function(graph) { + var rootNode = graph.root; + if (App.setup.supportsSVG) { + var firstTimeSetup = false; + var tnode = function(text) { + return document.createTextNode(text); + }; + if (svg == null || svg.parentNode !== document.body) { + firstTimeSetup = true; + } + + svg = SVG.initSVG(svg, rootNode.properties.width, rootNode.properties.height); + //Show staging element before staging + svg.style.display = 'block'; + + if (firstTimeSetup) { + stagingText = DOM.newEl('text', SVG_NS); + stagingTextNode = tnode(null); + DOM.setAttr(stagingText, { + x: 0 + }); + stagingText.appendChild(stagingTextNode); + svg.appendChild(stagingText); + document.body.appendChild(svg); + svg.style.visibility = 'hidden'; + svg.style.position = 'absolute'; + svg.style.top = '-100%'; + svg.style.left = '-100%'; + //todo: workaround for zero-dimension tag in Opera 12 + //svg.setAttribute('width', 0); + //svg.setAttribute('height', 0); + } + + var holderTextGroup = rootNode.children.holderTextGroup; + var htgProps = holderTextGroup.properties; + DOM.setAttr(stagingText, { + 'y': htgProps.font.size, + 'style': utils.cssProps({ + 'font-weight': htgProps.font.weight, + 'font-size': htgProps.font.size + htgProps.font.units, + 'font-family': htgProps.font.family + }) + }); + + //Unescape HTML entities to get approximately the right width + var txt = DOM.newEl('textarea'); + txt.innerHTML = htgProps.text; + stagingTextNode.nodeValue = txt.value; + + //Get bounding box for the whole string (total width and height) + var stagingTextBBox = stagingText.getBBox(); + + //Get line count and split the string into words + var lineCount = Math.ceil(stagingTextBBox.width / rootNode.properties.width); + var words = htgProps.text.split(' '); + var newlines = htgProps.text.match(/\\n/g); + lineCount += newlines == null ? 0 : newlines.length; + + //Get bounding box for the string with spaces removed + stagingTextNode.nodeValue = htgProps.text.replace(/[ ]+/g, ''); + var computedNoSpaceLength = stagingText.getComputedTextLength(); + + //Compute average space width + var diffLength = stagingTextBBox.width - computedNoSpaceLength; + var spaceWidth = Math.round(diffLength / Math.max(1, words.length - 1)); + + //Get widths for every word with space only if there is more than one line + var wordWidths = []; + if (lineCount > 1) { + stagingTextNode.nodeValue = ''; + for (var i = 0; i < words.length; i++) { + if (words[i].length === 0) continue; + stagingTextNode.nodeValue = utils.decodeHtmlEntity(words[i]); + var bbox = stagingText.getBBox(); + wordWidths.push({ + text: words[i], + width: bbox.width + }); + } + } + + //Hide staging element after staging + svg.style.display = 'none'; + + return { + spaceWidth: spaceWidth, + lineCount: lineCount, + boundingBox: stagingTextBBox, + words: wordWidths + }; + } else { + //todo: canvas fallback for measuring text on android 2.3 + return false; + } + }; + })(); + + //Helpers + + /** + * Prevents a function from being called too often, waits until a timer elapses to call it again + * + * @param fn Function to call + */ + function debounce(fn) { + if (!App.vars.debounceTimer) fn.call(this); + if (App.vars.debounceTimer) global.clearTimeout(App.vars.debounceTimer); + App.vars.debounceTimer = global.setTimeout(function() { + App.vars.debounceTimer = null; + fn.call(this); + }, App.setup.debounce); + } + + /** + * Holder-specific resize/orientation change callback, debounced to prevent excessive execution + */ + function resizeEvent() { + debounce(function() { + updateResizableElements(null); + }); + } + + //Set up flags + + for (var flag in App.flags) { + if (!App.flags.hasOwnProperty(flag)) continue; + App.flags[flag].match = function(val) { + return val.match(this.regex); + }; + } + + //Properties set once on setup + + App.setup = { + renderer: 'html', + debounce: 100, + ratio: 1, + supportsCanvas: false, + supportsSVG: false, + lineWrapRatio: 0.9, + dataAttr: 'data-src', + renderers: ['html', 'canvas', 'svg'] + }; + + //Properties modified during runtime + + App.vars = { + preempted: false, + resizableImages: [], + invisibleImages: {}, + invisibleId: 0, + visibilityCheckStarted: false, + debounceTimer: null, + cache: {} + }; + + //Pre-flight + + (function() { + var canvas = DOM.newEl('canvas'); + + if (canvas.getContext) { + if (canvas.toDataURL('image/png').indexOf('data:image/png') != -1) { + App.setup.renderer = 'canvas'; + App.setup.supportsCanvas = true; + } + } + + if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect) { + App.setup.renderer = 'svg'; + App.setup.supportsSVG = true; + } + })(); + + //Starts checking for invisible placeholders + startVisibilityCheck(); + + if (onDomReady) { + onDomReady(function() { + if (!App.vars.preempted) { + Holder.run(); + } + if (global.addEventListener) { + global.addEventListener('resize', resizeEvent, false); + global.addEventListener('orientationchange', resizeEvent, false); + } else { + global.attachEvent('onresize', resizeEvent); + } + + if (typeof global.Turbolinks == 'object') { + global.document.addEventListener('page:change', function() { + Holder.run(); + }); + } + }); + } + + module.exports = Holder; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /*! + * onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license + * + * Specially modified to work with Holder.js + */ + + function _onDomReady(win) { + //Lazy loading fix for Firefox < 3.6 + //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html + if (document.readyState == null && document.addEventListener) { + document.addEventListener("DOMContentLoaded", function DOMContentLoaded() { + document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); + document.readyState = "complete"; + }, false); + document.readyState = "loading"; + } + + var doc = win.document, + docElem = doc.documentElement, + + LOAD = "load", + FALSE = false, + ONLOAD = "on"+LOAD, + COMPLETE = "complete", + READYSTATE = "readyState", + ATTACHEVENT = "attachEvent", + DETACHEVENT = "detachEvent", + ADDEVENTLISTENER = "addEventListener", + DOMCONTENTLOADED = "DOMContentLoaded", + ONREADYSTATECHANGE = "onreadystatechange", + REMOVEEVENTLISTENER = "removeEventListener", + + // W3C Event model + w3c = ADDEVENTLISTENER in doc, + _top = FALSE, + + // isReady: Is the DOM ready to be used? Set to true once it occurs. + isReady = FALSE, + + // Callbacks pending execution until DOM is ready + callbacks = []; + + // Handle when the DOM is ready + function ready( fn ) { + if ( !isReady ) { + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !doc.body ) { + return defer( ready ); + } + + // Remember that the DOM is ready + isReady = true; + + // Execute all callbacks + while ( fn = callbacks.shift() ) { + defer( fn ); + } + } + } + + // The ready event handler + function completed( event ) { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) { + detach(); + ready(); + } + } + + // Clean-up method for dom ready events + function detach() { + if ( w3c ) { + doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE ); + } else { + doc[DETACHEVENT]( ONREADYSTATECHANGE, completed ); + win[DETACHEVENT]( ONLOAD, completed ); + } + } + + // Defers a function, scheduling it to run after the current call stack has cleared. + function defer( fn, wait ) { + // Allow 0 to be passed + setTimeout( fn, +wait >= 0 ? wait : 1 ); + } + + // Attach the listeners: + + // Catch cases where onDomReady is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( doc[READYSTATE] === COMPLETE ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + defer( ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( w3c ) { + // Use the handy event callback + doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + + // A fallback to window.onload, that will always work + win[ADDEVENTLISTENER]( LOAD, completed, FALSE ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed ); + + // A fallback to window.onload, that will always work + win[ATTACHEVENT]( ONLOAD, completed ); + + // If IE and not a frame + // continually check to see if the document is ready + try { + _top = win.frameElement == null && docElem; + } catch(e) {} + + if ( _top && _top.doScroll ) { + (function doScrollCheck() { + if ( !isReady ) { + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + _top.doScroll("left"); + } catch(e) { + return defer( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + ready(); + } + })(); + } + } + + function onDomReady( fn ) { + // If DOM is ready, execute the function (async), otherwise wait + isReady ? defer( fn ) : callbacks.push( fn ); + } + + // Add version + onDomReady.version = "1.4.0"; + // Add method to check if DOM is ready + onDomReady.isReady = function(){ + return isReady; + }; + + return onDomReady; + } + + module.exports = typeof window !== "undefined" && _onDomReady(window); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + //Modified version of component/querystring + //Changes: updated dependencies, dot notation parsing, JSHint fixes + //Fork at https://github.com/imsky/querystring + + /** + * Module dependencies. + */ + + var encode = encodeURIComponent; + var decode = decodeURIComponent; + var trim = __webpack_require__(4); + var type = __webpack_require__(5); + + var arrayRegex = /(\w+)\[(\d+)\]/; + var objectRegex = /\w+\.\w+/; + + /** + * Parse the given query `str`. + * + * @param {String} str + * @return {Object} + * @api public + */ + + exports.parse = function(str){ + if ('string' !== typeof str) return {}; + + str = trim(str); + if ('' === str) return {}; + if ('?' === str.charAt(0)) str = str.slice(1); + + var obj = {}; + var pairs = str.split('&'); + for (var i = 0; i < pairs.length; i++) { + var parts = pairs[i].split('='); + var key = decode(parts[0]); + var m, ctx, prop; + + if (m = arrayRegex.exec(key)) { + obj[m[1]] = obj[m[1]] || []; + obj[m[1]][m[2]] = decode(parts[1]); + continue; + } + + if (m = objectRegex.test(key)) { + m = key.split('.'); + ctx = obj; + + while (m.length) { + prop = m.shift(); + + if (!prop.length) continue; + + if (!ctx[prop]) { + ctx[prop] = {}; + } else if (ctx[prop] && typeof ctx[prop] !== 'object') { + break; + } + + if (!m.length) { + ctx[prop] = decode(parts[1]); + } + + ctx = ctx[prop]; + } + + continue; + } + + obj[parts[0]] = null == parts[1] ? '' : decode(parts[1]); + } + + return obj; + }; + + /** + * Stringify the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api public + */ + + exports.stringify = function(obj){ + if (!obj) return ''; + var pairs = []; + + for (var key in obj) { + var value = obj[key]; + + if ('array' == type(value)) { + for (var i = 0; i < value.length; ++i) { + pairs.push(encode(key + '[' + i + ']') + '=' + encode(value[i])); + } + continue; + } + + pairs.push(encode(key) + '=' + encode(obj[key])); + } + + return pairs.join('&'); + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + + exports = module.exports = trim; + + function trim(str){ + return str.replace(/^\s*|\s*$/g, ''); + } + + exports.left = function(str){ + return str.replace(/^\s*/, ''); + }; + + exports.right = function(str){ + return str.replace(/\s*$/, ''); + }; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + /** + * toString ref. + */ + + var toString = Object.prototype.toString; + + /** + * Return the type of `val`. + * + * @param {Mixed} val + * @return {String} + * @api public + */ + + module.exports = function(val){ + switch (toString.call(val)) { + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object Error]': return 'error'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val !== val) return 'nan'; + if (val && val.nodeType === 1) return 'element'; + + val = val.valueOf + ? val.valueOf() + : Object.prototype.valueOf.apply(val) + + return typeof val; + }; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + + var SceneGraph = function(sceneProperties) { + var nodeCount = 1; + + //todo: move merge to helpers section + function merge(parent, child) { + for (var prop in child) { + parent[prop] = child[prop]; + } + return parent; + } + + var SceneNode = function(name) { + nodeCount++; + this.parent = null; + this.children = {}; + this.id = nodeCount; + this.name = 'n' + nodeCount; + if (typeof name !== 'undefined') { + this.name = name; + } + this.x = this.y = this.z = 0; + this.width = this.height = 0; + }; + + SceneNode.prototype.resize = function(width, height) { + if (width != null) { + this.width = width; + } + if (height != null) { + this.height = height; + } + }; + + SceneNode.prototype.moveTo = function(x, y, z) { + this.x = x != null ? x : this.x; + this.y = y != null ? y : this.y; + this.z = z != null ? z : this.z; + }; + + SceneNode.prototype.add = function(child) { + var name = child.name; + if (typeof this.children[name] === 'undefined') { + this.children[name] = child; + child.parent = this; + } else { + throw 'SceneGraph: child already exists: ' + name; + } + }; + + var RootNode = function() { + SceneNode.call(this, 'root'); + this.properties = sceneProperties; + }; + + RootNode.prototype = new SceneNode(); + + var Shape = function(name, props) { + SceneNode.call(this, name); + this.properties = { + 'fill': '#000000' + }; + if (typeof props !== 'undefined') { + merge(this.properties, props); + } else if (typeof name !== 'undefined' && typeof name !== 'string') { + throw 'SceneGraph: invalid node name'; + } + }; + + Shape.prototype = new SceneNode(); + + var Group = function() { + Shape.apply(this, arguments); + this.type = 'group'; + }; + + Group.prototype = new Shape(); + + var Rect = function() { + Shape.apply(this, arguments); + this.type = 'rect'; + }; + + Rect.prototype = new Shape(); + + var Text = function(text) { + Shape.call(this); + this.type = 'text'; + this.properties.text = text; + }; + + Text.prototype = new Shape(); + + var root = new RootNode(); + + this.Shape = { + 'Rect': Rect, + 'Text': Text, + 'Group': Group + }; + + this.root = root; + return this; + }; + + module.exports = SceneGraph; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Shallow object clone and merge + * + * @param a Object A + * @param b Object B + * @returns {Object} New object with all of A's properties, and all of B's properties, overwriting A's properties + */ + exports.extend = function(a, b) { + var c = {}; + for (var x in a) { + if (a.hasOwnProperty(x)) { + c[x] = a[x]; + } + } + if (b != null) { + for (var y in b) { + if (b.hasOwnProperty(y)) { + c[y] = b[y]; + } + } + } + return c; + }; + + /** + * Takes a k/v list of CSS properties and returns a rule + * + * @param props CSS properties object + */ + exports.cssProps = function(props) { + var ret = []; + for (var p in props) { + if (props.hasOwnProperty(p)) { + ret.push(p + ':' + props[p]); + } + } + return ret.join(';'); + }; + + /** + * Encodes HTML entities in a string + * + * @param str Input string + */ + exports.encodeHtmlEntity = function(str) { + var buf = []; + var charCode = 0; + for (var i = str.length - 1; i >= 0; i--) { + charCode = str.charCodeAt(i); + if (charCode > 128) { + buf.unshift(['&#', charCode, ';'].join('')); + } else { + buf.unshift(str[i]); + } + } + return buf.join(''); + }; + + /** + * Checks if an image exists + * + * @param src URL of image + * @param callback Callback to call once image status has been found + */ + exports.imageExists = function(src, callback) { + var image = new Image(); + image.onerror = function() { + callback.call(this, false); + }; + image.onload = function() { + callback.call(this, true); + }; + image.src = src; + }; + + /** + * Decodes HTML entities in a string + * + * @param str Input string + */ + exports.decodeHtmlEntity = function(str) { + return str.replace(/&#(\d+);/g, function(match, dec) { + return String.fromCharCode(dec); + }); + }; + + + /** + * Returns an element's dimensions if it's visible, `false` otherwise. + * + * @param el DOM element + */ + exports.dimensionCheck = function(el) { + var dimensions = { + height: el.clientHeight, + width: el.clientWidth + }; + + if (dimensions.height && dimensions.width) { + return dimensions; + } else { + return false; + } + }; + + + /** + * Returns true if value is truthy or if it is "semantically truthy" + * @param val + */ + exports.truthy = function(val) { + if (typeof val === 'string') { + return val === 'true' || val === 'yes' || val === '1' || val === 'on' || val === '✓'; + } + return !!val; + }; + + /** + * Parses input into a well-formed CSS color + * @param val + */ + exports.parseColor = function(val) { + var hexre = /(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i; + var rgbre = /^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/; + var rgbare = /^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/; + + var match = val.match(hexre); + var retval; + + if (match !== null) { + retval = match[1] || match[2]; + if (retval[0] !== '#') { + return '#' + retval; + } else { + return retval; + } + } + + match = val.match(rgbre); + + if (match !== null) { + retval = 'rgb(' + match.slice(1).join(',') + ')'; + return retval; + } + + match = val.match(rgbare); + + if (match !== null) { + const normalizeAlpha = function (a) { return '0.' + a.split('.')[1]; }; + const fixedMatch = match.slice(1).map(function (e, i) { + return (i === 3) ? normalizeAlpha(e) : e; + }); + retval = 'rgba(' + fixedMatch.join(',') + ')'; + return retval; + } + + return null; + }; + + /** + * Provides the correct scaling ratio for canvas drawing operations on HiDPI screens (e.g. Retina displays) + */ + exports.canvasRatio = function () { + var devicePixelRatio = 1; + var backingStoreRatio = 1; + + if (global.document) { + var canvas = global.document.createElement('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + devicePixelRatio = global.devicePixelRatio || 1; + backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + } + } + + return devicePixelRatio / backingStoreRatio; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {var DOM = __webpack_require__(9); + + var SVG_NS = 'http://www.w3.org/2000/svg'; + var NODE_TYPE_COMMENT = 8; + + /** + * Generic SVG element creation function + * + * @param svg SVG context, set to null if new + * @param width Document width + * @param height Document height + */ + exports.initSVG = function(svg, width, height) { + var defs, style, initialize = false; + + if (svg && svg.querySelector) { + style = svg.querySelector('style'); + if (style === null) { + initialize = true; + } + } else { + svg = DOM.newEl('svg', SVG_NS); + initialize = true; + } + + if (initialize) { + defs = DOM.newEl('defs', SVG_NS); + style = DOM.newEl('style', SVG_NS); + DOM.setAttr(style, { + 'type': 'text/css' + }); + defs.appendChild(style); + svg.appendChild(defs); + } + + //IE throws an exception if this is set and Chrome requires it to be set + if (svg.webkitMatchesSelector) { + svg.setAttribute('xmlns', SVG_NS); + } + + //Remove comment nodes + for (var i = 0; i < svg.childNodes.length; i++) { + if (svg.childNodes[i].nodeType === NODE_TYPE_COMMENT) { + svg.removeChild(svg.childNodes[i]); + } + } + + //Remove CSS + while (style.childNodes.length) { + style.removeChild(style.childNodes[0]); + } + + DOM.setAttr(svg, { + 'width': width, + 'height': height, + 'viewBox': '0 0 ' + width + ' ' + height, + 'preserveAspectRatio': 'none' + }); + + return svg; + }; + + /** + * Converts serialized SVG to a string suitable for data URI use + * @param svgString Serialized SVG string + * @param [base64] Use base64 encoding for data URI + */ + exports.svgStringToDataURI = function() { + var rawPrefix = 'data:image/svg+xml;charset=UTF-8,'; + var base64Prefix = 'data:image/svg+xml;charset=UTF-8;base64,'; + + return function(svgString, base64) { + if (base64) { + return base64Prefix + btoa(global.unescape(encodeURIComponent(svgString))); + } else { + return rawPrefix + encodeURIComponent(svgString); + } + }; + }(); + + /** + * Returns serialized SVG with XML processing instructions + * + * @param svg SVG context + * @param stylesheets CSS stylesheets to include + */ + exports.serializeSVG = function(svg, engineSettings) { + if (!global.XMLSerializer) return; + var serializer = new XMLSerializer(); + var svgCSS = ''; + var stylesheets = engineSettings.stylesheets; + + //External stylesheets: Processing Instruction method + if (engineSettings.svgXMLStylesheet) { + var xml = DOM.createXML(); + //Add directives + for (var i = stylesheets.length - 1; i >= 0; i--) { + var csspi = xml.createProcessingInstruction('xml-stylesheet', 'href="' + stylesheets[i] + '" rel="stylesheet"'); + xml.insertBefore(csspi, xml.firstChild); + } + + xml.removeChild(xml.documentElement); + svgCSS = serializer.serializeToString(xml); + } + + var svgText = serializer.serializeToString(svg); + svgText = svgText.replace(/\&(\#[0-9]{2,}\;)/g, '&$1'); + return svgCSS + svgText; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Generic new DOM element function + * + * @param tag Tag to create + * @param namespace Optional namespace value + */ + exports.newEl = function(tag, namespace) { + if (!global.document) return; + + if (namespace == null) { + return global.document.createElement(tag); + } else { + return global.document.createElementNS(namespace, tag); + } + }; + + /** + * Generic setAttribute function + * + * @param el Reference to DOM element + * @param attrs Object with attribute keys and values + */ + exports.setAttr = function (el, attrs) { + for (var a in attrs) { + el.setAttribute(a, attrs[a]); + } + }; + + /** + * Creates a XML document + * @private + */ + exports.createXML = function() { + if (!global.DOMParser) return; + return new DOMParser().parseFromString('', 'application/xml'); + }; + + /** + * Converts a value into an array of DOM nodes + * + * @param val A string, a NodeList, a Node, or an HTMLCollection + */ + exports.getNodeArray = function(val) { + var retval = null; + if (typeof(val) == 'string') { + retval = document.querySelectorAll(val); + } else if (global.NodeList && val instanceof global.NodeList) { + retval = val; + } else if (global.Node && val instanceof global.Node) { + retval = [val]; + } else if (global.HTMLCollection && val instanceof global.HTMLCollection) { + retval = val; + } else if (val instanceof Array) { + retval = val; + } else if (val === null) { + retval = []; + } + + retval = Array.prototype.slice.call(retval); + + return retval; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + + var Color = function(color, options) { + //todo: support rgba, hsla, and rrggbbaa notation + //todo: use CIELAB internally + //todo: add clamp function (with sign) + if (typeof color !== 'string') return; + + this.original = color; + + if (color.charAt(0) === '#') { + color = color.slice(1); + } + + if (/[^a-f0-9]+/i.test(color)) return; + + if (color.length === 3) { + color = color.replace(/./g, '$&$&'); + } + + if (color.length !== 6) return; + + this.alpha = 1; + + if (options && options.alpha) { + this.alpha = options.alpha; + } + + this.set(parseInt(color, 16)); + }; + + //todo: jsdocs + Color.rgb2hex = function(r, g, b) { + function format (decimal) { + var hex = (decimal | 0).toString(16); + if (decimal < 16) { + hex = '0' + hex; + } + return hex; + } + + return [r, g, b].map(format).join(''); + }; + + //todo: jsdocs + Color.hsl2rgb = function (h, s, l) { + var H = h / 60; + var C = (1 - Math.abs(2 * l - 1)) * s; + var X = C * (1 - Math.abs(parseInt(H) % 2 - 1)); + var m = l - (C / 2); + + var r = 0, g = 0, b = 0; + + if (H >= 0 && H < 1) { + r = C; + g = X; + } else if (H >= 1 && H < 2) { + r = X; + g = C; + } else if (H >= 2 && H < 3) { + g = C; + b = X; + } else if (H >= 3 && H < 4) { + g = X; + b = C; + } else if (H >= 4 && H < 5) { + r = X; + b = C; + } else if (H >= 5 && H < 6) { + r = C; + b = X; + } + + r += m; + g += m; + b += m; + + r = parseInt(r * 255); + g = parseInt(g * 255); + b = parseInt(b * 255); + + return [r, g, b]; + }; + + /** + * Sets the color from a raw RGB888 integer + * @param raw RGB888 representation of color + */ + //todo: refactor into a static method + //todo: factor out individual color spaces + //todo: add HSL, CIELAB, and CIELUV + Color.prototype.set = function (val) { + this.raw = val; + + var r = (this.raw & 0xFF0000) >> 16; + var g = (this.raw & 0x00FF00) >> 8; + var b = (this.raw & 0x0000FF); + + // BT.709 + var y = 0.2126 * r + 0.7152 * g + 0.0722 * b; + var u = -0.09991 * r - 0.33609 * g + 0.436 * b; + var v = 0.615 * r - 0.55861 * g - 0.05639 * b; + + this.rgb = { + r: r, + g: g, + b: b + }; + + this.yuv = { + y: y, + u: u, + v: v + }; + + return this; + }; + + /** + * Lighten or darken a color + * @param multiplier Amount to lighten or darken (-1 to 1) + */ + Color.prototype.lighten = function(multiplier) { + var cm = Math.min(1, Math.max(0, Math.abs(multiplier))) * (multiplier < 0 ? -1 : 1); + var bm = (255 * cm) | 0; + var cr = Math.min(255, Math.max(0, this.rgb.r + bm)); + var cg = Math.min(255, Math.max(0, this.rgb.g + bm)); + var cb = Math.min(255, Math.max(0, this.rgb.b + bm)); + var hex = Color.rgb2hex(cr, cg, cb); + return new Color(hex); + }; + + /** + * Output color in hex format + * @param addHash Add a hash character to the beginning of the output + */ + Color.prototype.toHex = function(addHash) { + return (addHash ? '#' : '') + this.raw.toString(16); + }; + + /** + * Returns whether or not current color is lighter than another color + * @param color Color to compare against + */ + Color.prototype.lighterThan = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + return this.yuv.y > color.yuv.y; + }; + + /** + * Returns the result of mixing current color with another color + * @param color Color to mix with + * @param multiplier How much to mix with the other color + */ + /* + Color.prototype.mix = function (color, multiplier) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var r = this.rgb.r; + var g = this.rgb.g; + var b = this.rgb.b; + var a = this.alpha; + + var m = typeof multiplier !== 'undefined' ? multiplier : 0.5; + + //todo: write a lerp function + r = r + m * (color.rgb.r - r); + g = g + m * (color.rgb.g - g); + b = b + m * (color.rgb.b - b); + a = a + m * (color.alpha - a); + + return new Color(Color.rgbToHex(r, g, b), { + 'alpha': a + }); + }; + */ + + /** + * Returns the result of blending another color on top of current color with alpha + * @param color Color to blend on top of current color, i.e. "Ca" + */ + //todo: see if .blendAlpha can be merged into .mix + Color.prototype.blendAlpha = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var Ca = color; + var Cb = this; + + //todo: write alpha blending function + var r = Ca.alpha * Ca.rgb.r + (1 - Ca.alpha) * Cb.rgb.r; + var g = Ca.alpha * Ca.rgb.g + (1 - Ca.alpha) * Cb.rgb.g; + var b = Ca.alpha * Ca.rgb.b + (1 - Ca.alpha) * Cb.rgb.b; + + return new Color(Color.rgb2hex(r, g, b)); + }; + + module.exports = Color; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports) { + + module.exports = { + 'version': '2.9.7', + 'svg_ns': 'http://www.w3.org/2000/svg' + }; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + var shaven = __webpack_require__(13); + + var SVG = __webpack_require__(8); + var constants = __webpack_require__(11); + var utils = __webpack_require__(7); + + var SVG_NS = constants.svg_ns; + + var templates = { + 'element': function (options) { + var tag = options.tag; + var content = options.content || ''; + delete options.tag; + delete options.content; + return [tag, content, options]; + } + }; + + //todo: deprecate tag arg, infer tag from shape object + function convertShape (shape, tag) { + return templates.element({ + 'tag': tag, + 'width': shape.width, + 'height': shape.height, + 'fill': shape.properties.fill + }); + } + + function textCss (properties) { + return utils.cssProps({ + 'fill': properties.fill, + 'font-weight': properties.font.weight, + 'font-family': properties.font.family + ', monospace', + 'font-size': properties.font.size + properties.font.units + }); + } + + function outlinePath (bgWidth, bgHeight, outlineWidth) { + var outlineOffsetWidth = outlineWidth / 2; + + return [ + 'M', outlineOffsetWidth, outlineOffsetWidth, + 'H', bgWidth - outlineOffsetWidth, + 'V', bgHeight - outlineOffsetWidth, + 'H', outlineOffsetWidth, + 'V', 0, + 'M', 0, outlineOffsetWidth, + 'L', bgWidth, bgHeight - outlineOffsetWidth, + 'M', 0, bgHeight - outlineOffsetWidth, + 'L', bgWidth, outlineOffsetWidth + ].join(' '); + } + + module.exports = function (sceneGraph, renderSettings) { + var engineSettings = renderSettings.engineSettings; + var stylesheets = engineSettings.stylesheets; + var stylesheetXml = stylesheets.map(function (stylesheet) { + return ''; + }).join('\n'); + + var holderId = 'holder_' + Number(new Date()).toString(16); + + var root = sceneGraph.root; + var textGroup = root.children.holderTextGroup; + + var css = '#' + holderId + ' text { ' + textCss(textGroup.properties) + ' } '; + + // push text down to be equally vertically aligned with canvas renderer + textGroup.y += textGroup.textPositionData.boundingBox.height * 0.8; + + var wordTags = []; + + Object.keys(textGroup.children).forEach(function (lineKey) { + var line = textGroup.children[lineKey]; + + Object.keys(line.children).forEach(function (wordKey) { + var word = line.children[wordKey]; + var x = textGroup.x + line.x + word.x; + var y = textGroup.y + line.y + word.y; + var wordTag = templates.element({ + 'tag': 'text', + 'content': word.properties.text, + 'x': x, + 'y': y + }); + + wordTags.push(wordTag); + }); + }); + + var text = templates.element({ + 'tag': 'g', + 'content': wordTags + }); + + var outline = null; + + if (root.children.holderBg.properties.outline) { + var outlineProperties = root.children.holderBg.properties.outline; + outline = templates.element({ + 'tag': 'path', + 'd': outlinePath(root.children.holderBg.width, root.children.holderBg.height, outlineProperties.width), + 'stroke-width': outlineProperties.width, + 'stroke': outlineProperties.fill, + 'fill': 'none' + }); + } + + var bg = convertShape(root.children.holderBg, 'rect'); + + var sceneContent = []; + + sceneContent.push(bg); + if (outlineProperties) { + sceneContent.push(outline); + } + sceneContent.push(text); + + var scene = templates.element({ + 'tag': 'g', + 'id': holderId, + 'content': sceneContent + }); + + var style = templates.element({ + 'tag': 'style', + //todo: figure out how to add CDATA directive + 'content': css, + 'type': 'text/css' + }); + + var defs = templates.element({ + 'tag': 'defs', + 'content': style + }); + + var svg = templates.element({ + 'tag': 'svg', + 'content': [defs, scene], + 'width': root.properties.width, + 'height': root.properties.height, + 'xmlns': SVG_NS, + 'viewBox': [0, 0, root.properties.width, root.properties.height].join(' '), + 'preserveAspectRatio': 'none' + }); + + var output = shaven(svg); + + if (/\&(x)?#[0-9A-Fa-f]/.test(output[0])) { + output[0] = output[0].replace(/&#/gm, '&#'); + } + + output = stylesheetXml + output[0]; + + var svgString = SVG.svgStringToDataURI(output, renderSettings.mode === 'background'); + return svgString; + }; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + var escape = __webpack_require__(14) + + // TODO: remove namespace + + module.exports = function shaven (array, namespace, returnObject) { + + 'use strict' + + var i = 1 + var doesEscape = true + var HTMLString + var attributeKey + var callback + var key + + + returnObject = returnObject || {} + + + function createElement (sugarString) { + + var tags = sugarString.match(/^[\w-]+/) + var element = { + tag: tags ? tags[0] : 'div', + attr: {}, + children: [] + } + var id = sugarString.match(/#([\w-]+)/) + var reference = sugarString.match(/\$([\w-]+)/) + var classNames = sugarString.match(/\.[\w-]+/g) + + + // Assign id if is set + if (id) { + element.attr.id = id[1] + + // Add element to the return object + returnObject[id[1]] = element + } + + if (reference) + returnObject[reference[1]] = element + + if (classNames) + element.attr.class = classNames.join(' ').replace(/\./g, '') + + if (sugarString.match(/&$/g)) + doesEscape = false + + return element + } + + function replacer (key, value) { + + if (value === null || value === false || value === undefined) + return + + if (typeof value !== 'string' && typeof value !== 'object') + return String(value) + + return value + } + + function escapeAttribute (string) { + return (string || string === 0) ? + String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') : + '' + } + + function escapeHTML (string) { + return String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + } + + + if (typeof array[0] === 'string') + array[0] = createElement(array[0]) + + else if (Array.isArray(array[0])) + i = 0 + + else + throw new Error( + 'First element of array must be a string, ' + + 'or an array and not ' + JSON.stringify(array[0]) + ) + + + for (; i < array.length; i++) { + + // Don't render element if value is false or null + if (array[i] === false || array[i] === null) { + array[0] = false + break + } + + // Continue with next array value if current value is undefined or true + else if (array[i] === undefined || array[i] === true) { + continue + } + + else if (typeof array[i] === 'string') { + if (doesEscape) + array[i] = escapeHTML(array[i]) + + array[0].children.push(array[i]) + } + + else if (typeof array[i] === 'number') { + + array[0].children.push(array[i]) + } + + else if (Array.isArray(array[i])) { + + if (Array.isArray(array[i][0])) { + array[i].reverse().forEach(function (subArray) { + array.splice(i + 1, 0, subArray) + }) + + if (i !== 0) + continue + i++ + } + + shaven(array[i], namespace, returnObject) + + if (array[i][0]) + array[0].children.push(array[i][0]) + } + + else if (typeof array[i] === 'function') + callback = array[i] + + + else if (typeof array[i] === 'object') { + for (attributeKey in array[i]) + if (array[i].hasOwnProperty(attributeKey)) + if (array[i][attributeKey] !== null && + array[i][attributeKey] !== false) + if (attributeKey === 'style' && + typeof array[i][attributeKey] === 'object') + array[0].attr[attributeKey] = JSON + .stringify(array[i][attributeKey], replacer) + .slice(2, -2) + .replace(/","/g, ';') + .replace(/":"/g, ':') + .replace(/\\"/g, '\'') + + else + array[0].attr[attributeKey] = array[i][attributeKey] + } + + else + throw new TypeError('"' + array[i] + '" is not allowed as a value.') + } + + + if (array[0] !== false) { + + HTMLString = '<' + array[0].tag + + for (key in array[0].attr) + if (array[0].attr.hasOwnProperty(key)) + HTMLString += ' ' + key + '="' + + escapeAttribute(array[0].attr[key]) + '"' + + HTMLString += '>' + + array[0].children.forEach(function (child) { + HTMLString += child + }) + + HTMLString += '' + + array[0] = HTMLString + } + + // Return root element on index 0 + returnObject[0] = array[0] + + if (callback) + callback(array[0]) + + // returns object containing all elements with an id and the root element + return returnObject + } + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + + /*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + + 'use strict'; + + /** + * Module variables. + * @private + */ + + var matchHtmlRegExp = /["'&<>]/; + + /** + * Module exports. + * @public + */ + + module.exports = escapeHtml; + + /** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + + function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; + } + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + var DOM = __webpack_require__(9); + var utils = __webpack_require__(7); + + module.exports = (function() { + var canvas = DOM.newEl('canvas'); + var ctx = null; + + return function(sceneGraph) { + if (ctx == null) { + ctx = canvas.getContext('2d'); + } + + var dpr = utils.canvasRatio(); + var root = sceneGraph.root; + canvas.width = dpr * root.properties.width; + canvas.height = dpr * root.properties.height ; + ctx.textBaseline = 'middle'; + + var bg = root.children.holderBg; + var bgWidth = dpr * bg.width; + var bgHeight = dpr * bg.height; + //todo: parametrize outline width (e.g. in scene object) + var outlineWidth = 2; + var outlineOffsetWidth = outlineWidth / 2; + + ctx.fillStyle = bg.properties.fill; + ctx.fillRect(0, 0, bgWidth, bgHeight); + + if (bg.properties.outline) { + //todo: abstract this into a method + ctx.strokeStyle = bg.properties.outline.fill; + ctx.lineWidth = bg.properties.outline.width; + ctx.moveTo(outlineOffsetWidth, outlineOffsetWidth); + // TL, TR, BR, BL + ctx.lineTo(bgWidth - outlineOffsetWidth, outlineOffsetWidth); + ctx.lineTo(bgWidth - outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, outlineOffsetWidth); + // Diagonals + ctx.moveTo(0, outlineOffsetWidth); + ctx.lineTo(bgWidth, bgHeight - outlineOffsetWidth); + ctx.moveTo(0, bgHeight - outlineOffsetWidth); + ctx.lineTo(bgWidth, outlineOffsetWidth); + ctx.stroke(); + } + + var textGroup = root.children.holderTextGroup; + ctx.font = textGroup.properties.font.weight + ' ' + (dpr * textGroup.properties.font.size) + textGroup.properties.font.units + ' ' + textGroup.properties.font.family + ', monospace'; + ctx.fillStyle = textGroup.properties.fill; + + for (var lineKey in textGroup.children) { + var line = textGroup.children[lineKey]; + for (var wordKey in line.children) { + var word = line.children[wordKey]; + var x = dpr * (textGroup.x + line.x + word.x); + var y = dpr * (textGroup.y + line.y + word.y + (textGroup.properties.leading / 2)); + + ctx.fillText(word.properties.text, x, y); + } + } + + return canvas.toDataURL('image/png'); + }; + })(); + +/***/ }) +/******/ ]) +}); +; +(function(ctx, isMeteorPackage) { + if (isMeteorPackage) { + Holder = ctx.Holder; + } +})(this, typeof Meteor !== 'undefined' && typeof Package !== 'undefined'); diff --git a/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.min.js b/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.min.js new file mode 100644 index 0000000..6935bf1 --- /dev/null +++ b/BlazorStudy.Bootstrap5Study/wwwroot/plugs/holder/holder.min.js @@ -0,0 +1,14 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +!function(e){if(e.document){var t=e.document;t.querySelectorAll||(t.querySelectorAll=function(n){var r,i=t.createElement("style"),a=[];for(t.documentElement.firstChild.appendChild(i),t._qsa=[],i.styleSheet.cssText=n+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",e.scrollBy(0,0),i.parentNode.removeChild(i);t._qsa.length;)r=t._qsa.shift(),r.style.removeAttribute("x-qsa"),a.push(r);return t._qsa=null,a}),t.querySelector||(t.querySelector=function(e){var n=t.querySelectorAll(e);return n.length?n[0]:null}),t.getElementsByClassName||(t.getElementsByClassName=function(e){return e=String(e).replace(/^|\s+/g,"."),t.querySelectorAll(e)}),Object.keys||(Object.keys=function(e){if(e!==Object(e))throw TypeError("Object.keys called on non-object");var t,n=[];for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.push(t);return n}),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError();var r,i=arguments[1];for(r=0;n>r;r++)r in t&&e.call(i,t[r],r,t)}),function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";e.atob=e.atob||function(e){e=String(e);var n,r=0,i=[],a=0,o=0;if(e=e.replace(/\s/g,""),e.length%4===0&&(e=e.replace(/=+$/,"")),e.length%4===1)throw Error("InvalidCharacterError");if(/[^+\/0-9A-Za-z]/.test(e))throw Error("InvalidCharacterError");for(;r>16&255)),i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a)),o=0,a=0),r+=1;return 12===o?(a>>=4,i.push(String.fromCharCode(255&a))):18===o&&(a>>=2,i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a))),i.join("")},e.btoa=e.btoa||function(e){e=String(e);var n,r,i,a,o,s,l,h=0,u=[];if(/[^\x00-\xFF]/.test(e))throw Error("InvalidCharacterError");for(;h>2,o=(3&n)<<4|r>>4,s=(15&r)<<2|i>>6,l=63&i,h===e.length+2?(s=64,l=64):h===e.length+1&&(l=64),u.push(t.charAt(a),t.charAt(o),t.charAt(s),t.charAt(l));return u.join("")}}(e),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(e){var t=this.__proto__||this.constructor.prototype;return e in this&&(!(e in t)||t[e]!==this[e])}),function(){if("performance"in e==!1&&(e.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in e.performance==!1){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),e.performance.now=function(){return Date.now()-t}}}(),e.requestAnimationFrame||(e.webkitRequestAnimationFrame&&e.webkitCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return webkitRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.webkitCancelAnimationFrame}(e):e.mozRequestAnimationFrame&&e.mozCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return mozRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.mozCancelAnimationFrame}(e):!function(e){e.requestAnimationFrame=function(t){return e.setTimeout(t,1e3/60)},e.cancelAnimationFrame=e.clearTimeout}(e))}}(this),function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Holder=t():e.Holder=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){(function(t){function r(e,t,n,r){var o=i(n.substr(n.lastIndexOf(e.domain)),e);o&&a({mode:null,el:r,flags:o,engineSettings:t})}function i(e,t){var n={theme:T(O.settings.themes.gray,null),stylesheets:t.stylesheets,instanceOptions:t},r=e.indexOf("?"),i=[e];-1!==r&&(i=[e.slice(0,r),e.slice(r+1)]);var a=i[0].split("/");n.holderURL=e;var o=a[1],s=o.match(/([\d]+p?)x([\d]+p?)/);if(!s)return!1;if(n.fluid=-1!==o.indexOf("p"),n.dimensions={width:s[1].replace("p","%"),height:s[2].replace("p","%")},2===i.length){var l=v.parse(i[1]);if(w.truthy(l.ratio)){n.fluid=!0;var h=parseFloat(n.dimensions.width.replace("%","")),u=parseFloat(n.dimensions.height.replace("%",""));u=Math.floor(100*(u/h)),h=100,n.dimensions.width=h+"%",n.dimensions.height=u+"%"}if(n.auto=w.truthy(l.auto),l.bg&&(n.theme.bg=w.parseColor(l.bg)),l.fg&&(n.theme.fg=w.parseColor(l.fg)),l.bg&&!l.fg&&(n.autoFg=!0),l.theme&&n.instanceOptions.themes.hasOwnProperty(l.theme)&&(n.theme=T(n.instanceOptions.themes[l.theme],null)),l.text&&(n.text=l.text),l.textmode&&(n.textmode=l.textmode),l.size&&parseFloat(l.size)&&(n.size=parseFloat(l.size)),l.font&&(n.font=l.font),l.align&&(n.align=l.align),l.lineWrap&&(n.lineWrap=l.lineWrap),n.nowrap=w.truthy(l.nowrap),n.outline=w.truthy(l.outline),w.truthy(l.random)){O.vars.cache.themeKeys=O.vars.cache.themeKeys||Object.keys(n.instanceOptions.themes);var d=O.vars.cache.themeKeys[0|Math.random()*O.vars.cache.themeKeys.length];n.theme=T(n.instanceOptions.themes[d],null)}}return n}function a(e){var t=e.mode,n=e.el,r=e.flags,i=e.engineSettings,a=r.dimensions,s=r.theme,l=a.width+"x"+a.height;t=null==t?r.fluid?"fluid":"image":t;var d=/holder_([a-z]+)/g,c=!1;if(null!=r.text&&(s.text=r.text,"object"===n.nodeName.toLowerCase())){for(var f=s.text.split("\\n"),p=0;p1){var b,x=0,A=0,C=0;w=new s.Group("line"+C),("left"===e.align||"right"===e.align)&&(a=e.width*(1-2*(1-r)));for(var E=0;E=a||k===!0)&&(t(g,w,x,g.properties.leading),g.add(w),x=0,A+=g.properties.leading,C+=1,w=new s.Group("line"+C),w.y=A),k!==!0&&(v.moveTo(x,0),x+=m.spaceWidth+T.width,w.add(v))}if(t(g,w,x,g.properties.leading),g.add(w),"left"===e.align)g.moveTo(e.width-i,null,null);else if("right"===e.align){for(b in g.children)w=g.children[b],w.moveTo(e.width-w.width,null,null);g.moveTo(0-(e.width-i),null,null)}else{for(b in g.children)w=g.children[b],w.moveTo((g.width-w.width)/2,null,null);g.moveTo((e.width-g.width)/2,null,null)}g.moveTo(null,(e.height-g.height)/2,null),(e.height-g.height)/2<0&&g.moveTo(null,0,null)}else v=new s.Text(e.text),w=new s.Group("line0"),w.add(v),g.add(w),"left"===e.align?g.moveTo(e.width-i,null,null):"right"===e.align?g.moveTo(0-(e.width-i),null,null):g.moveTo((e.width-m.boundingBox.width)/2,null,null),g.moveTo(null,(e.height-m.boundingBox.height)/2,null);return o}function l(e,t,n,r){var i=parseInt(e,10),a=parseInt(t,10),o=Math.max(i,a),s=Math.min(i,a),l=.8*Math.min(s,o*r);return Math.round(Math.max(n,l))}function h(e){var t;t=null==e||null==e.nodeType?O.vars.resizableImages:[e];for(var n=0,r=t.length;r>n;n++){var i=t[n];if(i.holderData){var a=i.holderData.flags,s=k(i);if(s){if(!i.holderData.resizeUpdate)continue;if(a.fluid&&a.auto){var l=i.holderData.fluidConfig;switch(l.mode){case"width":s.height=s.width/l.ratio;break;case"height":s.width=s.height*l.ratio}}var h={mode:"image",holderSettings:{dimensions:s,theme:a.theme,flags:a},el:i,engineSettings:i.holderData.engineSettings};"exact"==a.textmode&&(a.exactDimensions=s,h.holderSettings.dimensions=a.dimensions),o(h)}else f(i)}}}function u(e){if(e.holderData){var t=k(e);if(t){var n=e.holderData.flags,r={fluidHeight:"%"==n.dimensions.height.slice(-1),fluidWidth:"%"==n.dimensions.width.slice(-1),mode:null,initialDimensions:t};r.fluidWidth&&!r.fluidHeight?(r.mode="width",r.ratio=r.initialDimensions.width/parseFloat(n.dimensions.height)):!r.fluidWidth&&r.fluidHeight&&(r.mode="height",r.ratio=parseFloat(n.dimensions.width)/r.initialDimensions.height),e.holderData.fluidConfig=r}else f(e)}}function d(){var e,n=[],r=Object.keys(O.vars.invisibleImages);r.forEach(function(t){e=O.vars.invisibleImages[t],k(e)&&"img"==e.nodeName.toLowerCase()&&(n.push(e),delete O.vars.invisibleImages[t])}),n.length&&j.run({images:n}),setTimeout(function(){t.requestAnimationFrame(d)},10)}function c(){O.vars.visibilityCheckStarted||(t.requestAnimationFrame(d),O.vars.visibilityCheckStarted=!0)}function f(e){e.holderData.invisibleId||(O.vars.invisibleId+=1,O.vars.invisibleImages["i"+O.vars.invisibleId]=e,e.holderData.invisibleId=O.vars.invisibleId)}function p(e){O.vars.debounceTimer||e.call(this),O.vars.debounceTimer&&t.clearTimeout(O.vars.debounceTimer),O.vars.debounceTimer=t.setTimeout(function(){O.vars.debounceTimer=null,e.call(this)},O.setup.debounce)}function g(){p(function(){h(null)})}var m=n(2),v=n(3),y=n(6),w=n(7),b=n(8),x=n(9),S=n(10),A=n(11),C=n(12),E=n(15),T=w.extend,k=w.dimensionCheck,F=A.svg_ns,j={version:A.version,addTheme:function(e,t){return null!=e&&null!=t&&(O.settings.themes[e]=t),delete O.vars.cache.themeKeys,this},addImage:function(e,t){var n=x.getNodeArray(t);return n.forEach(function(t){var n=x.newEl("img"),r={};r[O.setup.dataAttr]=e,x.setAttr(n,r),t.appendChild(n)}),this},setResizeUpdate:function(e,t){e.holderData&&(e.holderData.resizeUpdate=!!t,e.holderData.resizeUpdate&&h(e))},run:function(e){e=e||{};var n={},o=T(O.settings,e);O.vars.preempted=!0,O.vars.dataAttr=o.dataAttr||O.setup.dataAttr,n.renderer=o.renderer?o.renderer:O.setup.renderer,-1===O.setup.renderers.join(",").indexOf(n.renderer)&&(n.renderer=O.setup.supportsSVG?"svg":O.setup.supportsCanvas?"canvas":"html");var s=x.getNodeArray(o.images),l=x.getNodeArray(o.bgnodes),h=x.getNodeArray(o.stylenodes),u=x.getNodeArray(o.objects);return n.stylesheets=[],n.svgXMLStylesheet=!0,n.noFontFallback=!!o.noFontFallback,n.noBackgroundSize=!!o.noBackgroundSize,h.forEach(function(e){if(e.attributes.rel&&e.attributes.href&&"stylesheet"==e.attributes.rel.value){var t=e.attributes.href.value,r=x.newEl("a");r.href=t;var i=r.protocol+"//"+r.host+r.pathname+r.search;n.stylesheets.push(i)}}),l.forEach(function(e){if(t.getComputedStyle){var r=t.getComputedStyle(e,null).getPropertyValue("background-image"),s=e.getAttribute("data-background-src"),l=s||r,h=null,u=o.domain+"/",d=l.indexOf(u);if(0===d)h=l;else if(1===d&&"?"===l[0])h=l.slice(1);else{var c=l.substr(d).match(/([^\"]*)"?\)/);if(null!==c)h=c[1];else if(0===l.indexOf("url("))throw"Holder: unable to parse background URL: "+l}if(h){var f=i(h,o);f&&a({mode:"background",el:e,flags:f,engineSettings:n})}}}),u.forEach(function(e){var t={};try{t.data=e.getAttribute("data"),t.dataSrc=e.getAttribute(O.vars.dataAttr)}catch(i){}var a=null!=t.data&&0===t.data.indexOf(o.domain),s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain);a?r(o,n,t.data,e):s&&r(o,n,t.dataSrc,e)}),s.forEach(function(e){var t={};try{t.src=e.getAttribute("src"),t.dataSrc=e.getAttribute(O.vars.dataAttr),t.rendered=e.getAttribute("data-holder-rendered")}catch(i){}var a=null!=t.src,s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain),l=null!=t.rendered&&"true"==t.rendered;a?0===t.src.indexOf(o.domain)?r(o,n,t.src,e):s&&(l?r(o,n,t.dataSrc,e):!function(e,t,n,i,a){w.imageExists(e,function(e){e||r(t,n,i,a)})}(t.src,o,n,t.dataSrc,e)):s&&r(o,n,t.dataSrc,e)}),this}},O={settings:{domain:"holder.js",images:"img",objects:"object",bgnodes:"body .holderjs",stylenodes:"head link.holderjs",themes:{gray:{bg:"#EEEEEE",fg:"#AAAAAA"},social:{bg:"#3a5a97",fg:"#FFFFFF"},industrial:{bg:"#434A52",fg:"#C2F200"},sky:{bg:"#0D8FDB",fg:"#FFFFFF"},vine:{bg:"#39DBAC",fg:"#1E292C"},lava:{bg:"#F8591A",fg:"#1C2846"}}},defaults:{size:10,units:"pt",scale:1/16}},z=function(){var e=null,t=null,n=null;return function(r){var i=r.root;if(O.setup.supportsSVG){var a=!1,o=function(e){return document.createTextNode(e)};(null==e||e.parentNode!==document.body)&&(a=!0),e=b.initSVG(e,i.properties.width,i.properties.height),e.style.display="block",a&&(t=x.newEl("text",F),n=o(null),x.setAttr(t,{x:0}),t.appendChild(n),e.appendChild(t),document.body.appendChild(e),e.style.visibility="hidden",e.style.position="absolute",e.style.top="-100%",e.style.left="-100%");var s=i.children.holderTextGroup,l=s.properties;x.setAttr(t,{y:l.font.size,style:w.cssProps({"font-weight":l.font.weight,"font-size":l.font.size+l.font.units,"font-family":l.font.family})});var h=x.newEl("textarea");h.innerHTML=l.text,n.nodeValue=h.value;var u=t.getBBox(),d=Math.ceil(u.width/i.properties.width),c=l.text.split(" "),f=l.text.match(/\\n/g);d+=null==f?0:f.length,n.nodeValue=l.text.replace(/[ ]+/g,"");var p=t.getComputedTextLength(),g=u.width-p,m=Math.round(g/Math.max(1,c.length-1)),v=[];if(d>1){n.nodeValue="";for(var y=0;y=0?t:1)}function a(e){x?i(e):S.push(e)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function C(){document.removeEventListener("DOMContentLoaded",C,!1),document.readyState="complete"},!1),document.readyState="loading");var o=e.document,s=o.documentElement,l="load",h=!1,u="on"+l,d="complete",c="readyState",f="attachEvent",p="detachEvent",g="addEventListener",m="DOMContentLoaded",v="onreadystatechange",y="removeEventListener",w=g in o,b=h,x=h,S=[];if(o[c]===d)i(t);else if(w)o[g](m,n,h),e[g](l,n,h);else{o[f](v,n),e[f](u,n);try{b=null==e.frameElement&&s}catch(A){}b&&b.doScroll&&!function E(){if(!x){try{b.doScroll("left")}catch(e){return i(E,50)}r(),t()}}()}return a.version="1.4.0",a.isReady=function(){return x},a}e.exports="undefined"!=typeof window&&n(window)},function(e,t,n){var r=encodeURIComponent,i=decodeURIComponent,a=n(4),o=n(5),s=/(\w+)\[(\d+)\]/,l=/\w+\.\w+/;t.parse=function(e){if("string"!=typeof e)return{};if(e=a(e),""===e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t={},n=e.split("&"),r=0;r=0;r--)n=e.charCodeAt(r),t.unshift(n>128?["&#",n,";"].join(""):e[r]);return t.join("")},t.imageExists=function(e,t){var n=new Image;n.onerror=function(){t.call(this,!1)},n.onload=function(){t.call(this,!0)},n.src=e},t.decodeHtmlEntity=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})},t.dimensionCheck=function(e){var t={height:e.clientHeight,width:e.clientWidth};return t.height&&t.width?t:!1},t.truthy=function(e){return"string"==typeof e?"true"===e||"yes"===e||"1"===e||"on"===e||"✓"===e:!!e},t.parseColor=function(e){var t,n=/(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i,r=/^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,i=/^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/,a=e.match(n);if(null!==a)return t=a[1]||a[2],"#"!==t[0]?"#"+t:t;if(a=e.match(r),null!==a)return t="rgb("+a.slice(1).join(",")+")";if(a=e.match(i),null!==a){const o=function(e){return"0."+e.split(".")[1]},s=a.slice(1).map(function(e,t){return 3===t?o(e):e});return t="rgba("+s.join(",")+")"}return null},t.canvasRatio=function(){var t=1,n=1;if(e.document){var r=e.document.createElement("canvas");if(r.getContext){var i=r.getContext("2d");t=e.devicePixelRatio||1,n=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1}}return t/n}}).call(t,function(){return this}())},function(e,t,n){(function(e){var r=n(9),i="http://www.w3.org/2000/svg",a=8;t.initSVG=function(e,t,n){var o,s,l=!1;e&&e.querySelector?(s=e.querySelector("style"),null===s&&(l=!0)):(e=r.newEl("svg",i),l=!0),l&&(o=r.newEl("defs",i),s=r.newEl("style",i),r.setAttr(s,{type:"text/css"}),o.appendChild(s),e.appendChild(o)),e.webkitMatchesSelector&&e.setAttribute("xmlns",i);for(var h=0;h=0;l--){var h=s.createProcessingInstruction("xml-stylesheet",'href="'+o[l]+'" rel="stylesheet"');s.insertBefore(h,s.firstChild)}s.removeChild(s.documentElement),a=i.serializeToString(s)}var u=i.serializeToString(t);return u=u.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),a+u}}}).call(t,function(){return this}())},function(e,t){(function(e){t.newEl=function(t,n){return e.document?null==n?e.document.createElement(t):e.document.createElementNS(n,t):void 0},t.setAttr=function(e,t){for(var n in t)e.setAttribute(n,t[n])},t.createXML=function(){return e.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0},t.getNodeArray=function(t){var n=null;return"string"==typeof t?n=document.querySelectorAll(t):e.NodeList&&t instanceof e.NodeList?n=t:e.Node&&t instanceof e.Node?n=[t]:e.HTMLCollection&&t instanceof e.HTMLCollection?n=t:t instanceof Array?n=t:null===t&&(n=[]),n=Array.prototype.slice.call(n)}}).call(t,function(){return this}())},function(e,t){var n=function(e,t){"string"==typeof e&&(this.original=e,"#"===e.charAt(0)&&(e=e.slice(1)),/[^a-f0-9]+/i.test(e)||(3===e.length&&(e=e.replace(/./g,"$&$&")),6===e.length&&(this.alpha=1,t&&t.alpha&&(this.alpha=t.alpha),this.set(parseInt(e,16)))))};n.rgb2hex=function(e,t,n){function r(e){var t=(0|e).toString(16);return 16>e&&(t="0"+t),t}return[e,t,n].map(r).join("")},n.hsl2rgb=function(e,t,n){var r=e/60,i=(1-Math.abs(2*n-1))*t,a=i*(1-Math.abs(parseInt(r)%2-1)),o=n-i/2,s=0,l=0,h=0;return r>=0&&1>r?(s=i,l=a):r>=1&&2>r?(s=a,l=i):r>=2&&3>r?(l=i,h=a):r>=3&&4>r?(l=a,h=i):r>=4&&5>r?(s=a,h=i):r>=5&&6>r&&(s=i,h=a),s+=o,l+=o,h+=o,s=parseInt(255*s),l=parseInt(255*l),h=parseInt(255*h),[s,l,h]},n.prototype.set=function(e){this.raw=e;var t=(16711680&this.raw)>>16,n=(65280&this.raw)>>8,r=255&this.raw,i=.2126*t+.7152*n+.0722*r,a=-.09991*t-.33609*n+.436*r,o=.615*t-.55861*n-.05639*r;return this.rgb={r:t,g:n,b:r},this.yuv={y:i,u:a,v:o},this},n.prototype.lighten=function(e){var t=Math.min(1,Math.max(0,Math.abs(e)))*(0>e?-1:1),r=255*t|0,i=Math.min(255,Math.max(0,this.rgb.r+r)),a=Math.min(255,Math.max(0,this.rgb.g+r)),o=Math.min(255,Math.max(0,this.rgb.b+r)),s=n.rgb2hex(i,a,o);return new n(s)},n.prototype.toHex=function(e){return(e?"#":"")+this.raw.toString(16)},n.prototype.lighterThan=function(e){return e instanceof n||(e=new n(e)),this.yuv.y>e.yuv.y},n.prototype.blendAlpha=function(e){e instanceof n||(e=new n(e));var t=e,r=this,i=t.alpha*t.rgb.r+(1-t.alpha)*r.rgb.r,a=t.alpha*t.rgb.g+(1-t.alpha)*r.rgb.g,o=t.alpha*t.rgb.b+(1-t.alpha)*r.rgb.b;return new n(n.rgb2hex(i,a,o))},e.exports=n},function(e,t){e.exports={version:"2.9.7",svg_ns:"http://www.w3.org/2000/svg"}},function(e,t,n){function r(e,t){return d.element({tag:t,width:e.width,height:e.height,fill:e.properties.fill})}function i(e){return h.cssProps({fill:e.fill,"font-weight":e.font.weight,"font-family":e.font.family+", monospace","font-size":e.font.size+e.font.units})}function a(e,t,n){var r=n/2;return["M",r,r,"H",e-r,"V",t-r,"H",r,"V",0,"M",0,r,"L",e,t-r,"M",0,t-r,"L",e,r].join(" ")}var o=n(13),s=n(8),l=n(11),h=n(7),u=l.svg_ns,d={element:function(e){var t=e.tag,n=e.content||"";return delete e.tag,delete e.content,[t,n,e]}};e.exports=function(e,t){var n=t.engineSettings,l=n.stylesheets,h=l.map(function(e){return''}).join("\n"),c="holder_"+Number(new Date).toString(16),f=e.root,p=f.children.holderTextGroup,g="#"+c+" text { "+i(p.properties)+" } ";p.y+=.8*p.textPositionData.boundingBox.height;var m=[];Object.keys(p.children).forEach(function(e){var t=p.children[e];Object.keys(t.children).forEach(function(e){var n=t.children[e],r=p.x+t.x+n.x,i=p.y+t.y+n.y,a=d.element({tag:"text",content:n.properties.text,x:r,y:i});m.push(a)})});var v=d.element({tag:"g",content:m}),y=null;if(f.children.holderBg.properties.outline){var w=f.children.holderBg.properties.outline;y=d.element({tag:"path",d:a(f.children.holderBg.width,f.children.holderBg.height,w.width),"stroke-width":w.width,stroke:w.fill,fill:"none"})}var b=r(f.children.holderBg,"rect"),x=[];x.push(b),w&&x.push(y),x.push(v);var S=d.element({tag:"g",id:c,content:x}),A=d.element({tag:"style",content:g,type:"text/css"}),C=d.element({tag:"defs",content:A}),E=d.element({tag:"svg",content:[C,S],width:f.properties.width,height:f.properties.height,xmlns:u,viewBox:[0,0,f.properties.width,f.properties.height].join(" "),preserveAspectRatio:"none"}),T=o(E);/\&(x)?#[0-9A-Fa-f]/.test(T[0])&&(T[0]=T[0].replace(/&#/gm,"&#")),T=h+T[0];var k=s.svgStringToDataURI(T,"background"===t.mode);return k}},function(e,t,n){n(14);e.exports=function r(e,t,n){"use strict";function i(e){var t=e.match(/^[\w-]+/),r={tag:t?t[0]:"div",attr:{},children:[]},i=e.match(/#([\w-]+)/),a=e.match(/\$([\w-]+)/),o=e.match(/\.[\w-]+/g);return i&&(r.attr.id=i[1],n[i[1]]=r),a&&(n[a[1]]=r),o&&(r.attr["class"]=o.join(" ").replace(/\./g,"")),e.match(/&$/g)&&(f=!1),r}function a(e,t){return null!==t&&t!==!1&&void 0!==t?"string"!=typeof t&&"object"!=typeof t?String(t):t:void 0}function o(e){return e||0===e?String(e).replace(/&/g,"&").replace(/"/g,"""):""}function s(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}var l,h,u,d,c=1,f=!0;if(n=n||{},"string"==typeof e[0])e[0]=i(e[0]);else{if(!Array.isArray(e[0]))throw new Error("First element of array must be a string, or an array and not "+JSON.stringify(e[0]));c=0}for(;c",e[0]=l}return n[0]=e[0],u&&u(e[0]),n}},function(e,t){"use strict";function n(e){var t=""+e,n=r.exec(t);if(!n)return t;var i,a="",o=0,s=0;for(o=n.index;o]/;e.exports=n},function(e,t,n){var r=n(9),i=n(7);e.exports=function(){var e=r.newEl("canvas"),t=null;return function(n){null==t&&(t=e.getContext("2d"));var r=i.canvasRatio(),a=n.root;e.width=r*a.properties.width,e.height=r*a.properties.height,t.textBaseline="middle";var o=a.children.holderBg,s=r*o.width,l=r*o.height,h=2,u=h/2;t.fillStyle=o.properties.fill,t.fillRect(0,0,s,l),o.properties.outline&&(t.strokeStyle=o.properties.outline.fill,t.lineWidth=o.properties.outline.width,t.moveTo(u,u),t.lineTo(s-u,u),t.lineTo(s-u,l-u),t.lineTo(u,l-u),t.lineTo(u,u),t.moveTo(0,u),t.lineTo(s,l-u),t.moveTo(0,l-u),t.lineTo(s,u),t.stroke());var d=a.children.holderTextGroup;t.font=d.properties.font.weight+" "+r*d.properties.font.size+d.properties.font.units+" "+d.properties.font.family+", monospace",t.fillStyle=d.properties.fill;for(var c in d.children){var f=d.children[c];for(var p in f.children){var g=f.children[p],m=r*(d.x+f.x+g.x),v=r*(d.y+f.y+g.y+d.properties.leading/2); + +t.fillText(g.properties.text,m,v)}}return e.toDataURL("image/png")}}()}])}),function(e,t){t&&(Holder=e.Holder)}(this,"undefined"!=typeof Meteor&&"undefined"!=typeof Package); \ No newline at end of file diff --git a/文件下载/holder-v2.9.8.zip b/文件下载/holder-v2.9.8.zip new file mode 100644 index 0000000000000000000000000000000000000000..4388b49737d5488f9dba03d87df9a53917b25db1 GIT binary patch literal 156658 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
lc4N+m8e+Q_QCZTinQT_a>J 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±+&|5_UUO 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 z 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 Bbld;{ literal 0 HcmV?d00001 diff --git a/静态站点/Bootstrap4/plugs/holder/holder.js b/静态站点/Bootstrap4/plugs/holder/holder.js new file mode 100644 index 0000000..db1e43b --- /dev/null +++ b/静态站点/Bootstrap4/plugs/holder/holder.js @@ -0,0 +1,3063 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +(function (window) { + if (!window.document) return; + var document = window.document; + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + if (!document.querySelectorAll) { + document.querySelectorAll = function (selectors) { + var style = document.createElement('style'), elements = [], element; + document.documentElement.firstChild.appendChild(style); + document._qsa = []; + + style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}'; + window.scrollBy(0, 0); + style.parentNode.removeChild(style); + + while (document._qsa.length) { + element = document._qsa.shift(); + element.style.removeAttribute('x-qsa'); + elements.push(element); + } + document._qsa = null; + return elements; + }; + } + + if (!document.querySelector) { + document.querySelector = function (selectors) { + var elements = document.querySelectorAll(selectors); + return (elements.length) ? elements[0] : null; + }; + } + + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (classNames) { + classNames = String(classNames).replace(/^|\s+/g, '.'); + return document.querySelectorAll(classNames); + }; + } + + //https://github.com/inexorabletash/polyfill + // ES5 15.2.3.14 Object.keys ( O ) + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys + if (!Object.keys) { + Object.keys = function (o) { + if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); } + var ret = [], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + ret.push(p); + } + } + return ret; + }; + } + + // ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] ) + // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun /*, thisp */) { + if (this === void 0 || this === null) { throw TypeError(); } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { throw TypeError(); } + + var thisp = arguments[1], i; + for (i = 0; i < len; i++) { + if (i in t) { + fun.call(thisp, t[i], i, t); + } + } + }; + } + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + (function (global) { + var B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + global.atob = global.atob || function (input) { + input = String(input); + var position = 0, + output = [], + buffer = 0, bits = 0, n; + + input = input.replace(/\s/g, ''); + if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); } + if ((input.length % 4) === 1) { throw Error('InvalidCharacterError'); } + if (/[^+/0-9A-Za-z]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + n = B64_ALPHABET.indexOf(input.charAt(position)); + buffer = (buffer << 6) | n; + bits += 6; + + if (bits === 24) { + output.push(String.fromCharCode((buffer >> 16) & 0xFF)); + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + bits = 0; + buffer = 0; + } + position += 1; + } + + if (bits === 12) { + buffer = buffer >> 4; + output.push(String.fromCharCode(buffer & 0xFF)); + } else if (bits === 18) { + buffer = buffer >> 2; + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + } + + return output.join(''); + }; + + global.btoa = global.btoa || function (input) { + input = String(input); + var position = 0, + out = [], + o1, o2, o3, + e1, e2, e3, e4; + + if (/[^\x00-\xFF]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + o1 = input.charCodeAt(position++); + o2 = input.charCodeAt(position++); + o3 = input.charCodeAt(position++); + + // 111111 112222 222233 333333 + e1 = o1 >> 2; + e2 = ((o1 & 0x3) << 4) | (o2 >> 4); + e3 = ((o2 & 0xf) << 2) | (o3 >> 6); + e4 = o3 & 0x3f; + + if (position === input.length + 2) { + e3 = 64; e4 = 64; + } + else if (position === input.length + 1) { + e4 = 64; + } + + out.push(B64_ALPHABET.charAt(e1), + B64_ALPHABET.charAt(e2), + B64_ALPHABET.charAt(e3), + B64_ALPHABET.charAt(e4)); + } + + return out.join(''); + }; + }(window)); + + //https://gist.github.com/jimeh/332357 + if (!Object.prototype.hasOwnProperty){ + /*jshint -W001, -W103 */ + Object.prototype.hasOwnProperty = function(prop) { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + }; + /*jshint +W001, +W103 */ + } + + // @license http://opensource.org/licenses/MIT + // copyright Paul Irish 2015 + + + // Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill + // github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js + // as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values + + // if you want values similar to what you'd get with real perf.now, place this towards the head of the page + // but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed + + + (function(){ + + if ('performance' in window === false) { + window.performance = {}; + } + + Date.now = (Date.now || function () { // thanks IE8 + return new Date().getTime(); + }); + + if ('now' in window.performance === false){ + + var nowOffset = Date.now(); + + if (performance.timing && performance.timing.navigationStart){ + nowOffset = performance.timing.navigationStart; + } + + window.performance.now = function now(){ + return Date.now() - nowOffset; + }; + } + + })(); + + //requestAnimationFrame polyfill for older Firefox/Chrome versions + if (!window.requestAnimationFrame) { + if (window.webkitRequestAnimationFrame && window.webkitCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-webkit.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return webkitRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.webkitCancelAnimationFrame; + }(window)); + } else if (window.mozRequestAnimationFrame && window.mozCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-moz.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return mozRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.mozCancelAnimationFrame; + }(window)); + } else { + (function (global) { + global.requestAnimationFrame = function (callback) { + return global.setTimeout(callback, 1000 / 60); + }; + + global.cancelAnimationFrame = global.clearTimeout; + })(window); + } + } +})(this); + +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Holder"] = factory(); + else + root["Holder"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - https://imsky.co + */ + + module.exports = __webpack_require__(1); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - http://imsky.co + */ + + //Libraries and functions + var onDomReady = __webpack_require__(2); + var querystring = __webpack_require__(3); + + var SceneGraph = __webpack_require__(6); + var utils = __webpack_require__(7); + var SVG = __webpack_require__(8); + var DOM = __webpack_require__(9); + var Color = __webpack_require__(10); + var constants = __webpack_require__(11); + + var svgRenderer = __webpack_require__(12); + var sgCanvasRenderer = __webpack_require__(15); + + var extend = utils.extend; + var dimensionCheck = utils.dimensionCheck; + + //Constants and definitions + var SVG_NS = constants.svg_ns; + + var Holder = { + version: constants.version, + + /** + * Adds a theme to default settings + * + * @param {string} name Theme name + * @param {Object} theme Theme object, with foreground, background, size, font, and fontweight properties. + */ + addTheme: function(name, theme) { + name != null && theme != null && (App.settings.themes[name] = theme); + delete App.vars.cache.themeKeys; + return this; + }, + + /** + * Appends a placeholder to an element + * + * @param {string} src Placeholder URL string + * @param el A selector or a reference to a DOM node + */ + addImage: function(src, el) { + //todo: use jquery fallback if available for all QSA references + var nodes = DOM.getNodeArray(el); + nodes.forEach(function (node) { + var img = DOM.newEl('img'); + var domProps = {}; + domProps[App.setup.dataAttr] = src; + DOM.setAttr(img, domProps); + node.appendChild(img); + }); + return this; + }, + + /** + * Sets whether or not an image is updated on resize. + * If an image is set to be updated, it is immediately rendered. + * + * @param {Object} el Image DOM element + * @param {Boolean} value Resizable update flag value + */ + setResizeUpdate: function(el, value) { + if (el.holderData) { + el.holderData.resizeUpdate = !!value; + if (el.holderData.resizeUpdate) { + updateResizableElements(el); + } + } + }, + + /** + * Runs Holder with options. By default runs Holder on all images with "holder.js" in their source attributes. + * + * @param {Object} userOptions Options object, can contain domain, themes, images, and bgnodes properties + */ + run: function(userOptions) { + //todo: split processing into separate queues + userOptions = userOptions || {}; + var engineSettings = {}; + var options = extend(App.settings, userOptions); + + App.vars.preempted = true; + App.vars.dataAttr = options.dataAttr || App.setup.dataAttr; + + engineSettings.renderer = options.renderer ? options.renderer : App.setup.renderer; + if (App.setup.renderers.join(',').indexOf(engineSettings.renderer) === -1) { + engineSettings.renderer = App.setup.supportsSVG ? 'svg' : (App.setup.supportsCanvas ? 'canvas' : 'html'); + } + + var images = DOM.getNodeArray(options.images); + var bgnodes = DOM.getNodeArray(options.bgnodes); + var stylenodes = DOM.getNodeArray(options.stylenodes); + var objects = DOM.getNodeArray(options.objects); + + engineSettings.stylesheets = []; + engineSettings.svgXMLStylesheet = true; + engineSettings.noFontFallback = !!options.noFontFallback; + engineSettings.noBackgroundSize = !!options.noBackgroundSize; + + stylenodes.forEach(function (styleNode) { + if (styleNode.attributes.rel && styleNode.attributes.href && styleNode.attributes.rel.value == 'stylesheet') { + var href = styleNode.attributes.href.value; + //todo: write isomorphic relative-to-absolute URL function + var proxyLink = DOM.newEl('a'); + proxyLink.href = href; + var stylesheetURL = proxyLink.protocol + '//' + proxyLink.host + proxyLink.pathname + proxyLink.search; + engineSettings.stylesheets.push(stylesheetURL); + } + }); + + bgnodes.forEach(function (bgNode) { + //Skip processing background nodes if getComputedStyle is unavailable, since only modern browsers would be able to use canvas or SVG to render to background + if (!global.getComputedStyle) return; + var backgroundImage = global.getComputedStyle(bgNode, null).getPropertyValue('background-image'); + var dataBackgroundImage = bgNode.getAttribute('data-background-src'); + var rawURL = dataBackgroundImage || backgroundImage; + + var holderURL = null; + var holderString = options.domain + '/'; + var holderStringIndex = rawURL.indexOf(holderString); + + if (holderStringIndex === 0) { + holderURL = rawURL; + } else if (holderStringIndex === 1 && rawURL[0] === '?') { + holderURL = rawURL.slice(1); + } else { + var fragment = rawURL.substr(holderStringIndex).match(/([^\"]*)"?\)/); + if (fragment !== null) { + holderURL = fragment[1]; + } else if (rawURL.indexOf('url(') === 0) { + throw 'Holder: unable to parse background URL: ' + rawURL; + } + } + + if (holderURL) { + var holderFlags = parseURL(holderURL, options); + if (holderFlags) { + prepareDOMElement({ + mode: 'background', + el: bgNode, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + }); + + objects.forEach(function (object) { + var objectAttr = {}; + + try { + objectAttr.data = object.getAttribute('data'); + objectAttr.dataSrc = object.getAttribute(App.vars.dataAttr); + } catch (e) {} + + var objectHasSrcURL = objectAttr.data != null && objectAttr.data.indexOf(options.domain) === 0; + var objectHasDataSrcURL = objectAttr.dataSrc != null && objectAttr.dataSrc.indexOf(options.domain) === 0; + + if (objectHasSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.data, object); + } else if (objectHasDataSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.dataSrc, object); + } + }); + + images.forEach(function (image) { + var imageAttr = {}; + + try { + imageAttr.src = image.getAttribute('src'); + imageAttr.dataSrc = image.getAttribute(App.vars.dataAttr); + imageAttr.rendered = image.getAttribute('data-holder-rendered'); + } catch (e) {} + + var imageHasSrc = imageAttr.src != null; + var imageHasDataSrcURL = imageAttr.dataSrc != null && imageAttr.dataSrc.indexOf(options.domain) === 0; + var imageRendered = imageAttr.rendered != null && imageAttr.rendered == 'true'; + + if (imageHasSrc) { + if (imageAttr.src.indexOf(options.domain) === 0) { + prepareImageElement(options, engineSettings, imageAttr.src, image); + } else if (imageHasDataSrcURL) { + //Image has a valid data-src and an invalid src + if (imageRendered) { + //If the placeholder has already been render, re-render it + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } else { + //If the placeholder has not been rendered, check if the image exists and render a fallback if it doesn't + (function(src, options, engineSettings, dataSrc, image) { + utils.imageExists(src, function(exists) { + if (!exists) { + prepareImageElement(options, engineSettings, dataSrc, image); + } + }); + })(imageAttr.src, options, engineSettings, imageAttr.dataSrc, image); + } + } + } else if (imageHasDataSrcURL) { + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } + }); + + return this; + } + }; + + var App = { + settings: { + domain: 'holder.js', + images: 'img', + objects: 'object', + bgnodes: 'body .holderjs', + stylenodes: 'head link.holderjs', + themes: { + 'gray': { + bg: '#EEEEEE', + fg: '#AAAAAA' + }, + 'social': { + bg: '#3a5a97', + fg: '#FFFFFF' + }, + 'industrial': { + bg: '#434A52', + fg: '#C2F200' + }, + 'sky': { + bg: '#0D8FDB', + fg: '#FFFFFF' + }, + 'vine': { + bg: '#39DBAC', + fg: '#1E292C' + }, + 'lava': { + bg: '#F8591A', + fg: '#1C2846' + } + } + }, + defaults: { + size: 10, + units: 'pt', + scale: 1 / 16 + } + }; + + /** + * Processes provided source attribute and sets up the appropriate rendering workflow + * + * @private + * @param options Instance options from Holder.run + * @param renderSettings Instance configuration + * @param src Image URL + * @param el Image DOM element + */ + function prepareImageElement(options, engineSettings, src, el) { + var holderFlags = parseURL(src.substr(src.lastIndexOf(options.domain)), options); + if (holderFlags) { + prepareDOMElement({ + mode: null, + el: el, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + + /** + * Processes a Holder URL and extracts configuration from query string + * + * @private + * @param url URL + * @param instanceOptions Instance options from Holder.run + */ + function parseURL(url, instanceOptions) { + var holder = { + theme: extend(App.settings.themes.gray, null), + stylesheets: instanceOptions.stylesheets, + instanceOptions: instanceOptions + }; + + var firstQuestionMark = url.indexOf('?'); + var parts = [url]; + + if (firstQuestionMark !== -1) { + parts = [url.slice(0, firstQuestionMark), url.slice(firstQuestionMark + 1)]; + } + + var basics = parts[0].split('/'); + + holder.holderURL = url; + + var dimensions = basics[1]; + var dimensionData = dimensions.match(/([\d]+p?)x([\d]+p?)/); + + if (!dimensionData) return false; + + holder.fluid = dimensions.indexOf('p') !== -1; + + holder.dimensions = { + width: dimensionData[1].replace('p', '%'), + height: dimensionData[2].replace('p', '%') + }; + + if (parts.length === 2) { + var options = querystring.parse(parts[1]); + + // Dimensions + + if (utils.truthy(options.ratio)) { + holder.fluid = true; + var ratioWidth = parseFloat(holder.dimensions.width.replace('%', '')); + var ratioHeight = parseFloat(holder.dimensions.height.replace('%', '')); + + ratioHeight = Math.floor(100 * (ratioHeight / ratioWidth)); + ratioWidth = 100; + + holder.dimensions.width = ratioWidth + '%'; + holder.dimensions.height = ratioHeight + '%'; + } + + holder.auto = utils.truthy(options.auto); + + // Colors + + if (options.bg) { + holder.theme.bg = utils.parseColor(options.bg); + } + + if (options.fg) { + holder.theme.fg = utils.parseColor(options.fg); + } + + //todo: add automatic foreground to themes without foreground + if (options.bg && !options.fg) { + holder.autoFg = true; + } + + if (options.theme && holder.instanceOptions.themes.hasOwnProperty(options.theme)) { + holder.theme = extend(holder.instanceOptions.themes[options.theme], null); + } + + // Text + + if (options.text) { + holder.text = options.text; + } + + if (options.textmode) { + holder.textmode = options.textmode; + } + + if (options.size && parseFloat(options.size)) { + holder.size = parseFloat(options.size); + } + + if (options.font) { + holder.font = options.font; + } + + if (options.align) { + holder.align = options.align; + } + + if (options.lineWrap) { + holder.lineWrap = options.lineWrap; + } + + holder.nowrap = utils.truthy(options.nowrap); + + // Miscellaneous + + holder.outline = utils.truthy(options.outline); + + if (utils.truthy(options.random)) { + App.vars.cache.themeKeys = App.vars.cache.themeKeys || Object.keys(holder.instanceOptions.themes); + var _theme = App.vars.cache.themeKeys[0 | Math.random() * App.vars.cache.themeKeys.length]; + holder.theme = extend(holder.instanceOptions.themes[_theme], null); + } + } + + return holder; + } + + /** + * Modifies the DOM to fit placeholders and sets up resizable image callbacks (for fluid and automatically sized placeholders) + * + * @private + * @param settings DOM prep settings + */ + function prepareDOMElement(prepSettings) { + var mode = prepSettings.mode; + var el = prepSettings.el; + var flags = prepSettings.flags; + var _engineSettings = prepSettings.engineSettings; + var dimensions = flags.dimensions, + theme = flags.theme; + var dimensionsCaption = dimensions.width + 'x' + dimensions.height; + mode = mode == null ? (flags.fluid ? 'fluid' : 'image') : mode; + var holderTemplateRe = /holder_([a-z]+)/g; + var dimensionsInText = false; + + if (flags.text != null) { + theme.text = flags.text; + + // SVG embedding doesn't parse Unicode properly + if (el.nodeName.toLowerCase() === 'object') { + var textLines = theme.text.split('\\n'); + for (var k = 0; k < textLines.length; k++) { + textLines[k] = utils.encodeHtmlEntity(textLines[k]); + } + theme.text = textLines.join('\\n'); + } + } + + if (theme.text) { + var holderTemplateMatches = theme.text.match(holderTemplateRe); + + if (holderTemplateMatches !== null) { + //todo: optimize template replacement + holderTemplateMatches.forEach(function (match) { + if (match === 'holder_dimensions') { + theme.text = theme.text.replace(match, dimensionsCaption); + } + }); + } + } + + var holderURL = flags.holderURL; + var engineSettings = extend(_engineSettings, null); + + if (flags.font) { + /* + If external fonts are used in a placeholder rendered with SVG, Holder falls back to canvas. + + This is done because Firefox and Chrome disallow embedded SVGs from referencing external assets. + The workaround is either to change the placeholder tag from to or to use the canvas renderer. + */ + theme.font = flags.font; + if (!engineSettings.noFontFallback && el.nodeName.toLowerCase() === 'img' && App.setup.supportsCanvas && engineSettings.renderer === 'svg') { + engineSettings = extend(engineSettings, { + renderer: 'canvas' + }); + } + } + + //Chrome and Opera require a quick 10ms re-render if web fonts are used with canvas + if (flags.font && engineSettings.renderer == 'canvas') { + engineSettings.reRender = true; + } + + if (mode == 'background') { + if (el.getAttribute('data-background-src') == null) { + DOM.setAttr(el, { + 'data-background-src': holderURL + }); + } + } else { + var domProps = {}; + domProps[App.vars.dataAttr] = holderURL; + DOM.setAttr(el, domProps); + } + + flags.theme = theme; + + //todo consider using all renderSettings in holderData + el.holderData = { + flags: flags, + engineSettings: engineSettings + }; + + if (mode == 'image' || mode == 'fluid') { + DOM.setAttr(el, { + 'alt': theme.text ? (dimensionsInText ? theme.text : theme.text + ' [' + dimensionsCaption + ']') : dimensionsCaption + }); + } + + var renderSettings = { + mode: mode, + el: el, + holderSettings: { + dimensions: dimensions, + theme: theme, + flags: flags + }, + engineSettings: engineSettings + }; + + if (mode == 'image') { + if (!flags.auto) { + el.style.width = dimensions.width + 'px'; + el.style.height = dimensions.height + 'px'; + } + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + render(renderSettings); + + if (flags.textmode == 'exact') { + el.holderData.resizeUpdate = true; + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } else if (mode == 'background' && engineSettings.renderer != 'html') { + render(renderSettings); + } else if (mode == 'fluid') { + el.holderData.resizeUpdate = true; + + if (dimensions.height.slice(-1) == '%') { + el.style.height = dimensions.height; + } else if (flags.auto == null || !flags.auto) { + el.style.height = dimensions.height + 'px'; + } + if (dimensions.width.slice(-1) == '%') { + el.style.width = dimensions.width; + } else if (flags.auto == null || !flags.auto) { + el.style.width = dimensions.width + 'px'; + } + if (el.style.display == 'inline' || el.style.display === '' || el.style.display == 'none') { + el.style.display = 'block'; + } + + setInitialDimensions(el); + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } + + /** + * Core function that takes output from renderers and sets it as the source or background-image of the target element + * + * @private + * @param renderSettings Renderer settings + */ + function render(renderSettings) { + var image = null; + var mode = renderSettings.mode; + var el = renderSettings.el; + var holderSettings = renderSettings.holderSettings; + var engineSettings = renderSettings.engineSettings; + + switch (engineSettings.renderer) { + case 'svg': + if (!App.setup.supportsSVG) return; + break; + case 'canvas': + if (!App.setup.supportsCanvas) return; + break; + default: + return; + } + + //todo: move generation of scene up to flag generation to reduce extra object creation + var scene = { + width: holderSettings.dimensions.width, + height: holderSettings.dimensions.height, + theme: holderSettings.theme, + flags: holderSettings.flags + }; + + var sceneGraph = buildSceneGraph(scene); + + function getRenderedImage() { + var image = null; + switch (engineSettings.renderer) { + case 'canvas': + image = sgCanvasRenderer(sceneGraph, renderSettings); + break; + case 'svg': + image = svgRenderer(sceneGraph, renderSettings); + break; + default: + throw 'Holder: invalid renderer: ' + engineSettings.renderer; + } + + return image; + } + + image = getRenderedImage(); + + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + + //todo: add canvas rendering + if (mode == 'background') { + el.style.backgroundImage = 'url(' + image + ')'; + + if (!engineSettings.noBackgroundSize) { + el.style.backgroundSize = scene.width + 'px ' + scene.height + 'px'; + } + } else { + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + if (engineSettings.reRender) { + global.setTimeout(function () { + var image = getRenderedImage(); + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + //todo: refactor this code into a function + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + }, 150); + } + } + //todo: account for re-rendering + DOM.setAttr(el, { + 'data-holder-rendered': true + }); + } + + /** + * Core function that takes a Holder scene description and builds a scene graph + * + * @private + * @param scene Holder scene object + */ + //todo: make this function reusable + //todo: merge app defaults and setup properties into the scene argument + function buildSceneGraph(scene) { + var fontSize = App.defaults.size; + if (parseFloat(scene.theme.size)) { + fontSize = scene.theme.size; + } else if (parseFloat(scene.flags.size)) { + fontSize = scene.flags.size; + } + + scene.font = { + family: scene.theme.font ? scene.theme.font : 'Arial, Helvetica, Open Sans, sans-serif', + size: textSize(scene.width, scene.height, fontSize, App.defaults.scale), + units: scene.theme.units ? scene.theme.units : App.defaults.units, + weight: scene.theme.fontweight ? scene.theme.fontweight : 'bold' + }; + + scene.text = scene.theme.text || Math.floor(scene.width) + 'x' + Math.floor(scene.height); + + scene.noWrap = scene.theme.nowrap || scene.flags.nowrap; + + scene.align = scene.theme.align || scene.flags.align || 'center'; + + switch (scene.flags.textmode) { + case 'literal': + scene.text = scene.flags.dimensions.width + 'x' + scene.flags.dimensions.height; + break; + case 'exact': + if (!scene.flags.exactDimensions) break; + scene.text = Math.floor(scene.flags.exactDimensions.width) + 'x' + Math.floor(scene.flags.exactDimensions.height); + break; + } + + var lineWrap = scene.flags.lineWrap || App.setup.lineWrapRatio; + var sceneMargin = scene.width * lineWrap; + var maxLineWidth = sceneMargin; + + var sceneGraph = new SceneGraph({ + width: scene.width, + height: scene.height + }); + + var Shape = sceneGraph.Shape; + + var holderBg = new Shape.Rect('holderBg', { + fill: scene.theme.bg + }); + + holderBg.resize(scene.width, scene.height); + sceneGraph.root.add(holderBg); + + if (scene.flags.outline) { + var outlineColor = new Color(holderBg.properties.fill); + outlineColor = outlineColor.lighten(outlineColor.lighterThan('7f7f7f') ? -0.1 : 0.1); + holderBg.properties.outline = { + fill: outlineColor.toHex(true), + width: 2 + }; + } + + var holderTextColor = scene.theme.fg; + + if (scene.flags.autoFg) { + var holderBgColor = new Color(holderBg.properties.fill); + var lightColor = new Color('fff'); + var darkColor = new Color('000', { + 'alpha': 0.285714 + }); + + holderTextColor = holderBgColor.blendAlpha(holderBgColor.lighterThan('7f7f7f') ? darkColor : lightColor).toHex(true); + } + + var holderTextGroup = new Shape.Group('holderTextGroup', { + text: scene.text, + align: scene.align, + font: scene.font, + fill: holderTextColor + }); + + holderTextGroup.moveTo(null, null, 1); + sceneGraph.root.add(holderTextGroup); + + var tpdata = holderTextGroup.textPositionData = stagingRenderer(sceneGraph); + if (!tpdata) { + throw 'Holder: staging fallback not supported yet.'; + } + holderTextGroup.properties.leading = tpdata.boundingBox.height; + + var textNode = null; + var line = null; + + function finalizeLine(parent, line, width, height) { + line.width = width; + line.height = height; + parent.width = Math.max(parent.width, line.width); + parent.height += line.height; + } + + if (tpdata.lineCount > 1) { + var offsetX = 0; + var offsetY = 0; + var lineIndex = 0; + var lineKey; + line = new Shape.Group('line' + lineIndex); + + //Double margin so that left/right-aligned next is not flush with edge of image + if (scene.align === 'left' || scene.align === 'right') { + maxLineWidth = scene.width * (1 - (1 - lineWrap) * 2); + } + + for (var i = 0; i < tpdata.words.length; i++) { + var word = tpdata.words[i]; + textNode = new Shape.Text(word.text); + var newline = word.text == '\\n'; + if (!scene.noWrap && (offsetX + word.width >= maxLineWidth || newline === true)) { + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + offsetX = 0; + offsetY += holderTextGroup.properties.leading; + lineIndex += 1; + line = new Shape.Group('line' + lineIndex); + line.y = offsetY; + } + if (newline === true) { + continue; + } + textNode.moveTo(offsetX, 0); + offsetX += tpdata.spaceWidth + word.width; + line.add(textNode); + } + + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo(scene.width - line.width, null, null); + } + + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo((holderTextGroup.width - line.width) / 2, null, null); + } + + holderTextGroup.moveTo((scene.width - holderTextGroup.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - holderTextGroup.height) / 2, null); + + //If the text exceeds vertical space, move it down so the first line is visible + if ((scene.height - holderTextGroup.height) / 2 < 0) { + holderTextGroup.moveTo(null, 0, null); + } + } else { + textNode = new Shape.Text(scene.text); + line = new Shape.Group('line0'); + line.add(textNode); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + holderTextGroup.moveTo((scene.width - tpdata.boundingBox.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - tpdata.boundingBox.height) / 2, null); + } + + //todo: renderlist + return sceneGraph; + } + + /** + * Adaptive text sizing function + * + * @private + * @param width Parent width + * @param height Parent height + * @param fontSize Requested text size + * @param scale Proportional scale of text + */ + function textSize(width, height, fontSize, scale) { + var stageWidth = parseInt(width, 10); + var stageHeight = parseInt(height, 10); + + var bigSide = Math.max(stageWidth, stageHeight); + var smallSide = Math.min(stageWidth, stageHeight); + + var newHeight = 0.8 * Math.min(smallSide, bigSide * scale); + return Math.round(Math.max(fontSize, newHeight)); + } + + /** + * Iterates over resizable (fluid or auto) placeholders and renders them + * + * @private + * @param element Optional element selector, specified only if a specific element needs to be re-rendered + */ + function updateResizableElements(element) { + var images; + if (element == null || element.nodeType == null) { + images = App.vars.resizableImages; + } else { + images = [element]; + } + for (var i = 0, l = images.length; i < l; i++) { + var el = images[i]; + if (el.holderData) { + var flags = el.holderData.flags; + var dimensions = dimensionCheck(el); + if (dimensions) { + if (!el.holderData.resizeUpdate) { + continue; + } + + if (flags.fluid && flags.auto) { + var fluidConfig = el.holderData.fluidConfig; + switch (fluidConfig.mode) { + case 'width': + dimensions.height = dimensions.width / fluidConfig.ratio; + break; + case 'height': + dimensions.width = dimensions.height * fluidConfig.ratio; + break; + } + } + + var settings = { + mode: 'image', + holderSettings: { + dimensions: dimensions, + theme: flags.theme, + flags: flags + }, + el: el, + engineSettings: el.holderData.engineSettings + }; + + if (flags.textmode == 'exact') { + flags.exactDimensions = dimensions; + settings.holderSettings.dimensions = flags.dimensions; + } + + render(settings); + } else { + setInvisible(el); + } + } + } + } + + /** + * Sets up aspect ratio metadata for fluid placeholders, in order to preserve proportions when resizing + * + * @private + * @param el Image DOM element + */ + function setInitialDimensions(el) { + if (el.holderData) { + var dimensions = dimensionCheck(el); + if (dimensions) { + var flags = el.holderData.flags; + + var fluidConfig = { + fluidHeight: flags.dimensions.height.slice(-1) == '%', + fluidWidth: flags.dimensions.width.slice(-1) == '%', + mode: null, + initialDimensions: dimensions + }; + + if (fluidConfig.fluidWidth && !fluidConfig.fluidHeight) { + fluidConfig.mode = 'width'; + fluidConfig.ratio = fluidConfig.initialDimensions.width / parseFloat(flags.dimensions.height); + } else if (!fluidConfig.fluidWidth && fluidConfig.fluidHeight) { + fluidConfig.mode = 'height'; + fluidConfig.ratio = parseFloat(flags.dimensions.width) / fluidConfig.initialDimensions.height; + } + + el.holderData.fluidConfig = fluidConfig; + } else { + setInvisible(el); + } + } + } + + /** + * Iterates through all current invisible images, and if they're visible, renders them and removes them from further checks. Runs every animation frame. + * + * @private + */ + function visibilityCheck() { + var renderableImages = []; + var keys = Object.keys(App.vars.invisibleImages); + var el; + + keys.forEach(function (key) { + el = App.vars.invisibleImages[key]; + if (dimensionCheck(el) && el.nodeName.toLowerCase() == 'img') { + renderableImages.push(el); + delete App.vars.invisibleImages[key]; + } + }); + + if (renderableImages.length) { + Holder.run({ + images: renderableImages + }); + } + + // Done to prevent 100% CPU usage via aggressive calling of requestAnimationFrame + setTimeout(function () { + global.requestAnimationFrame(visibilityCheck); + }, 10); + } + + /** + * Starts checking for invisible placeholders if not doing so yet. Does nothing otherwise. + * + * @private + */ + function startVisibilityCheck() { + if (!App.vars.visibilityCheckStarted) { + global.requestAnimationFrame(visibilityCheck); + App.vars.visibilityCheckStarted = true; + } + } + + /** + * Sets a unique ID for an image detected to be invisible and adds it to the map of invisible images checked by visibilityCheck + * + * @private + * @param el Invisible DOM element + */ + function setInvisible(el) { + if (!el.holderData.invisibleId) { + App.vars.invisibleId += 1; + App.vars.invisibleImages['i' + App.vars.invisibleId] = el; + el.holderData.invisibleId = App.vars.invisibleId; + } + } + + //todo: see if possible to convert stagingRenderer to use HTML only + var stagingRenderer = (function() { + var svg = null, + stagingText = null, + stagingTextNode = null; + return function(graph) { + var rootNode = graph.root; + if (App.setup.supportsSVG) { + var firstTimeSetup = false; + var tnode = function(text) { + return document.createTextNode(text); + }; + if (svg == null || svg.parentNode !== document.body) { + firstTimeSetup = true; + } + + svg = SVG.initSVG(svg, rootNode.properties.width, rootNode.properties.height); + //Show staging element before staging + svg.style.display = 'block'; + + if (firstTimeSetup) { + stagingText = DOM.newEl('text', SVG_NS); + stagingTextNode = tnode(null); + DOM.setAttr(stagingText, { + x: 0 + }); + stagingText.appendChild(stagingTextNode); + svg.appendChild(stagingText); + document.body.appendChild(svg); + svg.style.visibility = 'hidden'; + svg.style.position = 'absolute'; + svg.style.top = '-100%'; + svg.style.left = '-100%'; + //todo: workaround for zero-dimension tag in Opera 12 + //svg.setAttribute('width', 0); + //svg.setAttribute('height', 0); + } + + var holderTextGroup = rootNode.children.holderTextGroup; + var htgProps = holderTextGroup.properties; + DOM.setAttr(stagingText, { + 'y': htgProps.font.size, + 'style': utils.cssProps({ + 'font-weight': htgProps.font.weight, + 'font-size': htgProps.font.size + htgProps.font.units, + 'font-family': htgProps.font.family + }) + }); + + //Unescape HTML entities to get approximately the right width + var txt = DOM.newEl('textarea'); + txt.innerHTML = htgProps.text; + stagingTextNode.nodeValue = txt.value; + + //Get bounding box for the whole string (total width and height) + var stagingTextBBox = stagingText.getBBox(); + + //Get line count and split the string into words + var lineCount = Math.ceil(stagingTextBBox.width / rootNode.properties.width); + var words = htgProps.text.split(' '); + var newlines = htgProps.text.match(/\\n/g); + lineCount += newlines == null ? 0 : newlines.length; + + //Get bounding box for the string with spaces removed + stagingTextNode.nodeValue = htgProps.text.replace(/[ ]+/g, ''); + var computedNoSpaceLength = stagingText.getComputedTextLength(); + + //Compute average space width + var diffLength = stagingTextBBox.width - computedNoSpaceLength; + var spaceWidth = Math.round(diffLength / Math.max(1, words.length - 1)); + + //Get widths for every word with space only if there is more than one line + var wordWidths = []; + if (lineCount > 1) { + stagingTextNode.nodeValue = ''; + for (var i = 0; i < words.length; i++) { + if (words[i].length === 0) continue; + stagingTextNode.nodeValue = utils.decodeHtmlEntity(words[i]); + var bbox = stagingText.getBBox(); + wordWidths.push({ + text: words[i], + width: bbox.width + }); + } + } + + //Hide staging element after staging + svg.style.display = 'none'; + + return { + spaceWidth: spaceWidth, + lineCount: lineCount, + boundingBox: stagingTextBBox, + words: wordWidths + }; + } else { + //todo: canvas fallback for measuring text on android 2.3 + return false; + } + }; + })(); + + //Helpers + + /** + * Prevents a function from being called too often, waits until a timer elapses to call it again + * + * @param fn Function to call + */ + function debounce(fn) { + if (!App.vars.debounceTimer) fn.call(this); + if (App.vars.debounceTimer) global.clearTimeout(App.vars.debounceTimer); + App.vars.debounceTimer = global.setTimeout(function() { + App.vars.debounceTimer = null; + fn.call(this); + }, App.setup.debounce); + } + + /** + * Holder-specific resize/orientation change callback, debounced to prevent excessive execution + */ + function resizeEvent() { + debounce(function() { + updateResizableElements(null); + }); + } + + //Set up flags + + for (var flag in App.flags) { + if (!App.flags.hasOwnProperty(flag)) continue; + App.flags[flag].match = function(val) { + return val.match(this.regex); + }; + } + + //Properties set once on setup + + App.setup = { + renderer: 'html', + debounce: 100, + ratio: 1, + supportsCanvas: false, + supportsSVG: false, + lineWrapRatio: 0.9, + dataAttr: 'data-src', + renderers: ['html', 'canvas', 'svg'] + }; + + //Properties modified during runtime + + App.vars = { + preempted: false, + resizableImages: [], + invisibleImages: {}, + invisibleId: 0, + visibilityCheckStarted: false, + debounceTimer: null, + cache: {} + }; + + //Pre-flight + + (function() { + var canvas = DOM.newEl('canvas'); + + if (canvas.getContext) { + if (canvas.toDataURL('image/png').indexOf('data:image/png') != -1) { + App.setup.renderer = 'canvas'; + App.setup.supportsCanvas = true; + } + } + + if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect) { + App.setup.renderer = 'svg'; + App.setup.supportsSVG = true; + } + })(); + + //Starts checking for invisible placeholders + startVisibilityCheck(); + + if (onDomReady) { + onDomReady(function() { + if (!App.vars.preempted) { + Holder.run(); + } + if (global.addEventListener) { + global.addEventListener('resize', resizeEvent, false); + global.addEventListener('orientationchange', resizeEvent, false); + } else { + global.attachEvent('onresize', resizeEvent); + } + + if (typeof global.Turbolinks == 'object') { + global.document.addEventListener('page:change', function() { + Holder.run(); + }); + } + }); + } + + module.exports = Holder; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /*! + * onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license + * + * Specially modified to work with Holder.js + */ + + function _onDomReady(win) { + //Lazy loading fix for Firefox < 3.6 + //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html + if (document.readyState == null && document.addEventListener) { + document.addEventListener("DOMContentLoaded", function DOMContentLoaded() { + document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); + document.readyState = "complete"; + }, false); + document.readyState = "loading"; + } + + var doc = win.document, + docElem = doc.documentElement, + + LOAD = "load", + FALSE = false, + ONLOAD = "on"+LOAD, + COMPLETE = "complete", + READYSTATE = "readyState", + ATTACHEVENT = "attachEvent", + DETACHEVENT = "detachEvent", + ADDEVENTLISTENER = "addEventListener", + DOMCONTENTLOADED = "DOMContentLoaded", + ONREADYSTATECHANGE = "onreadystatechange", + REMOVEEVENTLISTENER = "removeEventListener", + + // W3C Event model + w3c = ADDEVENTLISTENER in doc, + _top = FALSE, + + // isReady: Is the DOM ready to be used? Set to true once it occurs. + isReady = FALSE, + + // Callbacks pending execution until DOM is ready + callbacks = []; + + // Handle when the DOM is ready + function ready( fn ) { + if ( !isReady ) { + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !doc.body ) { + return defer( ready ); + } + + // Remember that the DOM is ready + isReady = true; + + // Execute all callbacks + while ( fn = callbacks.shift() ) { + defer( fn ); + } + } + } + + // The ready event handler + function completed( event ) { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) { + detach(); + ready(); + } + } + + // Clean-up method for dom ready events + function detach() { + if ( w3c ) { + doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE ); + } else { + doc[DETACHEVENT]( ONREADYSTATECHANGE, completed ); + win[DETACHEVENT]( ONLOAD, completed ); + } + } + + // Defers a function, scheduling it to run after the current call stack has cleared. + function defer( fn, wait ) { + // Allow 0 to be passed + setTimeout( fn, +wait >= 0 ? wait : 1 ); + } + + // Attach the listeners: + + // Catch cases where onDomReady is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( doc[READYSTATE] === COMPLETE ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + defer( ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( w3c ) { + // Use the handy event callback + doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + + // A fallback to window.onload, that will always work + win[ADDEVENTLISTENER]( LOAD, completed, FALSE ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed ); + + // A fallback to window.onload, that will always work + win[ATTACHEVENT]( ONLOAD, completed ); + + // If IE and not a frame + // continually check to see if the document is ready + try { + _top = win.frameElement == null && docElem; + } catch(e) {} + + if ( _top && _top.doScroll ) { + (function doScrollCheck() { + if ( !isReady ) { + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + _top.doScroll("left"); + } catch(e) { + return defer( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + ready(); + } + })(); + } + } + + function onDomReady( fn ) { + // If DOM is ready, execute the function (async), otherwise wait + isReady ? defer( fn ) : callbacks.push( fn ); + } + + // Add version + onDomReady.version = "1.4.0"; + // Add method to check if DOM is ready + onDomReady.isReady = function(){ + return isReady; + }; + + return onDomReady; + } + + module.exports = typeof window !== "undefined" && _onDomReady(window); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + //Modified version of component/querystring + //Changes: updated dependencies, dot notation parsing, JSHint fixes + //Fork at https://github.com/imsky/querystring + + /** + * Module dependencies. + */ + + var encode = encodeURIComponent; + var decode = decodeURIComponent; + var trim = __webpack_require__(4); + var type = __webpack_require__(5); + + var arrayRegex = /(\w+)\[(\d+)\]/; + var objectRegex = /\w+\.\w+/; + + /** + * Parse the given query `str`. + * + * @param {String} str + * @return {Object} + * @api public + */ + + exports.parse = function(str){ + if ('string' !== typeof str) return {}; + + str = trim(str); + if ('' === str) return {}; + if ('?' === str.charAt(0)) str = str.slice(1); + + var obj = {}; + var pairs = str.split('&'); + for (var i = 0; i < pairs.length; i++) { + var parts = pairs[i].split('='); + var key = decode(parts[0]); + var m, ctx, prop; + + if (m = arrayRegex.exec(key)) { + obj[m[1]] = obj[m[1]] || []; + obj[m[1]][m[2]] = decode(parts[1]); + continue; + } + + if (m = objectRegex.test(key)) { + m = key.split('.'); + ctx = obj; + + while (m.length) { + prop = m.shift(); + + if (!prop.length) continue; + + if (!ctx[prop]) { + ctx[prop] = {}; + } else if (ctx[prop] && typeof ctx[prop] !== 'object') { + break; + } + + if (!m.length) { + ctx[prop] = decode(parts[1]); + } + + ctx = ctx[prop]; + } + + continue; + } + + obj[parts[0]] = null == parts[1] ? '' : decode(parts[1]); + } + + return obj; + }; + + /** + * Stringify the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api public + */ + + exports.stringify = function(obj){ + if (!obj) return ''; + var pairs = []; + + for (var key in obj) { + var value = obj[key]; + + if ('array' == type(value)) { + for (var i = 0; i < value.length; ++i) { + pairs.push(encode(key + '[' + i + ']') + '=' + encode(value[i])); + } + continue; + } + + pairs.push(encode(key) + '=' + encode(obj[key])); + } + + return pairs.join('&'); + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + + exports = module.exports = trim; + + function trim(str){ + return str.replace(/^\s*|\s*$/g, ''); + } + + exports.left = function(str){ + return str.replace(/^\s*/, ''); + }; + + exports.right = function(str){ + return str.replace(/\s*$/, ''); + }; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + /** + * toString ref. + */ + + var toString = Object.prototype.toString; + + /** + * Return the type of `val`. + * + * @param {Mixed} val + * @return {String} + * @api public + */ + + module.exports = function(val){ + switch (toString.call(val)) { + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object Error]': return 'error'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val !== val) return 'nan'; + if (val && val.nodeType === 1) return 'element'; + + val = val.valueOf + ? val.valueOf() + : Object.prototype.valueOf.apply(val) + + return typeof val; + }; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + + var SceneGraph = function(sceneProperties) { + var nodeCount = 1; + + //todo: move merge to helpers section + function merge(parent, child) { + for (var prop in child) { + parent[prop] = child[prop]; + } + return parent; + } + + var SceneNode = function(name) { + nodeCount++; + this.parent = null; + this.children = {}; + this.id = nodeCount; + this.name = 'n' + nodeCount; + if (typeof name !== 'undefined') { + this.name = name; + } + this.x = this.y = this.z = 0; + this.width = this.height = 0; + }; + + SceneNode.prototype.resize = function(width, height) { + if (width != null) { + this.width = width; + } + if (height != null) { + this.height = height; + } + }; + + SceneNode.prototype.moveTo = function(x, y, z) { + this.x = x != null ? x : this.x; + this.y = y != null ? y : this.y; + this.z = z != null ? z : this.z; + }; + + SceneNode.prototype.add = function(child) { + var name = child.name; + if (typeof this.children[name] === 'undefined') { + this.children[name] = child; + child.parent = this; + } else { + throw 'SceneGraph: child already exists: ' + name; + } + }; + + var RootNode = function() { + SceneNode.call(this, 'root'); + this.properties = sceneProperties; + }; + + RootNode.prototype = new SceneNode(); + + var Shape = function(name, props) { + SceneNode.call(this, name); + this.properties = { + 'fill': '#000000' + }; + if (typeof props !== 'undefined') { + merge(this.properties, props); + } else if (typeof name !== 'undefined' && typeof name !== 'string') { + throw 'SceneGraph: invalid node name'; + } + }; + + Shape.prototype = new SceneNode(); + + var Group = function() { + Shape.apply(this, arguments); + this.type = 'group'; + }; + + Group.prototype = new Shape(); + + var Rect = function() { + Shape.apply(this, arguments); + this.type = 'rect'; + }; + + Rect.prototype = new Shape(); + + var Text = function(text) { + Shape.call(this); + this.type = 'text'; + this.properties.text = text; + }; + + Text.prototype = new Shape(); + + var root = new RootNode(); + + this.Shape = { + 'Rect': Rect, + 'Text': Text, + 'Group': Group + }; + + this.root = root; + return this; + }; + + module.exports = SceneGraph; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Shallow object clone and merge + * + * @param a Object A + * @param b Object B + * @returns {Object} New object with all of A's properties, and all of B's properties, overwriting A's properties + */ + exports.extend = function(a, b) { + var c = {}; + for (var x in a) { + if (a.hasOwnProperty(x)) { + c[x] = a[x]; + } + } + if (b != null) { + for (var y in b) { + if (b.hasOwnProperty(y)) { + c[y] = b[y]; + } + } + } + return c; + }; + + /** + * Takes a k/v list of CSS properties and returns a rule + * + * @param props CSS properties object + */ + exports.cssProps = function(props) { + var ret = []; + for (var p in props) { + if (props.hasOwnProperty(p)) { + ret.push(p + ':' + props[p]); + } + } + return ret.join(';'); + }; + + /** + * Encodes HTML entities in a string + * + * @param str Input string + */ + exports.encodeHtmlEntity = function(str) { + var buf = []; + var charCode = 0; + for (var i = str.length - 1; i >= 0; i--) { + charCode = str.charCodeAt(i); + if (charCode > 128) { + buf.unshift(['&#', charCode, ';'].join('')); + } else { + buf.unshift(str[i]); + } + } + return buf.join(''); + }; + + /** + * Checks if an image exists + * + * @param src URL of image + * @param callback Callback to call once image status has been found + */ + exports.imageExists = function(src, callback) { + var image = new Image(); + image.onerror = function() { + callback.call(this, false); + }; + image.onload = function() { + callback.call(this, true); + }; + image.src = src; + }; + + /** + * Decodes HTML entities in a string + * + * @param str Input string + */ + exports.decodeHtmlEntity = function(str) { + return str.replace(/&#(\d+);/g, function(match, dec) { + return String.fromCharCode(dec); + }); + }; + + + /** + * Returns an element's dimensions if it's visible, `false` otherwise. + * + * @param el DOM element + */ + exports.dimensionCheck = function(el) { + var dimensions = { + height: el.clientHeight, + width: el.clientWidth + }; + + if (dimensions.height && dimensions.width) { + return dimensions; + } else { + return false; + } + }; + + + /** + * Returns true if value is truthy or if it is "semantically truthy" + * @param val + */ + exports.truthy = function(val) { + if (typeof val === 'string') { + return val === 'true' || val === 'yes' || val === '1' || val === 'on' || val === '✓'; + } + return !!val; + }; + + /** + * Parses input into a well-formed CSS color + * @param val + */ + exports.parseColor = function(val) { + var hexre = /(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i; + var rgbre = /^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/; + var rgbare = /^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/; + + var match = val.match(hexre); + var retval; + + if (match !== null) { + retval = match[1] || match[2]; + if (retval[0] !== '#') { + return '#' + retval; + } else { + return retval; + } + } + + match = val.match(rgbre); + + if (match !== null) { + retval = 'rgb(' + match.slice(1).join(',') + ')'; + return retval; + } + + match = val.match(rgbare); + + if (match !== null) { + const normalizeAlpha = function (a) { return '0.' + a.split('.')[1]; }; + const fixedMatch = match.slice(1).map(function (e, i) { + return (i === 3) ? normalizeAlpha(e) : e; + }); + retval = 'rgba(' + fixedMatch.join(',') + ')'; + return retval; + } + + return null; + }; + + /** + * Provides the correct scaling ratio for canvas drawing operations on HiDPI screens (e.g. Retina displays) + */ + exports.canvasRatio = function () { + var devicePixelRatio = 1; + var backingStoreRatio = 1; + + if (global.document) { + var canvas = global.document.createElement('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + devicePixelRatio = global.devicePixelRatio || 1; + backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + } + } + + return devicePixelRatio / backingStoreRatio; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {var DOM = __webpack_require__(9); + + var SVG_NS = 'http://www.w3.org/2000/svg'; + var NODE_TYPE_COMMENT = 8; + + /** + * Generic SVG element creation function + * + * @param svg SVG context, set to null if new + * @param width Document width + * @param height Document height + */ + exports.initSVG = function(svg, width, height) { + var defs, style, initialize = false; + + if (svg && svg.querySelector) { + style = svg.querySelector('style'); + if (style === null) { + initialize = true; + } + } else { + svg = DOM.newEl('svg', SVG_NS); + initialize = true; + } + + if (initialize) { + defs = DOM.newEl('defs', SVG_NS); + style = DOM.newEl('style', SVG_NS); + DOM.setAttr(style, { + 'type': 'text/css' + }); + defs.appendChild(style); + svg.appendChild(defs); + } + + //IE throws an exception if this is set and Chrome requires it to be set + if (svg.webkitMatchesSelector) { + svg.setAttribute('xmlns', SVG_NS); + } + + //Remove comment nodes + for (var i = 0; i < svg.childNodes.length; i++) { + if (svg.childNodes[i].nodeType === NODE_TYPE_COMMENT) { + svg.removeChild(svg.childNodes[i]); + } + } + + //Remove CSS + while (style.childNodes.length) { + style.removeChild(style.childNodes[0]); + } + + DOM.setAttr(svg, { + 'width': width, + 'height': height, + 'viewBox': '0 0 ' + width + ' ' + height, + 'preserveAspectRatio': 'none' + }); + + return svg; + }; + + /** + * Converts serialized SVG to a string suitable for data URI use + * @param svgString Serialized SVG string + * @param [base64] Use base64 encoding for data URI + */ + exports.svgStringToDataURI = function() { + var rawPrefix = 'data:image/svg+xml;charset=UTF-8,'; + var base64Prefix = 'data:image/svg+xml;charset=UTF-8;base64,'; + + return function(svgString, base64) { + if (base64) { + return base64Prefix + btoa(global.unescape(encodeURIComponent(svgString))); + } else { + return rawPrefix + encodeURIComponent(svgString); + } + }; + }(); + + /** + * Returns serialized SVG with XML processing instructions + * + * @param svg SVG context + * @param stylesheets CSS stylesheets to include + */ + exports.serializeSVG = function(svg, engineSettings) { + if (!global.XMLSerializer) return; + var serializer = new XMLSerializer(); + var svgCSS = ''; + var stylesheets = engineSettings.stylesheets; + + //External stylesheets: Processing Instruction method + if (engineSettings.svgXMLStylesheet) { + var xml = DOM.createXML(); + //Add directives + for (var i = stylesheets.length - 1; i >= 0; i--) { + var csspi = xml.createProcessingInstruction('xml-stylesheet', 'href="' + stylesheets[i] + '" rel="stylesheet"'); + xml.insertBefore(csspi, xml.firstChild); + } + + xml.removeChild(xml.documentElement); + svgCSS = serializer.serializeToString(xml); + } + + var svgText = serializer.serializeToString(svg); + svgText = svgText.replace(/\&(\#[0-9]{2,}\;)/g, '&$1'); + return svgCSS + svgText; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Generic new DOM element function + * + * @param tag Tag to create + * @param namespace Optional namespace value + */ + exports.newEl = function(tag, namespace) { + if (!global.document) return; + + if (namespace == null) { + return global.document.createElement(tag); + } else { + return global.document.createElementNS(namespace, tag); + } + }; + + /** + * Generic setAttribute function + * + * @param el Reference to DOM element + * @param attrs Object with attribute keys and values + */ + exports.setAttr = function (el, attrs) { + for (var a in attrs) { + el.setAttribute(a, attrs[a]); + } + }; + + /** + * Creates a XML document + * @private + */ + exports.createXML = function() { + if (!global.DOMParser) return; + return new DOMParser().parseFromString('', 'application/xml'); + }; + + /** + * Converts a value into an array of DOM nodes + * + * @param val A string, a NodeList, a Node, or an HTMLCollection + */ + exports.getNodeArray = function(val) { + var retval = null; + if (typeof(val) == 'string') { + retval = document.querySelectorAll(val); + } else if (global.NodeList && val instanceof global.NodeList) { + retval = val; + } else if (global.Node && val instanceof global.Node) { + retval = [val]; + } else if (global.HTMLCollection && val instanceof global.HTMLCollection) { + retval = val; + } else if (val instanceof Array) { + retval = val; + } else if (val === null) { + retval = []; + } + + retval = Array.prototype.slice.call(retval); + + return retval; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + + var Color = function(color, options) { + //todo: support rgba, hsla, and rrggbbaa notation + //todo: use CIELAB internally + //todo: add clamp function (with sign) + if (typeof color !== 'string') return; + + this.original = color; + + if (color.charAt(0) === '#') { + color = color.slice(1); + } + + if (/[^a-f0-9]+/i.test(color)) return; + + if (color.length === 3) { + color = color.replace(/./g, '$&$&'); + } + + if (color.length !== 6) return; + + this.alpha = 1; + + if (options && options.alpha) { + this.alpha = options.alpha; + } + + this.set(parseInt(color, 16)); + }; + + //todo: jsdocs + Color.rgb2hex = function(r, g, b) { + function format (decimal) { + var hex = (decimal | 0).toString(16); + if (decimal < 16) { + hex = '0' + hex; + } + return hex; + } + + return [r, g, b].map(format).join(''); + }; + + //todo: jsdocs + Color.hsl2rgb = function (h, s, l) { + var H = h / 60; + var C = (1 - Math.abs(2 * l - 1)) * s; + var X = C * (1 - Math.abs(parseInt(H) % 2 - 1)); + var m = l - (C / 2); + + var r = 0, g = 0, b = 0; + + if (H >= 0 && H < 1) { + r = C; + g = X; + } else if (H >= 1 && H < 2) { + r = X; + g = C; + } else if (H >= 2 && H < 3) { + g = C; + b = X; + } else if (H >= 3 && H < 4) { + g = X; + b = C; + } else if (H >= 4 && H < 5) { + r = X; + b = C; + } else if (H >= 5 && H < 6) { + r = C; + b = X; + } + + r += m; + g += m; + b += m; + + r = parseInt(r * 255); + g = parseInt(g * 255); + b = parseInt(b * 255); + + return [r, g, b]; + }; + + /** + * Sets the color from a raw RGB888 integer + * @param raw RGB888 representation of color + */ + //todo: refactor into a static method + //todo: factor out individual color spaces + //todo: add HSL, CIELAB, and CIELUV + Color.prototype.set = function (val) { + this.raw = val; + + var r = (this.raw & 0xFF0000) >> 16; + var g = (this.raw & 0x00FF00) >> 8; + var b = (this.raw & 0x0000FF); + + // BT.709 + var y = 0.2126 * r + 0.7152 * g + 0.0722 * b; + var u = -0.09991 * r - 0.33609 * g + 0.436 * b; + var v = 0.615 * r - 0.55861 * g - 0.05639 * b; + + this.rgb = { + r: r, + g: g, + b: b + }; + + this.yuv = { + y: y, + u: u, + v: v + }; + + return this; + }; + + /** + * Lighten or darken a color + * @param multiplier Amount to lighten or darken (-1 to 1) + */ + Color.prototype.lighten = function(multiplier) { + var cm = Math.min(1, Math.max(0, Math.abs(multiplier))) * (multiplier < 0 ? -1 : 1); + var bm = (255 * cm) | 0; + var cr = Math.min(255, Math.max(0, this.rgb.r + bm)); + var cg = Math.min(255, Math.max(0, this.rgb.g + bm)); + var cb = Math.min(255, Math.max(0, this.rgb.b + bm)); + var hex = Color.rgb2hex(cr, cg, cb); + return new Color(hex); + }; + + /** + * Output color in hex format + * @param addHash Add a hash character to the beginning of the output + */ + Color.prototype.toHex = function(addHash) { + return (addHash ? '#' : '') + this.raw.toString(16); + }; + + /** + * Returns whether or not current color is lighter than another color + * @param color Color to compare against + */ + Color.prototype.lighterThan = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + return this.yuv.y > color.yuv.y; + }; + + /** + * Returns the result of mixing current color with another color + * @param color Color to mix with + * @param multiplier How much to mix with the other color + */ + /* + Color.prototype.mix = function (color, multiplier) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var r = this.rgb.r; + var g = this.rgb.g; + var b = this.rgb.b; + var a = this.alpha; + + var m = typeof multiplier !== 'undefined' ? multiplier : 0.5; + + //todo: write a lerp function + r = r + m * (color.rgb.r - r); + g = g + m * (color.rgb.g - g); + b = b + m * (color.rgb.b - b); + a = a + m * (color.alpha - a); + + return new Color(Color.rgbToHex(r, g, b), { + 'alpha': a + }); + }; + */ + + /** + * Returns the result of blending another color on top of current color with alpha + * @param color Color to blend on top of current color, i.e. "Ca" + */ + //todo: see if .blendAlpha can be merged into .mix + Color.prototype.blendAlpha = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var Ca = color; + var Cb = this; + + //todo: write alpha blending function + var r = Ca.alpha * Ca.rgb.r + (1 - Ca.alpha) * Cb.rgb.r; + var g = Ca.alpha * Ca.rgb.g + (1 - Ca.alpha) * Cb.rgb.g; + var b = Ca.alpha * Ca.rgb.b + (1 - Ca.alpha) * Cb.rgb.b; + + return new Color(Color.rgb2hex(r, g, b)); + }; + + module.exports = Color; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports) { + + module.exports = { + 'version': '2.9.7', + 'svg_ns': 'http://www.w3.org/2000/svg' + }; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + var shaven = __webpack_require__(13); + + var SVG = __webpack_require__(8); + var constants = __webpack_require__(11); + var utils = __webpack_require__(7); + + var SVG_NS = constants.svg_ns; + + var templates = { + 'element': function (options) { + var tag = options.tag; + var content = options.content || ''; + delete options.tag; + delete options.content; + return [tag, content, options]; + } + }; + + //todo: deprecate tag arg, infer tag from shape object + function convertShape (shape, tag) { + return templates.element({ + 'tag': tag, + 'width': shape.width, + 'height': shape.height, + 'fill': shape.properties.fill + }); + } + + function textCss (properties) { + return utils.cssProps({ + 'fill': properties.fill, + 'font-weight': properties.font.weight, + 'font-family': properties.font.family + ', monospace', + 'font-size': properties.font.size + properties.font.units + }); + } + + function outlinePath (bgWidth, bgHeight, outlineWidth) { + var outlineOffsetWidth = outlineWidth / 2; + + return [ + 'M', outlineOffsetWidth, outlineOffsetWidth, + 'H', bgWidth - outlineOffsetWidth, + 'V', bgHeight - outlineOffsetWidth, + 'H', outlineOffsetWidth, + 'V', 0, + 'M', 0, outlineOffsetWidth, + 'L', bgWidth, bgHeight - outlineOffsetWidth, + 'M', 0, bgHeight - outlineOffsetWidth, + 'L', bgWidth, outlineOffsetWidth + ].join(' '); + } + + module.exports = function (sceneGraph, renderSettings) { + var engineSettings = renderSettings.engineSettings; + var stylesheets = engineSettings.stylesheets; + var stylesheetXml = stylesheets.map(function (stylesheet) { + return ''; + }).join('\n'); + + var holderId = 'holder_' + Number(new Date()).toString(16); + + var root = sceneGraph.root; + var textGroup = root.children.holderTextGroup; + + var css = '#' + holderId + ' text { ' + textCss(textGroup.properties) + ' } '; + + // push text down to be equally vertically aligned with canvas renderer + textGroup.y += textGroup.textPositionData.boundingBox.height * 0.8; + + var wordTags = []; + + Object.keys(textGroup.children).forEach(function (lineKey) { + var line = textGroup.children[lineKey]; + + Object.keys(line.children).forEach(function (wordKey) { + var word = line.children[wordKey]; + var x = textGroup.x + line.x + word.x; + var y = textGroup.y + line.y + word.y; + var wordTag = templates.element({ + 'tag': 'text', + 'content': word.properties.text, + 'x': x, + 'y': y + }); + + wordTags.push(wordTag); + }); + }); + + var text = templates.element({ + 'tag': 'g', + 'content': wordTags + }); + + var outline = null; + + if (root.children.holderBg.properties.outline) { + var outlineProperties = root.children.holderBg.properties.outline; + outline = templates.element({ + 'tag': 'path', + 'd': outlinePath(root.children.holderBg.width, root.children.holderBg.height, outlineProperties.width), + 'stroke-width': outlineProperties.width, + 'stroke': outlineProperties.fill, + 'fill': 'none' + }); + } + + var bg = convertShape(root.children.holderBg, 'rect'); + + var sceneContent = []; + + sceneContent.push(bg); + if (outlineProperties) { + sceneContent.push(outline); + } + sceneContent.push(text); + + var scene = templates.element({ + 'tag': 'g', + 'id': holderId, + 'content': sceneContent + }); + + var style = templates.element({ + 'tag': 'style', + //todo: figure out how to add CDATA directive + 'content': css, + 'type': 'text/css' + }); + + var defs = templates.element({ + 'tag': 'defs', + 'content': style + }); + + var svg = templates.element({ + 'tag': 'svg', + 'content': [defs, scene], + 'width': root.properties.width, + 'height': root.properties.height, + 'xmlns': SVG_NS, + 'viewBox': [0, 0, root.properties.width, root.properties.height].join(' '), + 'preserveAspectRatio': 'none' + }); + + var output = shaven(svg); + + if (/\&(x)?#[0-9A-Fa-f]/.test(output[0])) { + output[0] = output[0].replace(/&#/gm, '&#'); + } + + output = stylesheetXml + output[0]; + + var svgString = SVG.svgStringToDataURI(output, renderSettings.mode === 'background'); + return svgString; + }; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + var escape = __webpack_require__(14) + + // TODO: remove namespace + + module.exports = function shaven (array, namespace, returnObject) { + + 'use strict' + + var i = 1 + var doesEscape = true + var HTMLString + var attributeKey + var callback + var key + + + returnObject = returnObject || {} + + + function createElement (sugarString) { + + var tags = sugarString.match(/^[\w-]+/) + var element = { + tag: tags ? tags[0] : 'div', + attr: {}, + children: [] + } + var id = sugarString.match(/#([\w-]+)/) + var reference = sugarString.match(/\$([\w-]+)/) + var classNames = sugarString.match(/\.[\w-]+/g) + + + // Assign id if is set + if (id) { + element.attr.id = id[1] + + // Add element to the return object + returnObject[id[1]] = element + } + + if (reference) + returnObject[reference[1]] = element + + if (classNames) + element.attr.class = classNames.join(' ').replace(/\./g, '') + + if (sugarString.match(/&$/g)) + doesEscape = false + + return element + } + + function replacer (key, value) { + + if (value === null || value === false || value === undefined) + return + + if (typeof value !== 'string' && typeof value !== 'object') + return String(value) + + return value + } + + function escapeAttribute (string) { + return (string || string === 0) ? + String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') : + '' + } + + function escapeHTML (string) { + return String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + } + + + if (typeof array[0] === 'string') + array[0] = createElement(array[0]) + + else if (Array.isArray(array[0])) + i = 0 + + else + throw new Error( + 'First element of array must be a string, ' + + 'or an array and not ' + JSON.stringify(array[0]) + ) + + + for (; i < array.length; i++) { + + // Don't render element if value is false or null + if (array[i] === false || array[i] === null) { + array[0] = false + break + } + + // Continue with next array value if current value is undefined or true + else if (array[i] === undefined || array[i] === true) { + continue + } + + else if (typeof array[i] === 'string') { + if (doesEscape) + array[i] = escapeHTML(array[i]) + + array[0].children.push(array[i]) + } + + else if (typeof array[i] === 'number') { + + array[0].children.push(array[i]) + } + + else if (Array.isArray(array[i])) { + + if (Array.isArray(array[i][0])) { + array[i].reverse().forEach(function (subArray) { + array.splice(i + 1, 0, subArray) + }) + + if (i !== 0) + continue + i++ + } + + shaven(array[i], namespace, returnObject) + + if (array[i][0]) + array[0].children.push(array[i][0]) + } + + else if (typeof array[i] === 'function') + callback = array[i] + + + else if (typeof array[i] === 'object') { + for (attributeKey in array[i]) + if (array[i].hasOwnProperty(attributeKey)) + if (array[i][attributeKey] !== null && + array[i][attributeKey] !== false) + if (attributeKey === 'style' && + typeof array[i][attributeKey] === 'object') + array[0].attr[attributeKey] = JSON + .stringify(array[i][attributeKey], replacer) + .slice(2, -2) + .replace(/","/g, ';') + .replace(/":"/g, ':') + .replace(/\\"/g, '\'') + + else + array[0].attr[attributeKey] = array[i][attributeKey] + } + + else + throw new TypeError('"' + array[i] + '" is not allowed as a value.') + } + + + if (array[0] !== false) { + + HTMLString = '<' + array[0].tag + + for (key in array[0].attr) + if (array[0].attr.hasOwnProperty(key)) + HTMLString += ' ' + key + '="' + + escapeAttribute(array[0].attr[key]) + '"' + + HTMLString += '>' + + array[0].children.forEach(function (child) { + HTMLString += child + }) + + HTMLString += '' + + array[0] = HTMLString + } + + // Return root element on index 0 + returnObject[0] = array[0] + + if (callback) + callback(array[0]) + + // returns object containing all elements with an id and the root element + return returnObject + } + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + + /*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + + 'use strict'; + + /** + * Module variables. + * @private + */ + + var matchHtmlRegExp = /["'&<>]/; + + /** + * Module exports. + * @public + */ + + module.exports = escapeHtml; + + /** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + + function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; + } + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + var DOM = __webpack_require__(9); + var utils = __webpack_require__(7); + + module.exports = (function() { + var canvas = DOM.newEl('canvas'); + var ctx = null; + + return function(sceneGraph) { + if (ctx == null) { + ctx = canvas.getContext('2d'); + } + + var dpr = utils.canvasRatio(); + var root = sceneGraph.root; + canvas.width = dpr * root.properties.width; + canvas.height = dpr * root.properties.height ; + ctx.textBaseline = 'middle'; + + var bg = root.children.holderBg; + var bgWidth = dpr * bg.width; + var bgHeight = dpr * bg.height; + //todo: parametrize outline width (e.g. in scene object) + var outlineWidth = 2; + var outlineOffsetWidth = outlineWidth / 2; + + ctx.fillStyle = bg.properties.fill; + ctx.fillRect(0, 0, bgWidth, bgHeight); + + if (bg.properties.outline) { + //todo: abstract this into a method + ctx.strokeStyle = bg.properties.outline.fill; + ctx.lineWidth = bg.properties.outline.width; + ctx.moveTo(outlineOffsetWidth, outlineOffsetWidth); + // TL, TR, BR, BL + ctx.lineTo(bgWidth - outlineOffsetWidth, outlineOffsetWidth); + ctx.lineTo(bgWidth - outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, outlineOffsetWidth); + // Diagonals + ctx.moveTo(0, outlineOffsetWidth); + ctx.lineTo(bgWidth, bgHeight - outlineOffsetWidth); + ctx.moveTo(0, bgHeight - outlineOffsetWidth); + ctx.lineTo(bgWidth, outlineOffsetWidth); + ctx.stroke(); + } + + var textGroup = root.children.holderTextGroup; + ctx.font = textGroup.properties.font.weight + ' ' + (dpr * textGroup.properties.font.size) + textGroup.properties.font.units + ' ' + textGroup.properties.font.family + ', monospace'; + ctx.fillStyle = textGroup.properties.fill; + + for (var lineKey in textGroup.children) { + var line = textGroup.children[lineKey]; + for (var wordKey in line.children) { + var word = line.children[wordKey]; + var x = dpr * (textGroup.x + line.x + word.x); + var y = dpr * (textGroup.y + line.y + word.y + (textGroup.properties.leading / 2)); + + ctx.fillText(word.properties.text, x, y); + } + } + + return canvas.toDataURL('image/png'); + }; + })(); + +/***/ }) +/******/ ]) +}); +; +(function(ctx, isMeteorPackage) { + if (isMeteorPackage) { + Holder = ctx.Holder; + } +})(this, typeof Meteor !== 'undefined' && typeof Package !== 'undefined'); diff --git a/静态站点/Bootstrap4/plugs/holder/holder.min.js b/静态站点/Bootstrap4/plugs/holder/holder.min.js new file mode 100644 index 0000000..6935bf1 --- /dev/null +++ b/静态站点/Bootstrap4/plugs/holder/holder.min.js @@ -0,0 +1,14 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +!function(e){if(e.document){var t=e.document;t.querySelectorAll||(t.querySelectorAll=function(n){var r,i=t.createElement("style"),a=[];for(t.documentElement.firstChild.appendChild(i),t._qsa=[],i.styleSheet.cssText=n+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",e.scrollBy(0,0),i.parentNode.removeChild(i);t._qsa.length;)r=t._qsa.shift(),r.style.removeAttribute("x-qsa"),a.push(r);return t._qsa=null,a}),t.querySelector||(t.querySelector=function(e){var n=t.querySelectorAll(e);return n.length?n[0]:null}),t.getElementsByClassName||(t.getElementsByClassName=function(e){return e=String(e).replace(/^|\s+/g,"."),t.querySelectorAll(e)}),Object.keys||(Object.keys=function(e){if(e!==Object(e))throw TypeError("Object.keys called on non-object");var t,n=[];for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.push(t);return n}),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError();var r,i=arguments[1];for(r=0;n>r;r++)r in t&&e.call(i,t[r],r,t)}),function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";e.atob=e.atob||function(e){e=String(e);var n,r=0,i=[],a=0,o=0;if(e=e.replace(/\s/g,""),e.length%4===0&&(e=e.replace(/=+$/,"")),e.length%4===1)throw Error("InvalidCharacterError");if(/[^+\/0-9A-Za-z]/.test(e))throw Error("InvalidCharacterError");for(;r>16&255)),i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a)),o=0,a=0),r+=1;return 12===o?(a>>=4,i.push(String.fromCharCode(255&a))):18===o&&(a>>=2,i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a))),i.join("")},e.btoa=e.btoa||function(e){e=String(e);var n,r,i,a,o,s,l,h=0,u=[];if(/[^\x00-\xFF]/.test(e))throw Error("InvalidCharacterError");for(;h>2,o=(3&n)<<4|r>>4,s=(15&r)<<2|i>>6,l=63&i,h===e.length+2?(s=64,l=64):h===e.length+1&&(l=64),u.push(t.charAt(a),t.charAt(o),t.charAt(s),t.charAt(l));return u.join("")}}(e),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(e){var t=this.__proto__||this.constructor.prototype;return e in this&&(!(e in t)||t[e]!==this[e])}),function(){if("performance"in e==!1&&(e.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in e.performance==!1){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),e.performance.now=function(){return Date.now()-t}}}(),e.requestAnimationFrame||(e.webkitRequestAnimationFrame&&e.webkitCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return webkitRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.webkitCancelAnimationFrame}(e):e.mozRequestAnimationFrame&&e.mozCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return mozRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.mozCancelAnimationFrame}(e):!function(e){e.requestAnimationFrame=function(t){return e.setTimeout(t,1e3/60)},e.cancelAnimationFrame=e.clearTimeout}(e))}}(this),function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Holder=t():e.Holder=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){(function(t){function r(e,t,n,r){var o=i(n.substr(n.lastIndexOf(e.domain)),e);o&&a({mode:null,el:r,flags:o,engineSettings:t})}function i(e,t){var n={theme:T(O.settings.themes.gray,null),stylesheets:t.stylesheets,instanceOptions:t},r=e.indexOf("?"),i=[e];-1!==r&&(i=[e.slice(0,r),e.slice(r+1)]);var a=i[0].split("/");n.holderURL=e;var o=a[1],s=o.match(/([\d]+p?)x([\d]+p?)/);if(!s)return!1;if(n.fluid=-1!==o.indexOf("p"),n.dimensions={width:s[1].replace("p","%"),height:s[2].replace("p","%")},2===i.length){var l=v.parse(i[1]);if(w.truthy(l.ratio)){n.fluid=!0;var h=parseFloat(n.dimensions.width.replace("%","")),u=parseFloat(n.dimensions.height.replace("%",""));u=Math.floor(100*(u/h)),h=100,n.dimensions.width=h+"%",n.dimensions.height=u+"%"}if(n.auto=w.truthy(l.auto),l.bg&&(n.theme.bg=w.parseColor(l.bg)),l.fg&&(n.theme.fg=w.parseColor(l.fg)),l.bg&&!l.fg&&(n.autoFg=!0),l.theme&&n.instanceOptions.themes.hasOwnProperty(l.theme)&&(n.theme=T(n.instanceOptions.themes[l.theme],null)),l.text&&(n.text=l.text),l.textmode&&(n.textmode=l.textmode),l.size&&parseFloat(l.size)&&(n.size=parseFloat(l.size)),l.font&&(n.font=l.font),l.align&&(n.align=l.align),l.lineWrap&&(n.lineWrap=l.lineWrap),n.nowrap=w.truthy(l.nowrap),n.outline=w.truthy(l.outline),w.truthy(l.random)){O.vars.cache.themeKeys=O.vars.cache.themeKeys||Object.keys(n.instanceOptions.themes);var d=O.vars.cache.themeKeys[0|Math.random()*O.vars.cache.themeKeys.length];n.theme=T(n.instanceOptions.themes[d],null)}}return n}function a(e){var t=e.mode,n=e.el,r=e.flags,i=e.engineSettings,a=r.dimensions,s=r.theme,l=a.width+"x"+a.height;t=null==t?r.fluid?"fluid":"image":t;var d=/holder_([a-z]+)/g,c=!1;if(null!=r.text&&(s.text=r.text,"object"===n.nodeName.toLowerCase())){for(var f=s.text.split("\\n"),p=0;p1){var b,x=0,A=0,C=0;w=new s.Group("line"+C),("left"===e.align||"right"===e.align)&&(a=e.width*(1-2*(1-r)));for(var E=0;E=a||k===!0)&&(t(g,w,x,g.properties.leading),g.add(w),x=0,A+=g.properties.leading,C+=1,w=new s.Group("line"+C),w.y=A),k!==!0&&(v.moveTo(x,0),x+=m.spaceWidth+T.width,w.add(v))}if(t(g,w,x,g.properties.leading),g.add(w),"left"===e.align)g.moveTo(e.width-i,null,null);else if("right"===e.align){for(b in g.children)w=g.children[b],w.moveTo(e.width-w.width,null,null);g.moveTo(0-(e.width-i),null,null)}else{for(b in g.children)w=g.children[b],w.moveTo((g.width-w.width)/2,null,null);g.moveTo((e.width-g.width)/2,null,null)}g.moveTo(null,(e.height-g.height)/2,null),(e.height-g.height)/2<0&&g.moveTo(null,0,null)}else v=new s.Text(e.text),w=new s.Group("line0"),w.add(v),g.add(w),"left"===e.align?g.moveTo(e.width-i,null,null):"right"===e.align?g.moveTo(0-(e.width-i),null,null):g.moveTo((e.width-m.boundingBox.width)/2,null,null),g.moveTo(null,(e.height-m.boundingBox.height)/2,null);return o}function l(e,t,n,r){var i=parseInt(e,10),a=parseInt(t,10),o=Math.max(i,a),s=Math.min(i,a),l=.8*Math.min(s,o*r);return Math.round(Math.max(n,l))}function h(e){var t;t=null==e||null==e.nodeType?O.vars.resizableImages:[e];for(var n=0,r=t.length;r>n;n++){var i=t[n];if(i.holderData){var a=i.holderData.flags,s=k(i);if(s){if(!i.holderData.resizeUpdate)continue;if(a.fluid&&a.auto){var l=i.holderData.fluidConfig;switch(l.mode){case"width":s.height=s.width/l.ratio;break;case"height":s.width=s.height*l.ratio}}var h={mode:"image",holderSettings:{dimensions:s,theme:a.theme,flags:a},el:i,engineSettings:i.holderData.engineSettings};"exact"==a.textmode&&(a.exactDimensions=s,h.holderSettings.dimensions=a.dimensions),o(h)}else f(i)}}}function u(e){if(e.holderData){var t=k(e);if(t){var n=e.holderData.flags,r={fluidHeight:"%"==n.dimensions.height.slice(-1),fluidWidth:"%"==n.dimensions.width.slice(-1),mode:null,initialDimensions:t};r.fluidWidth&&!r.fluidHeight?(r.mode="width",r.ratio=r.initialDimensions.width/parseFloat(n.dimensions.height)):!r.fluidWidth&&r.fluidHeight&&(r.mode="height",r.ratio=parseFloat(n.dimensions.width)/r.initialDimensions.height),e.holderData.fluidConfig=r}else f(e)}}function d(){var e,n=[],r=Object.keys(O.vars.invisibleImages);r.forEach(function(t){e=O.vars.invisibleImages[t],k(e)&&"img"==e.nodeName.toLowerCase()&&(n.push(e),delete O.vars.invisibleImages[t])}),n.length&&j.run({images:n}),setTimeout(function(){t.requestAnimationFrame(d)},10)}function c(){O.vars.visibilityCheckStarted||(t.requestAnimationFrame(d),O.vars.visibilityCheckStarted=!0)}function f(e){e.holderData.invisibleId||(O.vars.invisibleId+=1,O.vars.invisibleImages["i"+O.vars.invisibleId]=e,e.holderData.invisibleId=O.vars.invisibleId)}function p(e){O.vars.debounceTimer||e.call(this),O.vars.debounceTimer&&t.clearTimeout(O.vars.debounceTimer),O.vars.debounceTimer=t.setTimeout(function(){O.vars.debounceTimer=null,e.call(this)},O.setup.debounce)}function g(){p(function(){h(null)})}var m=n(2),v=n(3),y=n(6),w=n(7),b=n(8),x=n(9),S=n(10),A=n(11),C=n(12),E=n(15),T=w.extend,k=w.dimensionCheck,F=A.svg_ns,j={version:A.version,addTheme:function(e,t){return null!=e&&null!=t&&(O.settings.themes[e]=t),delete O.vars.cache.themeKeys,this},addImage:function(e,t){var n=x.getNodeArray(t);return n.forEach(function(t){var n=x.newEl("img"),r={};r[O.setup.dataAttr]=e,x.setAttr(n,r),t.appendChild(n)}),this},setResizeUpdate:function(e,t){e.holderData&&(e.holderData.resizeUpdate=!!t,e.holderData.resizeUpdate&&h(e))},run:function(e){e=e||{};var n={},o=T(O.settings,e);O.vars.preempted=!0,O.vars.dataAttr=o.dataAttr||O.setup.dataAttr,n.renderer=o.renderer?o.renderer:O.setup.renderer,-1===O.setup.renderers.join(",").indexOf(n.renderer)&&(n.renderer=O.setup.supportsSVG?"svg":O.setup.supportsCanvas?"canvas":"html");var s=x.getNodeArray(o.images),l=x.getNodeArray(o.bgnodes),h=x.getNodeArray(o.stylenodes),u=x.getNodeArray(o.objects);return n.stylesheets=[],n.svgXMLStylesheet=!0,n.noFontFallback=!!o.noFontFallback,n.noBackgroundSize=!!o.noBackgroundSize,h.forEach(function(e){if(e.attributes.rel&&e.attributes.href&&"stylesheet"==e.attributes.rel.value){var t=e.attributes.href.value,r=x.newEl("a");r.href=t;var i=r.protocol+"//"+r.host+r.pathname+r.search;n.stylesheets.push(i)}}),l.forEach(function(e){if(t.getComputedStyle){var r=t.getComputedStyle(e,null).getPropertyValue("background-image"),s=e.getAttribute("data-background-src"),l=s||r,h=null,u=o.domain+"/",d=l.indexOf(u);if(0===d)h=l;else if(1===d&&"?"===l[0])h=l.slice(1);else{var c=l.substr(d).match(/([^\"]*)"?\)/);if(null!==c)h=c[1];else if(0===l.indexOf("url("))throw"Holder: unable to parse background URL: "+l}if(h){var f=i(h,o);f&&a({mode:"background",el:e,flags:f,engineSettings:n})}}}),u.forEach(function(e){var t={};try{t.data=e.getAttribute("data"),t.dataSrc=e.getAttribute(O.vars.dataAttr)}catch(i){}var a=null!=t.data&&0===t.data.indexOf(o.domain),s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain);a?r(o,n,t.data,e):s&&r(o,n,t.dataSrc,e)}),s.forEach(function(e){var t={};try{t.src=e.getAttribute("src"),t.dataSrc=e.getAttribute(O.vars.dataAttr),t.rendered=e.getAttribute("data-holder-rendered")}catch(i){}var a=null!=t.src,s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain),l=null!=t.rendered&&"true"==t.rendered;a?0===t.src.indexOf(o.domain)?r(o,n,t.src,e):s&&(l?r(o,n,t.dataSrc,e):!function(e,t,n,i,a){w.imageExists(e,function(e){e||r(t,n,i,a)})}(t.src,o,n,t.dataSrc,e)):s&&r(o,n,t.dataSrc,e)}),this}},O={settings:{domain:"holder.js",images:"img",objects:"object",bgnodes:"body .holderjs",stylenodes:"head link.holderjs",themes:{gray:{bg:"#EEEEEE",fg:"#AAAAAA"},social:{bg:"#3a5a97",fg:"#FFFFFF"},industrial:{bg:"#434A52",fg:"#C2F200"},sky:{bg:"#0D8FDB",fg:"#FFFFFF"},vine:{bg:"#39DBAC",fg:"#1E292C"},lava:{bg:"#F8591A",fg:"#1C2846"}}},defaults:{size:10,units:"pt",scale:1/16}},z=function(){var e=null,t=null,n=null;return function(r){var i=r.root;if(O.setup.supportsSVG){var a=!1,o=function(e){return document.createTextNode(e)};(null==e||e.parentNode!==document.body)&&(a=!0),e=b.initSVG(e,i.properties.width,i.properties.height),e.style.display="block",a&&(t=x.newEl("text",F),n=o(null),x.setAttr(t,{x:0}),t.appendChild(n),e.appendChild(t),document.body.appendChild(e),e.style.visibility="hidden",e.style.position="absolute",e.style.top="-100%",e.style.left="-100%");var s=i.children.holderTextGroup,l=s.properties;x.setAttr(t,{y:l.font.size,style:w.cssProps({"font-weight":l.font.weight,"font-size":l.font.size+l.font.units,"font-family":l.font.family})});var h=x.newEl("textarea");h.innerHTML=l.text,n.nodeValue=h.value;var u=t.getBBox(),d=Math.ceil(u.width/i.properties.width),c=l.text.split(" "),f=l.text.match(/\\n/g);d+=null==f?0:f.length,n.nodeValue=l.text.replace(/[ ]+/g,"");var p=t.getComputedTextLength(),g=u.width-p,m=Math.round(g/Math.max(1,c.length-1)),v=[];if(d>1){n.nodeValue="";for(var y=0;y=0?t:1)}function a(e){x?i(e):S.push(e)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function C(){document.removeEventListener("DOMContentLoaded",C,!1),document.readyState="complete"},!1),document.readyState="loading");var o=e.document,s=o.documentElement,l="load",h=!1,u="on"+l,d="complete",c="readyState",f="attachEvent",p="detachEvent",g="addEventListener",m="DOMContentLoaded",v="onreadystatechange",y="removeEventListener",w=g in o,b=h,x=h,S=[];if(o[c]===d)i(t);else if(w)o[g](m,n,h),e[g](l,n,h);else{o[f](v,n),e[f](u,n);try{b=null==e.frameElement&&s}catch(A){}b&&b.doScroll&&!function E(){if(!x){try{b.doScroll("left")}catch(e){return i(E,50)}r(),t()}}()}return a.version="1.4.0",a.isReady=function(){return x},a}e.exports="undefined"!=typeof window&&n(window)},function(e,t,n){var r=encodeURIComponent,i=decodeURIComponent,a=n(4),o=n(5),s=/(\w+)\[(\d+)\]/,l=/\w+\.\w+/;t.parse=function(e){if("string"!=typeof e)return{};if(e=a(e),""===e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t={},n=e.split("&"),r=0;r=0;r--)n=e.charCodeAt(r),t.unshift(n>128?["&#",n,";"].join(""):e[r]);return t.join("")},t.imageExists=function(e,t){var n=new Image;n.onerror=function(){t.call(this,!1)},n.onload=function(){t.call(this,!0)},n.src=e},t.decodeHtmlEntity=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})},t.dimensionCheck=function(e){var t={height:e.clientHeight,width:e.clientWidth};return t.height&&t.width?t:!1},t.truthy=function(e){return"string"==typeof e?"true"===e||"yes"===e||"1"===e||"on"===e||"✓"===e:!!e},t.parseColor=function(e){var t,n=/(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i,r=/^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,i=/^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/,a=e.match(n);if(null!==a)return t=a[1]||a[2],"#"!==t[0]?"#"+t:t;if(a=e.match(r),null!==a)return t="rgb("+a.slice(1).join(",")+")";if(a=e.match(i),null!==a){const o=function(e){return"0."+e.split(".")[1]},s=a.slice(1).map(function(e,t){return 3===t?o(e):e});return t="rgba("+s.join(",")+")"}return null},t.canvasRatio=function(){var t=1,n=1;if(e.document){var r=e.document.createElement("canvas");if(r.getContext){var i=r.getContext("2d");t=e.devicePixelRatio||1,n=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1}}return t/n}}).call(t,function(){return this}())},function(e,t,n){(function(e){var r=n(9),i="http://www.w3.org/2000/svg",a=8;t.initSVG=function(e,t,n){var o,s,l=!1;e&&e.querySelector?(s=e.querySelector("style"),null===s&&(l=!0)):(e=r.newEl("svg",i),l=!0),l&&(o=r.newEl("defs",i),s=r.newEl("style",i),r.setAttr(s,{type:"text/css"}),o.appendChild(s),e.appendChild(o)),e.webkitMatchesSelector&&e.setAttribute("xmlns",i);for(var h=0;h=0;l--){var h=s.createProcessingInstruction("xml-stylesheet",'href="'+o[l]+'" rel="stylesheet"');s.insertBefore(h,s.firstChild)}s.removeChild(s.documentElement),a=i.serializeToString(s)}var u=i.serializeToString(t);return u=u.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),a+u}}}).call(t,function(){return this}())},function(e,t){(function(e){t.newEl=function(t,n){return e.document?null==n?e.document.createElement(t):e.document.createElementNS(n,t):void 0},t.setAttr=function(e,t){for(var n in t)e.setAttribute(n,t[n])},t.createXML=function(){return e.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0},t.getNodeArray=function(t){var n=null;return"string"==typeof t?n=document.querySelectorAll(t):e.NodeList&&t instanceof e.NodeList?n=t:e.Node&&t instanceof e.Node?n=[t]:e.HTMLCollection&&t instanceof e.HTMLCollection?n=t:t instanceof Array?n=t:null===t&&(n=[]),n=Array.prototype.slice.call(n)}}).call(t,function(){return this}())},function(e,t){var n=function(e,t){"string"==typeof e&&(this.original=e,"#"===e.charAt(0)&&(e=e.slice(1)),/[^a-f0-9]+/i.test(e)||(3===e.length&&(e=e.replace(/./g,"$&$&")),6===e.length&&(this.alpha=1,t&&t.alpha&&(this.alpha=t.alpha),this.set(parseInt(e,16)))))};n.rgb2hex=function(e,t,n){function r(e){var t=(0|e).toString(16);return 16>e&&(t="0"+t),t}return[e,t,n].map(r).join("")},n.hsl2rgb=function(e,t,n){var r=e/60,i=(1-Math.abs(2*n-1))*t,a=i*(1-Math.abs(parseInt(r)%2-1)),o=n-i/2,s=0,l=0,h=0;return r>=0&&1>r?(s=i,l=a):r>=1&&2>r?(s=a,l=i):r>=2&&3>r?(l=i,h=a):r>=3&&4>r?(l=a,h=i):r>=4&&5>r?(s=a,h=i):r>=5&&6>r&&(s=i,h=a),s+=o,l+=o,h+=o,s=parseInt(255*s),l=parseInt(255*l),h=parseInt(255*h),[s,l,h]},n.prototype.set=function(e){this.raw=e;var t=(16711680&this.raw)>>16,n=(65280&this.raw)>>8,r=255&this.raw,i=.2126*t+.7152*n+.0722*r,a=-.09991*t-.33609*n+.436*r,o=.615*t-.55861*n-.05639*r;return this.rgb={r:t,g:n,b:r},this.yuv={y:i,u:a,v:o},this},n.prototype.lighten=function(e){var t=Math.min(1,Math.max(0,Math.abs(e)))*(0>e?-1:1),r=255*t|0,i=Math.min(255,Math.max(0,this.rgb.r+r)),a=Math.min(255,Math.max(0,this.rgb.g+r)),o=Math.min(255,Math.max(0,this.rgb.b+r)),s=n.rgb2hex(i,a,o);return new n(s)},n.prototype.toHex=function(e){return(e?"#":"")+this.raw.toString(16)},n.prototype.lighterThan=function(e){return e instanceof n||(e=new n(e)),this.yuv.y>e.yuv.y},n.prototype.blendAlpha=function(e){e instanceof n||(e=new n(e));var t=e,r=this,i=t.alpha*t.rgb.r+(1-t.alpha)*r.rgb.r,a=t.alpha*t.rgb.g+(1-t.alpha)*r.rgb.g,o=t.alpha*t.rgb.b+(1-t.alpha)*r.rgb.b;return new n(n.rgb2hex(i,a,o))},e.exports=n},function(e,t){e.exports={version:"2.9.7",svg_ns:"http://www.w3.org/2000/svg"}},function(e,t,n){function r(e,t){return d.element({tag:t,width:e.width,height:e.height,fill:e.properties.fill})}function i(e){return h.cssProps({fill:e.fill,"font-weight":e.font.weight,"font-family":e.font.family+", monospace","font-size":e.font.size+e.font.units})}function a(e,t,n){var r=n/2;return["M",r,r,"H",e-r,"V",t-r,"H",r,"V",0,"M",0,r,"L",e,t-r,"M",0,t-r,"L",e,r].join(" ")}var o=n(13),s=n(8),l=n(11),h=n(7),u=l.svg_ns,d={element:function(e){var t=e.tag,n=e.content||"";return delete e.tag,delete e.content,[t,n,e]}};e.exports=function(e,t){var n=t.engineSettings,l=n.stylesheets,h=l.map(function(e){return''}).join("\n"),c="holder_"+Number(new Date).toString(16),f=e.root,p=f.children.holderTextGroup,g="#"+c+" text { "+i(p.properties)+" } ";p.y+=.8*p.textPositionData.boundingBox.height;var m=[];Object.keys(p.children).forEach(function(e){var t=p.children[e];Object.keys(t.children).forEach(function(e){var n=t.children[e],r=p.x+t.x+n.x,i=p.y+t.y+n.y,a=d.element({tag:"text",content:n.properties.text,x:r,y:i});m.push(a)})});var v=d.element({tag:"g",content:m}),y=null;if(f.children.holderBg.properties.outline){var w=f.children.holderBg.properties.outline;y=d.element({tag:"path",d:a(f.children.holderBg.width,f.children.holderBg.height,w.width),"stroke-width":w.width,stroke:w.fill,fill:"none"})}var b=r(f.children.holderBg,"rect"),x=[];x.push(b),w&&x.push(y),x.push(v);var S=d.element({tag:"g",id:c,content:x}),A=d.element({tag:"style",content:g,type:"text/css"}),C=d.element({tag:"defs",content:A}),E=d.element({tag:"svg",content:[C,S],width:f.properties.width,height:f.properties.height,xmlns:u,viewBox:[0,0,f.properties.width,f.properties.height].join(" "),preserveAspectRatio:"none"}),T=o(E);/\&(x)?#[0-9A-Fa-f]/.test(T[0])&&(T[0]=T[0].replace(/&#/gm,"&#")),T=h+T[0];var k=s.svgStringToDataURI(T,"background"===t.mode);return k}},function(e,t,n){n(14);e.exports=function r(e,t,n){"use strict";function i(e){var t=e.match(/^[\w-]+/),r={tag:t?t[0]:"div",attr:{},children:[]},i=e.match(/#([\w-]+)/),a=e.match(/\$([\w-]+)/),o=e.match(/\.[\w-]+/g);return i&&(r.attr.id=i[1],n[i[1]]=r),a&&(n[a[1]]=r),o&&(r.attr["class"]=o.join(" ").replace(/\./g,"")),e.match(/&$/g)&&(f=!1),r}function a(e,t){return null!==t&&t!==!1&&void 0!==t?"string"!=typeof t&&"object"!=typeof t?String(t):t:void 0}function o(e){return e||0===e?String(e).replace(/&/g,"&").replace(/"/g,"""):""}function s(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}var l,h,u,d,c=1,f=!0;if(n=n||{},"string"==typeof e[0])e[0]=i(e[0]);else{if(!Array.isArray(e[0]))throw new Error("First element of array must be a string, or an array and not "+JSON.stringify(e[0]));c=0}for(;c",e[0]=l}return n[0]=e[0],u&&u(e[0]),n}},function(e,t){"use strict";function n(e){var t=""+e,n=r.exec(t);if(!n)return t;var i,a="",o=0,s=0;for(o=n.index;o]/;e.exports=n},function(e,t,n){var r=n(9),i=n(7);e.exports=function(){var e=r.newEl("canvas"),t=null;return function(n){null==t&&(t=e.getContext("2d"));var r=i.canvasRatio(),a=n.root;e.width=r*a.properties.width,e.height=r*a.properties.height,t.textBaseline="middle";var o=a.children.holderBg,s=r*o.width,l=r*o.height,h=2,u=h/2;t.fillStyle=o.properties.fill,t.fillRect(0,0,s,l),o.properties.outline&&(t.strokeStyle=o.properties.outline.fill,t.lineWidth=o.properties.outline.width,t.moveTo(u,u),t.lineTo(s-u,u),t.lineTo(s-u,l-u),t.lineTo(u,l-u),t.lineTo(u,u),t.moveTo(0,u),t.lineTo(s,l-u),t.moveTo(0,l-u),t.lineTo(s,u),t.stroke());var d=a.children.holderTextGroup;t.font=d.properties.font.weight+" "+r*d.properties.font.size+d.properties.font.units+" "+d.properties.font.family+", monospace",t.fillStyle=d.properties.fill;for(var c in d.children){var f=d.children[c];for(var p in f.children){var g=f.children[p],m=r*(d.x+f.x+g.x),v=r*(d.y+f.y+g.y+d.properties.leading/2); + +t.fillText(g.properties.text,m,v)}}return e.toDataURL("image/png")}}()}])}),function(e,t){t&&(Holder=e.Holder)}(this,"undefined"!=typeof Meteor&&"undefined"!=typeof Package); \ No newline at end of file diff --git a/静态站点/Bootstrap5/pages/test.css b/静态站点/Bootstrap5/pages/test.css new file mode 100644 index 0000000..e69de29 diff --git a/静态站点/Bootstrap5/pages/test.html b/静态站点/Bootstrap5/pages/test.html new file mode 100644 index 0000000..3d99e8d --- /dev/null +++ b/静态站点/Bootstrap5/pages/test.html @@ -0,0 +1,25 @@ + + + + + + + BootstrapStudy + + + + + + + + +
+ ... +
+ + + + + + + diff --git a/静态站点/Bootstrap5/pages/test.js b/静态站点/Bootstrap5/pages/test.js new file mode 100644 index 0000000..f525482 --- /dev/null +++ b/静态站点/Bootstrap5/pages/test.js @@ -0,0 +1 @@ +console.log("来自 test.js 的日志"); \ No newline at end of file diff --git a/静态站点/Bootstrap5/plugs/holder/holder.js b/静态站点/Bootstrap5/plugs/holder/holder.js new file mode 100644 index 0000000..db1e43b --- /dev/null +++ b/静态站点/Bootstrap5/plugs/holder/holder.js @@ -0,0 +1,3063 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +(function (window) { + if (!window.document) return; + var document = window.document; + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + if (!document.querySelectorAll) { + document.querySelectorAll = function (selectors) { + var style = document.createElement('style'), elements = [], element; + document.documentElement.firstChild.appendChild(style); + document._qsa = []; + + style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}'; + window.scrollBy(0, 0); + style.parentNode.removeChild(style); + + while (document._qsa.length) { + element = document._qsa.shift(); + element.style.removeAttribute('x-qsa'); + elements.push(element); + } + document._qsa = null; + return elements; + }; + } + + if (!document.querySelector) { + document.querySelector = function (selectors) { + var elements = document.querySelectorAll(selectors); + return (elements.length) ? elements[0] : null; + }; + } + + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (classNames) { + classNames = String(classNames).replace(/^|\s+/g, '.'); + return document.querySelectorAll(classNames); + }; + } + + //https://github.com/inexorabletash/polyfill + // ES5 15.2.3.14 Object.keys ( O ) + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys + if (!Object.keys) { + Object.keys = function (o) { + if (o !== Object(o)) { throw TypeError('Object.keys called on non-object'); } + var ret = [], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + ret.push(p); + } + } + return ret; + }; + } + + // ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] ) + // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun /*, thisp */) { + if (this === void 0 || this === null) { throw TypeError(); } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { throw TypeError(); } + + var thisp = arguments[1], i; + for (i = 0; i < len; i++) { + if (i in t) { + fun.call(thisp, t[i], i, t); + } + } + }; + } + + //https://github.com/inexorabletash/polyfill/blob/master/web.js + (function (global) { + var B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + global.atob = global.atob || function (input) { + input = String(input); + var position = 0, + output = [], + buffer = 0, bits = 0, n; + + input = input.replace(/\s/g, ''); + if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); } + if ((input.length % 4) === 1) { throw Error('InvalidCharacterError'); } + if (/[^+/0-9A-Za-z]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + n = B64_ALPHABET.indexOf(input.charAt(position)); + buffer = (buffer << 6) | n; + bits += 6; + + if (bits === 24) { + output.push(String.fromCharCode((buffer >> 16) & 0xFF)); + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + bits = 0; + buffer = 0; + } + position += 1; + } + + if (bits === 12) { + buffer = buffer >> 4; + output.push(String.fromCharCode(buffer & 0xFF)); + } else if (bits === 18) { + buffer = buffer >> 2; + output.push(String.fromCharCode((buffer >> 8) & 0xFF)); + output.push(String.fromCharCode(buffer & 0xFF)); + } + + return output.join(''); + }; + + global.btoa = global.btoa || function (input) { + input = String(input); + var position = 0, + out = [], + o1, o2, o3, + e1, e2, e3, e4; + + if (/[^\x00-\xFF]/.test(input)) { throw Error('InvalidCharacterError'); } + + while (position < input.length) { + o1 = input.charCodeAt(position++); + o2 = input.charCodeAt(position++); + o3 = input.charCodeAt(position++); + + // 111111 112222 222233 333333 + e1 = o1 >> 2; + e2 = ((o1 & 0x3) << 4) | (o2 >> 4); + e3 = ((o2 & 0xf) << 2) | (o3 >> 6); + e4 = o3 & 0x3f; + + if (position === input.length + 2) { + e3 = 64; e4 = 64; + } + else if (position === input.length + 1) { + e4 = 64; + } + + out.push(B64_ALPHABET.charAt(e1), + B64_ALPHABET.charAt(e2), + B64_ALPHABET.charAt(e3), + B64_ALPHABET.charAt(e4)); + } + + return out.join(''); + }; + }(window)); + + //https://gist.github.com/jimeh/332357 + if (!Object.prototype.hasOwnProperty){ + /*jshint -W001, -W103 */ + Object.prototype.hasOwnProperty = function(prop) { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + }; + /*jshint +W001, +W103 */ + } + + // @license http://opensource.org/licenses/MIT + // copyright Paul Irish 2015 + + + // Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill + // github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js + // as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values + + // if you want values similar to what you'd get with real perf.now, place this towards the head of the page + // but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed + + + (function(){ + + if ('performance' in window === false) { + window.performance = {}; + } + + Date.now = (Date.now || function () { // thanks IE8 + return new Date().getTime(); + }); + + if ('now' in window.performance === false){ + + var nowOffset = Date.now(); + + if (performance.timing && performance.timing.navigationStart){ + nowOffset = performance.timing.navigationStart; + } + + window.performance.now = function now(){ + return Date.now() - nowOffset; + }; + } + + })(); + + //requestAnimationFrame polyfill for older Firefox/Chrome versions + if (!window.requestAnimationFrame) { + if (window.webkitRequestAnimationFrame && window.webkitCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-webkit.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return webkitRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.webkitCancelAnimationFrame; + }(window)); + } else if (window.mozRequestAnimationFrame && window.mozCancelAnimationFrame) { + //https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/requestAnimationFrame/polyfill-moz.js + (function (global) { + global.requestAnimationFrame = function (callback) { + return mozRequestAnimationFrame(function () { + callback(global.performance.now()); + }); + }; + + global.cancelAnimationFrame = global.mozCancelAnimationFrame; + }(window)); + } else { + (function (global) { + global.requestAnimationFrame = function (callback) { + return global.setTimeout(callback, 1000 / 60); + }; + + global.cancelAnimationFrame = global.clearTimeout; + })(window); + } + } +})(this); + +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Holder"] = factory(); + else + root["Holder"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + /* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - https://imsky.co + */ + + module.exports = __webpack_require__(1); + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* + Holder.js - client side image placeholders + (c) 2012-2020 Ivan Malopinsky - http://imsky.co + */ + + //Libraries and functions + var onDomReady = __webpack_require__(2); + var querystring = __webpack_require__(3); + + var SceneGraph = __webpack_require__(6); + var utils = __webpack_require__(7); + var SVG = __webpack_require__(8); + var DOM = __webpack_require__(9); + var Color = __webpack_require__(10); + var constants = __webpack_require__(11); + + var svgRenderer = __webpack_require__(12); + var sgCanvasRenderer = __webpack_require__(15); + + var extend = utils.extend; + var dimensionCheck = utils.dimensionCheck; + + //Constants and definitions + var SVG_NS = constants.svg_ns; + + var Holder = { + version: constants.version, + + /** + * Adds a theme to default settings + * + * @param {string} name Theme name + * @param {Object} theme Theme object, with foreground, background, size, font, and fontweight properties. + */ + addTheme: function(name, theme) { + name != null && theme != null && (App.settings.themes[name] = theme); + delete App.vars.cache.themeKeys; + return this; + }, + + /** + * Appends a placeholder to an element + * + * @param {string} src Placeholder URL string + * @param el A selector or a reference to a DOM node + */ + addImage: function(src, el) { + //todo: use jquery fallback if available for all QSA references + var nodes = DOM.getNodeArray(el); + nodes.forEach(function (node) { + var img = DOM.newEl('img'); + var domProps = {}; + domProps[App.setup.dataAttr] = src; + DOM.setAttr(img, domProps); + node.appendChild(img); + }); + return this; + }, + + /** + * Sets whether or not an image is updated on resize. + * If an image is set to be updated, it is immediately rendered. + * + * @param {Object} el Image DOM element + * @param {Boolean} value Resizable update flag value + */ + setResizeUpdate: function(el, value) { + if (el.holderData) { + el.holderData.resizeUpdate = !!value; + if (el.holderData.resizeUpdate) { + updateResizableElements(el); + } + } + }, + + /** + * Runs Holder with options. By default runs Holder on all images with "holder.js" in their source attributes. + * + * @param {Object} userOptions Options object, can contain domain, themes, images, and bgnodes properties + */ + run: function(userOptions) { + //todo: split processing into separate queues + userOptions = userOptions || {}; + var engineSettings = {}; + var options = extend(App.settings, userOptions); + + App.vars.preempted = true; + App.vars.dataAttr = options.dataAttr || App.setup.dataAttr; + + engineSettings.renderer = options.renderer ? options.renderer : App.setup.renderer; + if (App.setup.renderers.join(',').indexOf(engineSettings.renderer) === -1) { + engineSettings.renderer = App.setup.supportsSVG ? 'svg' : (App.setup.supportsCanvas ? 'canvas' : 'html'); + } + + var images = DOM.getNodeArray(options.images); + var bgnodes = DOM.getNodeArray(options.bgnodes); + var stylenodes = DOM.getNodeArray(options.stylenodes); + var objects = DOM.getNodeArray(options.objects); + + engineSettings.stylesheets = []; + engineSettings.svgXMLStylesheet = true; + engineSettings.noFontFallback = !!options.noFontFallback; + engineSettings.noBackgroundSize = !!options.noBackgroundSize; + + stylenodes.forEach(function (styleNode) { + if (styleNode.attributes.rel && styleNode.attributes.href && styleNode.attributes.rel.value == 'stylesheet') { + var href = styleNode.attributes.href.value; + //todo: write isomorphic relative-to-absolute URL function + var proxyLink = DOM.newEl('a'); + proxyLink.href = href; + var stylesheetURL = proxyLink.protocol + '//' + proxyLink.host + proxyLink.pathname + proxyLink.search; + engineSettings.stylesheets.push(stylesheetURL); + } + }); + + bgnodes.forEach(function (bgNode) { + //Skip processing background nodes if getComputedStyle is unavailable, since only modern browsers would be able to use canvas or SVG to render to background + if (!global.getComputedStyle) return; + var backgroundImage = global.getComputedStyle(bgNode, null).getPropertyValue('background-image'); + var dataBackgroundImage = bgNode.getAttribute('data-background-src'); + var rawURL = dataBackgroundImage || backgroundImage; + + var holderURL = null; + var holderString = options.domain + '/'; + var holderStringIndex = rawURL.indexOf(holderString); + + if (holderStringIndex === 0) { + holderURL = rawURL; + } else if (holderStringIndex === 1 && rawURL[0] === '?') { + holderURL = rawURL.slice(1); + } else { + var fragment = rawURL.substr(holderStringIndex).match(/([^\"]*)"?\)/); + if (fragment !== null) { + holderURL = fragment[1]; + } else if (rawURL.indexOf('url(') === 0) { + throw 'Holder: unable to parse background URL: ' + rawURL; + } + } + + if (holderURL) { + var holderFlags = parseURL(holderURL, options); + if (holderFlags) { + prepareDOMElement({ + mode: 'background', + el: bgNode, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + }); + + objects.forEach(function (object) { + var objectAttr = {}; + + try { + objectAttr.data = object.getAttribute('data'); + objectAttr.dataSrc = object.getAttribute(App.vars.dataAttr); + } catch (e) {} + + var objectHasSrcURL = objectAttr.data != null && objectAttr.data.indexOf(options.domain) === 0; + var objectHasDataSrcURL = objectAttr.dataSrc != null && objectAttr.dataSrc.indexOf(options.domain) === 0; + + if (objectHasSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.data, object); + } else if (objectHasDataSrcURL) { + prepareImageElement(options, engineSettings, objectAttr.dataSrc, object); + } + }); + + images.forEach(function (image) { + var imageAttr = {}; + + try { + imageAttr.src = image.getAttribute('src'); + imageAttr.dataSrc = image.getAttribute(App.vars.dataAttr); + imageAttr.rendered = image.getAttribute('data-holder-rendered'); + } catch (e) {} + + var imageHasSrc = imageAttr.src != null; + var imageHasDataSrcURL = imageAttr.dataSrc != null && imageAttr.dataSrc.indexOf(options.domain) === 0; + var imageRendered = imageAttr.rendered != null && imageAttr.rendered == 'true'; + + if (imageHasSrc) { + if (imageAttr.src.indexOf(options.domain) === 0) { + prepareImageElement(options, engineSettings, imageAttr.src, image); + } else if (imageHasDataSrcURL) { + //Image has a valid data-src and an invalid src + if (imageRendered) { + //If the placeholder has already been render, re-render it + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } else { + //If the placeholder has not been rendered, check if the image exists and render a fallback if it doesn't + (function(src, options, engineSettings, dataSrc, image) { + utils.imageExists(src, function(exists) { + if (!exists) { + prepareImageElement(options, engineSettings, dataSrc, image); + } + }); + })(imageAttr.src, options, engineSettings, imageAttr.dataSrc, image); + } + } + } else if (imageHasDataSrcURL) { + prepareImageElement(options, engineSettings, imageAttr.dataSrc, image); + } + }); + + return this; + } + }; + + var App = { + settings: { + domain: 'holder.js', + images: 'img', + objects: 'object', + bgnodes: 'body .holderjs', + stylenodes: 'head link.holderjs', + themes: { + 'gray': { + bg: '#EEEEEE', + fg: '#AAAAAA' + }, + 'social': { + bg: '#3a5a97', + fg: '#FFFFFF' + }, + 'industrial': { + bg: '#434A52', + fg: '#C2F200' + }, + 'sky': { + bg: '#0D8FDB', + fg: '#FFFFFF' + }, + 'vine': { + bg: '#39DBAC', + fg: '#1E292C' + }, + 'lava': { + bg: '#F8591A', + fg: '#1C2846' + } + } + }, + defaults: { + size: 10, + units: 'pt', + scale: 1 / 16 + } + }; + + /** + * Processes provided source attribute and sets up the appropriate rendering workflow + * + * @private + * @param options Instance options from Holder.run + * @param renderSettings Instance configuration + * @param src Image URL + * @param el Image DOM element + */ + function prepareImageElement(options, engineSettings, src, el) { + var holderFlags = parseURL(src.substr(src.lastIndexOf(options.domain)), options); + if (holderFlags) { + prepareDOMElement({ + mode: null, + el: el, + flags: holderFlags, + engineSettings: engineSettings + }); + } + } + + /** + * Processes a Holder URL and extracts configuration from query string + * + * @private + * @param url URL + * @param instanceOptions Instance options from Holder.run + */ + function parseURL(url, instanceOptions) { + var holder = { + theme: extend(App.settings.themes.gray, null), + stylesheets: instanceOptions.stylesheets, + instanceOptions: instanceOptions + }; + + var firstQuestionMark = url.indexOf('?'); + var parts = [url]; + + if (firstQuestionMark !== -1) { + parts = [url.slice(0, firstQuestionMark), url.slice(firstQuestionMark + 1)]; + } + + var basics = parts[0].split('/'); + + holder.holderURL = url; + + var dimensions = basics[1]; + var dimensionData = dimensions.match(/([\d]+p?)x([\d]+p?)/); + + if (!dimensionData) return false; + + holder.fluid = dimensions.indexOf('p') !== -1; + + holder.dimensions = { + width: dimensionData[1].replace('p', '%'), + height: dimensionData[2].replace('p', '%') + }; + + if (parts.length === 2) { + var options = querystring.parse(parts[1]); + + // Dimensions + + if (utils.truthy(options.ratio)) { + holder.fluid = true; + var ratioWidth = parseFloat(holder.dimensions.width.replace('%', '')); + var ratioHeight = parseFloat(holder.dimensions.height.replace('%', '')); + + ratioHeight = Math.floor(100 * (ratioHeight / ratioWidth)); + ratioWidth = 100; + + holder.dimensions.width = ratioWidth + '%'; + holder.dimensions.height = ratioHeight + '%'; + } + + holder.auto = utils.truthy(options.auto); + + // Colors + + if (options.bg) { + holder.theme.bg = utils.parseColor(options.bg); + } + + if (options.fg) { + holder.theme.fg = utils.parseColor(options.fg); + } + + //todo: add automatic foreground to themes without foreground + if (options.bg && !options.fg) { + holder.autoFg = true; + } + + if (options.theme && holder.instanceOptions.themes.hasOwnProperty(options.theme)) { + holder.theme = extend(holder.instanceOptions.themes[options.theme], null); + } + + // Text + + if (options.text) { + holder.text = options.text; + } + + if (options.textmode) { + holder.textmode = options.textmode; + } + + if (options.size && parseFloat(options.size)) { + holder.size = parseFloat(options.size); + } + + if (options.font) { + holder.font = options.font; + } + + if (options.align) { + holder.align = options.align; + } + + if (options.lineWrap) { + holder.lineWrap = options.lineWrap; + } + + holder.nowrap = utils.truthy(options.nowrap); + + // Miscellaneous + + holder.outline = utils.truthy(options.outline); + + if (utils.truthy(options.random)) { + App.vars.cache.themeKeys = App.vars.cache.themeKeys || Object.keys(holder.instanceOptions.themes); + var _theme = App.vars.cache.themeKeys[0 | Math.random() * App.vars.cache.themeKeys.length]; + holder.theme = extend(holder.instanceOptions.themes[_theme], null); + } + } + + return holder; + } + + /** + * Modifies the DOM to fit placeholders and sets up resizable image callbacks (for fluid and automatically sized placeholders) + * + * @private + * @param settings DOM prep settings + */ + function prepareDOMElement(prepSettings) { + var mode = prepSettings.mode; + var el = prepSettings.el; + var flags = prepSettings.flags; + var _engineSettings = prepSettings.engineSettings; + var dimensions = flags.dimensions, + theme = flags.theme; + var dimensionsCaption = dimensions.width + 'x' + dimensions.height; + mode = mode == null ? (flags.fluid ? 'fluid' : 'image') : mode; + var holderTemplateRe = /holder_([a-z]+)/g; + var dimensionsInText = false; + + if (flags.text != null) { + theme.text = flags.text; + + // SVG embedding doesn't parse Unicode properly + if (el.nodeName.toLowerCase() === 'object') { + var textLines = theme.text.split('\\n'); + for (var k = 0; k < textLines.length; k++) { + textLines[k] = utils.encodeHtmlEntity(textLines[k]); + } + theme.text = textLines.join('\\n'); + } + } + + if (theme.text) { + var holderTemplateMatches = theme.text.match(holderTemplateRe); + + if (holderTemplateMatches !== null) { + //todo: optimize template replacement + holderTemplateMatches.forEach(function (match) { + if (match === 'holder_dimensions') { + theme.text = theme.text.replace(match, dimensionsCaption); + } + }); + } + } + + var holderURL = flags.holderURL; + var engineSettings = extend(_engineSettings, null); + + if (flags.font) { + /* + If external fonts are used in a placeholder rendered with SVG, Holder falls back to canvas. + + This is done because Firefox and Chrome disallow embedded SVGs from referencing external assets. + The workaround is either to change the placeholder tag from to or to use the canvas renderer. + */ + theme.font = flags.font; + if (!engineSettings.noFontFallback && el.nodeName.toLowerCase() === 'img' && App.setup.supportsCanvas && engineSettings.renderer === 'svg') { + engineSettings = extend(engineSettings, { + renderer: 'canvas' + }); + } + } + + //Chrome and Opera require a quick 10ms re-render if web fonts are used with canvas + if (flags.font && engineSettings.renderer == 'canvas') { + engineSettings.reRender = true; + } + + if (mode == 'background') { + if (el.getAttribute('data-background-src') == null) { + DOM.setAttr(el, { + 'data-background-src': holderURL + }); + } + } else { + var domProps = {}; + domProps[App.vars.dataAttr] = holderURL; + DOM.setAttr(el, domProps); + } + + flags.theme = theme; + + //todo consider using all renderSettings in holderData + el.holderData = { + flags: flags, + engineSettings: engineSettings + }; + + if (mode == 'image' || mode == 'fluid') { + DOM.setAttr(el, { + 'alt': theme.text ? (dimensionsInText ? theme.text : theme.text + ' [' + dimensionsCaption + ']') : dimensionsCaption + }); + } + + var renderSettings = { + mode: mode, + el: el, + holderSettings: { + dimensions: dimensions, + theme: theme, + flags: flags + }, + engineSettings: engineSettings + }; + + if (mode == 'image') { + if (!flags.auto) { + el.style.width = dimensions.width + 'px'; + el.style.height = dimensions.height + 'px'; + } + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + render(renderSettings); + + if (flags.textmode == 'exact') { + el.holderData.resizeUpdate = true; + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } else if (mode == 'background' && engineSettings.renderer != 'html') { + render(renderSettings); + } else if (mode == 'fluid') { + el.holderData.resizeUpdate = true; + + if (dimensions.height.slice(-1) == '%') { + el.style.height = dimensions.height; + } else if (flags.auto == null || !flags.auto) { + el.style.height = dimensions.height + 'px'; + } + if (dimensions.width.slice(-1) == '%') { + el.style.width = dimensions.width; + } else if (flags.auto == null || !flags.auto) { + el.style.width = dimensions.width + 'px'; + } + if (el.style.display == 'inline' || el.style.display === '' || el.style.display == 'none') { + el.style.display = 'block'; + } + + setInitialDimensions(el); + + if (engineSettings.renderer == 'html') { + el.style.backgroundColor = theme.bg; + } else { + App.vars.resizableImages.push(el); + updateResizableElements(el); + } + } + } + + /** + * Core function that takes output from renderers and sets it as the source or background-image of the target element + * + * @private + * @param renderSettings Renderer settings + */ + function render(renderSettings) { + var image = null; + var mode = renderSettings.mode; + var el = renderSettings.el; + var holderSettings = renderSettings.holderSettings; + var engineSettings = renderSettings.engineSettings; + + switch (engineSettings.renderer) { + case 'svg': + if (!App.setup.supportsSVG) return; + break; + case 'canvas': + if (!App.setup.supportsCanvas) return; + break; + default: + return; + } + + //todo: move generation of scene up to flag generation to reduce extra object creation + var scene = { + width: holderSettings.dimensions.width, + height: holderSettings.dimensions.height, + theme: holderSettings.theme, + flags: holderSettings.flags + }; + + var sceneGraph = buildSceneGraph(scene); + + function getRenderedImage() { + var image = null; + switch (engineSettings.renderer) { + case 'canvas': + image = sgCanvasRenderer(sceneGraph, renderSettings); + break; + case 'svg': + image = svgRenderer(sceneGraph, renderSettings); + break; + default: + throw 'Holder: invalid renderer: ' + engineSettings.renderer; + } + + return image; + } + + image = getRenderedImage(); + + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + + //todo: add canvas rendering + if (mode == 'background') { + el.style.backgroundImage = 'url(' + image + ')'; + + if (!engineSettings.noBackgroundSize) { + el.style.backgroundSize = scene.width + 'px ' + scene.height + 'px'; + } + } else { + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + if (engineSettings.reRender) { + global.setTimeout(function () { + var image = getRenderedImage(); + if (image == null) { + throw 'Holder: couldn\'t render placeholder'; + } + //todo: refactor this code into a function + if (el.nodeName.toLowerCase() === 'img') { + DOM.setAttr(el, { + 'src': image + }); + } else if (el.nodeName.toLowerCase() === 'object') { + DOM.setAttr(el, { + 'data': image, + 'type': 'image/svg+xml' + }); + } + }, 150); + } + } + //todo: account for re-rendering + DOM.setAttr(el, { + 'data-holder-rendered': true + }); + } + + /** + * Core function that takes a Holder scene description and builds a scene graph + * + * @private + * @param scene Holder scene object + */ + //todo: make this function reusable + //todo: merge app defaults and setup properties into the scene argument + function buildSceneGraph(scene) { + var fontSize = App.defaults.size; + if (parseFloat(scene.theme.size)) { + fontSize = scene.theme.size; + } else if (parseFloat(scene.flags.size)) { + fontSize = scene.flags.size; + } + + scene.font = { + family: scene.theme.font ? scene.theme.font : 'Arial, Helvetica, Open Sans, sans-serif', + size: textSize(scene.width, scene.height, fontSize, App.defaults.scale), + units: scene.theme.units ? scene.theme.units : App.defaults.units, + weight: scene.theme.fontweight ? scene.theme.fontweight : 'bold' + }; + + scene.text = scene.theme.text || Math.floor(scene.width) + 'x' + Math.floor(scene.height); + + scene.noWrap = scene.theme.nowrap || scene.flags.nowrap; + + scene.align = scene.theme.align || scene.flags.align || 'center'; + + switch (scene.flags.textmode) { + case 'literal': + scene.text = scene.flags.dimensions.width + 'x' + scene.flags.dimensions.height; + break; + case 'exact': + if (!scene.flags.exactDimensions) break; + scene.text = Math.floor(scene.flags.exactDimensions.width) + 'x' + Math.floor(scene.flags.exactDimensions.height); + break; + } + + var lineWrap = scene.flags.lineWrap || App.setup.lineWrapRatio; + var sceneMargin = scene.width * lineWrap; + var maxLineWidth = sceneMargin; + + var sceneGraph = new SceneGraph({ + width: scene.width, + height: scene.height + }); + + var Shape = sceneGraph.Shape; + + var holderBg = new Shape.Rect('holderBg', { + fill: scene.theme.bg + }); + + holderBg.resize(scene.width, scene.height); + sceneGraph.root.add(holderBg); + + if (scene.flags.outline) { + var outlineColor = new Color(holderBg.properties.fill); + outlineColor = outlineColor.lighten(outlineColor.lighterThan('7f7f7f') ? -0.1 : 0.1); + holderBg.properties.outline = { + fill: outlineColor.toHex(true), + width: 2 + }; + } + + var holderTextColor = scene.theme.fg; + + if (scene.flags.autoFg) { + var holderBgColor = new Color(holderBg.properties.fill); + var lightColor = new Color('fff'); + var darkColor = new Color('000', { + 'alpha': 0.285714 + }); + + holderTextColor = holderBgColor.blendAlpha(holderBgColor.lighterThan('7f7f7f') ? darkColor : lightColor).toHex(true); + } + + var holderTextGroup = new Shape.Group('holderTextGroup', { + text: scene.text, + align: scene.align, + font: scene.font, + fill: holderTextColor + }); + + holderTextGroup.moveTo(null, null, 1); + sceneGraph.root.add(holderTextGroup); + + var tpdata = holderTextGroup.textPositionData = stagingRenderer(sceneGraph); + if (!tpdata) { + throw 'Holder: staging fallback not supported yet.'; + } + holderTextGroup.properties.leading = tpdata.boundingBox.height; + + var textNode = null; + var line = null; + + function finalizeLine(parent, line, width, height) { + line.width = width; + line.height = height; + parent.width = Math.max(parent.width, line.width); + parent.height += line.height; + } + + if (tpdata.lineCount > 1) { + var offsetX = 0; + var offsetY = 0; + var lineIndex = 0; + var lineKey; + line = new Shape.Group('line' + lineIndex); + + //Double margin so that left/right-aligned next is not flush with edge of image + if (scene.align === 'left' || scene.align === 'right') { + maxLineWidth = scene.width * (1 - (1 - lineWrap) * 2); + } + + for (var i = 0; i < tpdata.words.length; i++) { + var word = tpdata.words[i]; + textNode = new Shape.Text(word.text); + var newline = word.text == '\\n'; + if (!scene.noWrap && (offsetX + word.width >= maxLineWidth || newline === true)) { + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + offsetX = 0; + offsetY += holderTextGroup.properties.leading; + lineIndex += 1; + line = new Shape.Group('line' + lineIndex); + line.y = offsetY; + } + if (newline === true) { + continue; + } + textNode.moveTo(offsetX, 0); + offsetX += tpdata.spaceWidth + word.width; + line.add(textNode); + } + + finalizeLine(holderTextGroup, line, offsetX, holderTextGroup.properties.leading); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo(scene.width - line.width, null, null); + } + + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + for (lineKey in holderTextGroup.children) { + line = holderTextGroup.children[lineKey]; + line.moveTo((holderTextGroup.width - line.width) / 2, null, null); + } + + holderTextGroup.moveTo((scene.width - holderTextGroup.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - holderTextGroup.height) / 2, null); + + //If the text exceeds vertical space, move it down so the first line is visible + if ((scene.height - holderTextGroup.height) / 2 < 0) { + holderTextGroup.moveTo(null, 0, null); + } + } else { + textNode = new Shape.Text(scene.text); + line = new Shape.Group('line0'); + line.add(textNode); + holderTextGroup.add(line); + + if (scene.align === 'left') { + holderTextGroup.moveTo(scene.width - sceneMargin, null, null); + } else if (scene.align === 'right') { + holderTextGroup.moveTo(0 - (scene.width - sceneMargin), null, null); + } else { + holderTextGroup.moveTo((scene.width - tpdata.boundingBox.width) / 2, null, null); + } + + holderTextGroup.moveTo(null, (scene.height - tpdata.boundingBox.height) / 2, null); + } + + //todo: renderlist + return sceneGraph; + } + + /** + * Adaptive text sizing function + * + * @private + * @param width Parent width + * @param height Parent height + * @param fontSize Requested text size + * @param scale Proportional scale of text + */ + function textSize(width, height, fontSize, scale) { + var stageWidth = parseInt(width, 10); + var stageHeight = parseInt(height, 10); + + var bigSide = Math.max(stageWidth, stageHeight); + var smallSide = Math.min(stageWidth, stageHeight); + + var newHeight = 0.8 * Math.min(smallSide, bigSide * scale); + return Math.round(Math.max(fontSize, newHeight)); + } + + /** + * Iterates over resizable (fluid or auto) placeholders and renders them + * + * @private + * @param element Optional element selector, specified only if a specific element needs to be re-rendered + */ + function updateResizableElements(element) { + var images; + if (element == null || element.nodeType == null) { + images = App.vars.resizableImages; + } else { + images = [element]; + } + for (var i = 0, l = images.length; i < l; i++) { + var el = images[i]; + if (el.holderData) { + var flags = el.holderData.flags; + var dimensions = dimensionCheck(el); + if (dimensions) { + if (!el.holderData.resizeUpdate) { + continue; + } + + if (flags.fluid && flags.auto) { + var fluidConfig = el.holderData.fluidConfig; + switch (fluidConfig.mode) { + case 'width': + dimensions.height = dimensions.width / fluidConfig.ratio; + break; + case 'height': + dimensions.width = dimensions.height * fluidConfig.ratio; + break; + } + } + + var settings = { + mode: 'image', + holderSettings: { + dimensions: dimensions, + theme: flags.theme, + flags: flags + }, + el: el, + engineSettings: el.holderData.engineSettings + }; + + if (flags.textmode == 'exact') { + flags.exactDimensions = dimensions; + settings.holderSettings.dimensions = flags.dimensions; + } + + render(settings); + } else { + setInvisible(el); + } + } + } + } + + /** + * Sets up aspect ratio metadata for fluid placeholders, in order to preserve proportions when resizing + * + * @private + * @param el Image DOM element + */ + function setInitialDimensions(el) { + if (el.holderData) { + var dimensions = dimensionCheck(el); + if (dimensions) { + var flags = el.holderData.flags; + + var fluidConfig = { + fluidHeight: flags.dimensions.height.slice(-1) == '%', + fluidWidth: flags.dimensions.width.slice(-1) == '%', + mode: null, + initialDimensions: dimensions + }; + + if (fluidConfig.fluidWidth && !fluidConfig.fluidHeight) { + fluidConfig.mode = 'width'; + fluidConfig.ratio = fluidConfig.initialDimensions.width / parseFloat(flags.dimensions.height); + } else if (!fluidConfig.fluidWidth && fluidConfig.fluidHeight) { + fluidConfig.mode = 'height'; + fluidConfig.ratio = parseFloat(flags.dimensions.width) / fluidConfig.initialDimensions.height; + } + + el.holderData.fluidConfig = fluidConfig; + } else { + setInvisible(el); + } + } + } + + /** + * Iterates through all current invisible images, and if they're visible, renders them and removes them from further checks. Runs every animation frame. + * + * @private + */ + function visibilityCheck() { + var renderableImages = []; + var keys = Object.keys(App.vars.invisibleImages); + var el; + + keys.forEach(function (key) { + el = App.vars.invisibleImages[key]; + if (dimensionCheck(el) && el.nodeName.toLowerCase() == 'img') { + renderableImages.push(el); + delete App.vars.invisibleImages[key]; + } + }); + + if (renderableImages.length) { + Holder.run({ + images: renderableImages + }); + } + + // Done to prevent 100% CPU usage via aggressive calling of requestAnimationFrame + setTimeout(function () { + global.requestAnimationFrame(visibilityCheck); + }, 10); + } + + /** + * Starts checking for invisible placeholders if not doing so yet. Does nothing otherwise. + * + * @private + */ + function startVisibilityCheck() { + if (!App.vars.visibilityCheckStarted) { + global.requestAnimationFrame(visibilityCheck); + App.vars.visibilityCheckStarted = true; + } + } + + /** + * Sets a unique ID for an image detected to be invisible and adds it to the map of invisible images checked by visibilityCheck + * + * @private + * @param el Invisible DOM element + */ + function setInvisible(el) { + if (!el.holderData.invisibleId) { + App.vars.invisibleId += 1; + App.vars.invisibleImages['i' + App.vars.invisibleId] = el; + el.holderData.invisibleId = App.vars.invisibleId; + } + } + + //todo: see if possible to convert stagingRenderer to use HTML only + var stagingRenderer = (function() { + var svg = null, + stagingText = null, + stagingTextNode = null; + return function(graph) { + var rootNode = graph.root; + if (App.setup.supportsSVG) { + var firstTimeSetup = false; + var tnode = function(text) { + return document.createTextNode(text); + }; + if (svg == null || svg.parentNode !== document.body) { + firstTimeSetup = true; + } + + svg = SVG.initSVG(svg, rootNode.properties.width, rootNode.properties.height); + //Show staging element before staging + svg.style.display = 'block'; + + if (firstTimeSetup) { + stagingText = DOM.newEl('text', SVG_NS); + stagingTextNode = tnode(null); + DOM.setAttr(stagingText, { + x: 0 + }); + stagingText.appendChild(stagingTextNode); + svg.appendChild(stagingText); + document.body.appendChild(svg); + svg.style.visibility = 'hidden'; + svg.style.position = 'absolute'; + svg.style.top = '-100%'; + svg.style.left = '-100%'; + //todo: workaround for zero-dimension tag in Opera 12 + //svg.setAttribute('width', 0); + //svg.setAttribute('height', 0); + } + + var holderTextGroup = rootNode.children.holderTextGroup; + var htgProps = holderTextGroup.properties; + DOM.setAttr(stagingText, { + 'y': htgProps.font.size, + 'style': utils.cssProps({ + 'font-weight': htgProps.font.weight, + 'font-size': htgProps.font.size + htgProps.font.units, + 'font-family': htgProps.font.family + }) + }); + + //Unescape HTML entities to get approximately the right width + var txt = DOM.newEl('textarea'); + txt.innerHTML = htgProps.text; + stagingTextNode.nodeValue = txt.value; + + //Get bounding box for the whole string (total width and height) + var stagingTextBBox = stagingText.getBBox(); + + //Get line count and split the string into words + var lineCount = Math.ceil(stagingTextBBox.width / rootNode.properties.width); + var words = htgProps.text.split(' '); + var newlines = htgProps.text.match(/\\n/g); + lineCount += newlines == null ? 0 : newlines.length; + + //Get bounding box for the string with spaces removed + stagingTextNode.nodeValue = htgProps.text.replace(/[ ]+/g, ''); + var computedNoSpaceLength = stagingText.getComputedTextLength(); + + //Compute average space width + var diffLength = stagingTextBBox.width - computedNoSpaceLength; + var spaceWidth = Math.round(diffLength / Math.max(1, words.length - 1)); + + //Get widths for every word with space only if there is more than one line + var wordWidths = []; + if (lineCount > 1) { + stagingTextNode.nodeValue = ''; + for (var i = 0; i < words.length; i++) { + if (words[i].length === 0) continue; + stagingTextNode.nodeValue = utils.decodeHtmlEntity(words[i]); + var bbox = stagingText.getBBox(); + wordWidths.push({ + text: words[i], + width: bbox.width + }); + } + } + + //Hide staging element after staging + svg.style.display = 'none'; + + return { + spaceWidth: spaceWidth, + lineCount: lineCount, + boundingBox: stagingTextBBox, + words: wordWidths + }; + } else { + //todo: canvas fallback for measuring text on android 2.3 + return false; + } + }; + })(); + + //Helpers + + /** + * Prevents a function from being called too often, waits until a timer elapses to call it again + * + * @param fn Function to call + */ + function debounce(fn) { + if (!App.vars.debounceTimer) fn.call(this); + if (App.vars.debounceTimer) global.clearTimeout(App.vars.debounceTimer); + App.vars.debounceTimer = global.setTimeout(function() { + App.vars.debounceTimer = null; + fn.call(this); + }, App.setup.debounce); + } + + /** + * Holder-specific resize/orientation change callback, debounced to prevent excessive execution + */ + function resizeEvent() { + debounce(function() { + updateResizableElements(null); + }); + } + + //Set up flags + + for (var flag in App.flags) { + if (!App.flags.hasOwnProperty(flag)) continue; + App.flags[flag].match = function(val) { + return val.match(this.regex); + }; + } + + //Properties set once on setup + + App.setup = { + renderer: 'html', + debounce: 100, + ratio: 1, + supportsCanvas: false, + supportsSVG: false, + lineWrapRatio: 0.9, + dataAttr: 'data-src', + renderers: ['html', 'canvas', 'svg'] + }; + + //Properties modified during runtime + + App.vars = { + preempted: false, + resizableImages: [], + invisibleImages: {}, + invisibleId: 0, + visibilityCheckStarted: false, + debounceTimer: null, + cache: {} + }; + + //Pre-flight + + (function() { + var canvas = DOM.newEl('canvas'); + + if (canvas.getContext) { + if (canvas.toDataURL('image/png').indexOf('data:image/png') != -1) { + App.setup.renderer = 'canvas'; + App.setup.supportsCanvas = true; + } + } + + if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect) { + App.setup.renderer = 'svg'; + App.setup.supportsSVG = true; + } + })(); + + //Starts checking for invisible placeholders + startVisibilityCheck(); + + if (onDomReady) { + onDomReady(function() { + if (!App.vars.preempted) { + Holder.run(); + } + if (global.addEventListener) { + global.addEventListener('resize', resizeEvent, false); + global.addEventListener('orientationchange', resizeEvent, false); + } else { + global.attachEvent('onresize', resizeEvent); + } + + if (typeof global.Turbolinks == 'object') { + global.document.addEventListener('page:change', function() { + Holder.run(); + }); + } + }); + } + + module.exports = Holder; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /*! + * onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license + * + * Specially modified to work with Holder.js + */ + + function _onDomReady(win) { + //Lazy loading fix for Firefox < 3.6 + //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html + if (document.readyState == null && document.addEventListener) { + document.addEventListener("DOMContentLoaded", function DOMContentLoaded() { + document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); + document.readyState = "complete"; + }, false); + document.readyState = "loading"; + } + + var doc = win.document, + docElem = doc.documentElement, + + LOAD = "load", + FALSE = false, + ONLOAD = "on"+LOAD, + COMPLETE = "complete", + READYSTATE = "readyState", + ATTACHEVENT = "attachEvent", + DETACHEVENT = "detachEvent", + ADDEVENTLISTENER = "addEventListener", + DOMCONTENTLOADED = "DOMContentLoaded", + ONREADYSTATECHANGE = "onreadystatechange", + REMOVEEVENTLISTENER = "removeEventListener", + + // W3C Event model + w3c = ADDEVENTLISTENER in doc, + _top = FALSE, + + // isReady: Is the DOM ready to be used? Set to true once it occurs. + isReady = FALSE, + + // Callbacks pending execution until DOM is ready + callbacks = []; + + // Handle when the DOM is ready + function ready( fn ) { + if ( !isReady ) { + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !doc.body ) { + return defer( ready ); + } + + // Remember that the DOM is ready + isReady = true; + + // Execute all callbacks + while ( fn = callbacks.shift() ) { + defer( fn ); + } + } + } + + // The ready event handler + function completed( event ) { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) { + detach(); + ready(); + } + } + + // Clean-up method for dom ready events + function detach() { + if ( w3c ) { + doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE ); + } else { + doc[DETACHEVENT]( ONREADYSTATECHANGE, completed ); + win[DETACHEVENT]( ONLOAD, completed ); + } + } + + // Defers a function, scheduling it to run after the current call stack has cleared. + function defer( fn, wait ) { + // Allow 0 to be passed + setTimeout( fn, +wait >= 0 ? wait : 1 ); + } + + // Attach the listeners: + + // Catch cases where onDomReady is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( doc[READYSTATE] === COMPLETE ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + defer( ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( w3c ) { + // Use the handy event callback + doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE ); + + // A fallback to window.onload, that will always work + win[ADDEVENTLISTENER]( LOAD, completed, FALSE ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed ); + + // A fallback to window.onload, that will always work + win[ATTACHEVENT]( ONLOAD, completed ); + + // If IE and not a frame + // continually check to see if the document is ready + try { + _top = win.frameElement == null && docElem; + } catch(e) {} + + if ( _top && _top.doScroll ) { + (function doScrollCheck() { + if ( !isReady ) { + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + _top.doScroll("left"); + } catch(e) { + return defer( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + ready(); + } + })(); + } + } + + function onDomReady( fn ) { + // If DOM is ready, execute the function (async), otherwise wait + isReady ? defer( fn ) : callbacks.push( fn ); + } + + // Add version + onDomReady.version = "1.4.0"; + // Add method to check if DOM is ready + onDomReady.isReady = function(){ + return isReady; + }; + + return onDomReady; + } + + module.exports = typeof window !== "undefined" && _onDomReady(window); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + //Modified version of component/querystring + //Changes: updated dependencies, dot notation parsing, JSHint fixes + //Fork at https://github.com/imsky/querystring + + /** + * Module dependencies. + */ + + var encode = encodeURIComponent; + var decode = decodeURIComponent; + var trim = __webpack_require__(4); + var type = __webpack_require__(5); + + var arrayRegex = /(\w+)\[(\d+)\]/; + var objectRegex = /\w+\.\w+/; + + /** + * Parse the given query `str`. + * + * @param {String} str + * @return {Object} + * @api public + */ + + exports.parse = function(str){ + if ('string' !== typeof str) return {}; + + str = trim(str); + if ('' === str) return {}; + if ('?' === str.charAt(0)) str = str.slice(1); + + var obj = {}; + var pairs = str.split('&'); + for (var i = 0; i < pairs.length; i++) { + var parts = pairs[i].split('='); + var key = decode(parts[0]); + var m, ctx, prop; + + if (m = arrayRegex.exec(key)) { + obj[m[1]] = obj[m[1]] || []; + obj[m[1]][m[2]] = decode(parts[1]); + continue; + } + + if (m = objectRegex.test(key)) { + m = key.split('.'); + ctx = obj; + + while (m.length) { + prop = m.shift(); + + if (!prop.length) continue; + + if (!ctx[prop]) { + ctx[prop] = {}; + } else if (ctx[prop] && typeof ctx[prop] !== 'object') { + break; + } + + if (!m.length) { + ctx[prop] = decode(parts[1]); + } + + ctx = ctx[prop]; + } + + continue; + } + + obj[parts[0]] = null == parts[1] ? '' : decode(parts[1]); + } + + return obj; + }; + + /** + * Stringify the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api public + */ + + exports.stringify = function(obj){ + if (!obj) return ''; + var pairs = []; + + for (var key in obj) { + var value = obj[key]; + + if ('array' == type(value)) { + for (var i = 0; i < value.length; ++i) { + pairs.push(encode(key + '[' + i + ']') + '=' + encode(value[i])); + } + continue; + } + + pairs.push(encode(key) + '=' + encode(obj[key])); + } + + return pairs.join('&'); + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + + + exports = module.exports = trim; + + function trim(str){ + return str.replace(/^\s*|\s*$/g, ''); + } + + exports.left = function(str){ + return str.replace(/^\s*/, ''); + }; + + exports.right = function(str){ + return str.replace(/\s*$/, ''); + }; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + /** + * toString ref. + */ + + var toString = Object.prototype.toString; + + /** + * Return the type of `val`. + * + * @param {Mixed} val + * @return {String} + * @api public + */ + + module.exports = function(val){ + switch (toString.call(val)) { + case '[object Date]': return 'date'; + case '[object RegExp]': return 'regexp'; + case '[object Arguments]': return 'arguments'; + case '[object Array]': return 'array'; + case '[object Error]': return 'error'; + } + + if (val === null) return 'null'; + if (val === undefined) return 'undefined'; + if (val !== val) return 'nan'; + if (val && val.nodeType === 1) return 'element'; + + val = val.valueOf + ? val.valueOf() + : Object.prototype.valueOf.apply(val) + + return typeof val; + }; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + + var SceneGraph = function(sceneProperties) { + var nodeCount = 1; + + //todo: move merge to helpers section + function merge(parent, child) { + for (var prop in child) { + parent[prop] = child[prop]; + } + return parent; + } + + var SceneNode = function(name) { + nodeCount++; + this.parent = null; + this.children = {}; + this.id = nodeCount; + this.name = 'n' + nodeCount; + if (typeof name !== 'undefined') { + this.name = name; + } + this.x = this.y = this.z = 0; + this.width = this.height = 0; + }; + + SceneNode.prototype.resize = function(width, height) { + if (width != null) { + this.width = width; + } + if (height != null) { + this.height = height; + } + }; + + SceneNode.prototype.moveTo = function(x, y, z) { + this.x = x != null ? x : this.x; + this.y = y != null ? y : this.y; + this.z = z != null ? z : this.z; + }; + + SceneNode.prototype.add = function(child) { + var name = child.name; + if (typeof this.children[name] === 'undefined') { + this.children[name] = child; + child.parent = this; + } else { + throw 'SceneGraph: child already exists: ' + name; + } + }; + + var RootNode = function() { + SceneNode.call(this, 'root'); + this.properties = sceneProperties; + }; + + RootNode.prototype = new SceneNode(); + + var Shape = function(name, props) { + SceneNode.call(this, name); + this.properties = { + 'fill': '#000000' + }; + if (typeof props !== 'undefined') { + merge(this.properties, props); + } else if (typeof name !== 'undefined' && typeof name !== 'string') { + throw 'SceneGraph: invalid node name'; + } + }; + + Shape.prototype = new SceneNode(); + + var Group = function() { + Shape.apply(this, arguments); + this.type = 'group'; + }; + + Group.prototype = new Shape(); + + var Rect = function() { + Shape.apply(this, arguments); + this.type = 'rect'; + }; + + Rect.prototype = new Shape(); + + var Text = function(text) { + Shape.call(this); + this.type = 'text'; + this.properties.text = text; + }; + + Text.prototype = new Shape(); + + var root = new RootNode(); + + this.Shape = { + 'Rect': Rect, + 'Text': Text, + 'Group': Group + }; + + this.root = root; + return this; + }; + + module.exports = SceneGraph; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Shallow object clone and merge + * + * @param a Object A + * @param b Object B + * @returns {Object} New object with all of A's properties, and all of B's properties, overwriting A's properties + */ + exports.extend = function(a, b) { + var c = {}; + for (var x in a) { + if (a.hasOwnProperty(x)) { + c[x] = a[x]; + } + } + if (b != null) { + for (var y in b) { + if (b.hasOwnProperty(y)) { + c[y] = b[y]; + } + } + } + return c; + }; + + /** + * Takes a k/v list of CSS properties and returns a rule + * + * @param props CSS properties object + */ + exports.cssProps = function(props) { + var ret = []; + for (var p in props) { + if (props.hasOwnProperty(p)) { + ret.push(p + ':' + props[p]); + } + } + return ret.join(';'); + }; + + /** + * Encodes HTML entities in a string + * + * @param str Input string + */ + exports.encodeHtmlEntity = function(str) { + var buf = []; + var charCode = 0; + for (var i = str.length - 1; i >= 0; i--) { + charCode = str.charCodeAt(i); + if (charCode > 128) { + buf.unshift(['&#', charCode, ';'].join('')); + } else { + buf.unshift(str[i]); + } + } + return buf.join(''); + }; + + /** + * Checks if an image exists + * + * @param src URL of image + * @param callback Callback to call once image status has been found + */ + exports.imageExists = function(src, callback) { + var image = new Image(); + image.onerror = function() { + callback.call(this, false); + }; + image.onload = function() { + callback.call(this, true); + }; + image.src = src; + }; + + /** + * Decodes HTML entities in a string + * + * @param str Input string + */ + exports.decodeHtmlEntity = function(str) { + return str.replace(/&#(\d+);/g, function(match, dec) { + return String.fromCharCode(dec); + }); + }; + + + /** + * Returns an element's dimensions if it's visible, `false` otherwise. + * + * @param el DOM element + */ + exports.dimensionCheck = function(el) { + var dimensions = { + height: el.clientHeight, + width: el.clientWidth + }; + + if (dimensions.height && dimensions.width) { + return dimensions; + } else { + return false; + } + }; + + + /** + * Returns true if value is truthy or if it is "semantically truthy" + * @param val + */ + exports.truthy = function(val) { + if (typeof val === 'string') { + return val === 'true' || val === 'yes' || val === '1' || val === 'on' || val === '✓'; + } + return !!val; + }; + + /** + * Parses input into a well-formed CSS color + * @param val + */ + exports.parseColor = function(val) { + var hexre = /(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i; + var rgbre = /^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/; + var rgbare = /^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/; + + var match = val.match(hexre); + var retval; + + if (match !== null) { + retval = match[1] || match[2]; + if (retval[0] !== '#') { + return '#' + retval; + } else { + return retval; + } + } + + match = val.match(rgbre); + + if (match !== null) { + retval = 'rgb(' + match.slice(1).join(',') + ')'; + return retval; + } + + match = val.match(rgbare); + + if (match !== null) { + const normalizeAlpha = function (a) { return '0.' + a.split('.')[1]; }; + const fixedMatch = match.slice(1).map(function (e, i) { + return (i === 3) ? normalizeAlpha(e) : e; + }); + retval = 'rgba(' + fixedMatch.join(',') + ')'; + return retval; + } + + return null; + }; + + /** + * Provides the correct scaling ratio for canvas drawing operations on HiDPI screens (e.g. Retina displays) + */ + exports.canvasRatio = function () { + var devicePixelRatio = 1; + var backingStoreRatio = 1; + + if (global.document) { + var canvas = global.document.createElement('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + devicePixelRatio = global.devicePixelRatio || 1; + backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + } + } + + return devicePixelRatio / backingStoreRatio; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {var DOM = __webpack_require__(9); + + var SVG_NS = 'http://www.w3.org/2000/svg'; + var NODE_TYPE_COMMENT = 8; + + /** + * Generic SVG element creation function + * + * @param svg SVG context, set to null if new + * @param width Document width + * @param height Document height + */ + exports.initSVG = function(svg, width, height) { + var defs, style, initialize = false; + + if (svg && svg.querySelector) { + style = svg.querySelector('style'); + if (style === null) { + initialize = true; + } + } else { + svg = DOM.newEl('svg', SVG_NS); + initialize = true; + } + + if (initialize) { + defs = DOM.newEl('defs', SVG_NS); + style = DOM.newEl('style', SVG_NS); + DOM.setAttr(style, { + 'type': 'text/css' + }); + defs.appendChild(style); + svg.appendChild(defs); + } + + //IE throws an exception if this is set and Chrome requires it to be set + if (svg.webkitMatchesSelector) { + svg.setAttribute('xmlns', SVG_NS); + } + + //Remove comment nodes + for (var i = 0; i < svg.childNodes.length; i++) { + if (svg.childNodes[i].nodeType === NODE_TYPE_COMMENT) { + svg.removeChild(svg.childNodes[i]); + } + } + + //Remove CSS + while (style.childNodes.length) { + style.removeChild(style.childNodes[0]); + } + + DOM.setAttr(svg, { + 'width': width, + 'height': height, + 'viewBox': '0 0 ' + width + ' ' + height, + 'preserveAspectRatio': 'none' + }); + + return svg; + }; + + /** + * Converts serialized SVG to a string suitable for data URI use + * @param svgString Serialized SVG string + * @param [base64] Use base64 encoding for data URI + */ + exports.svgStringToDataURI = function() { + var rawPrefix = 'data:image/svg+xml;charset=UTF-8,'; + var base64Prefix = 'data:image/svg+xml;charset=UTF-8;base64,'; + + return function(svgString, base64) { + if (base64) { + return base64Prefix + btoa(global.unescape(encodeURIComponent(svgString))); + } else { + return rawPrefix + encodeURIComponent(svgString); + } + }; + }(); + + /** + * Returns serialized SVG with XML processing instructions + * + * @param svg SVG context + * @param stylesheets CSS stylesheets to include + */ + exports.serializeSVG = function(svg, engineSettings) { + if (!global.XMLSerializer) return; + var serializer = new XMLSerializer(); + var svgCSS = ''; + var stylesheets = engineSettings.stylesheets; + + //External stylesheets: Processing Instruction method + if (engineSettings.svgXMLStylesheet) { + var xml = DOM.createXML(); + //Add directives + for (var i = stylesheets.length - 1; i >= 0; i--) { + var csspi = xml.createProcessingInstruction('xml-stylesheet', 'href="' + stylesheets[i] + '" rel="stylesheet"'); + xml.insertBefore(csspi, xml.firstChild); + } + + xml.removeChild(xml.documentElement); + svgCSS = serializer.serializeToString(xml); + } + + var svgText = serializer.serializeToString(svg); + svgText = svgText.replace(/\&(\#[0-9]{2,}\;)/g, '&$1'); + return svgCSS + svgText; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Generic new DOM element function + * + * @param tag Tag to create + * @param namespace Optional namespace value + */ + exports.newEl = function(tag, namespace) { + if (!global.document) return; + + if (namespace == null) { + return global.document.createElement(tag); + } else { + return global.document.createElementNS(namespace, tag); + } + }; + + /** + * Generic setAttribute function + * + * @param el Reference to DOM element + * @param attrs Object with attribute keys and values + */ + exports.setAttr = function (el, attrs) { + for (var a in attrs) { + el.setAttribute(a, attrs[a]); + } + }; + + /** + * Creates a XML document + * @private + */ + exports.createXML = function() { + if (!global.DOMParser) return; + return new DOMParser().parseFromString('', 'application/xml'); + }; + + /** + * Converts a value into an array of DOM nodes + * + * @param val A string, a NodeList, a Node, or an HTMLCollection + */ + exports.getNodeArray = function(val) { + var retval = null; + if (typeof(val) == 'string') { + retval = document.querySelectorAll(val); + } else if (global.NodeList && val instanceof global.NodeList) { + retval = val; + } else if (global.Node && val instanceof global.Node) { + retval = [val]; + } else if (global.HTMLCollection && val instanceof global.HTMLCollection) { + retval = val; + } else if (val instanceof Array) { + retval = val; + } else if (val === null) { + retval = []; + } + + retval = Array.prototype.slice.call(retval); + + return retval; + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + + var Color = function(color, options) { + //todo: support rgba, hsla, and rrggbbaa notation + //todo: use CIELAB internally + //todo: add clamp function (with sign) + if (typeof color !== 'string') return; + + this.original = color; + + if (color.charAt(0) === '#') { + color = color.slice(1); + } + + if (/[^a-f0-9]+/i.test(color)) return; + + if (color.length === 3) { + color = color.replace(/./g, '$&$&'); + } + + if (color.length !== 6) return; + + this.alpha = 1; + + if (options && options.alpha) { + this.alpha = options.alpha; + } + + this.set(parseInt(color, 16)); + }; + + //todo: jsdocs + Color.rgb2hex = function(r, g, b) { + function format (decimal) { + var hex = (decimal | 0).toString(16); + if (decimal < 16) { + hex = '0' + hex; + } + return hex; + } + + return [r, g, b].map(format).join(''); + }; + + //todo: jsdocs + Color.hsl2rgb = function (h, s, l) { + var H = h / 60; + var C = (1 - Math.abs(2 * l - 1)) * s; + var X = C * (1 - Math.abs(parseInt(H) % 2 - 1)); + var m = l - (C / 2); + + var r = 0, g = 0, b = 0; + + if (H >= 0 && H < 1) { + r = C; + g = X; + } else if (H >= 1 && H < 2) { + r = X; + g = C; + } else if (H >= 2 && H < 3) { + g = C; + b = X; + } else if (H >= 3 && H < 4) { + g = X; + b = C; + } else if (H >= 4 && H < 5) { + r = X; + b = C; + } else if (H >= 5 && H < 6) { + r = C; + b = X; + } + + r += m; + g += m; + b += m; + + r = parseInt(r * 255); + g = parseInt(g * 255); + b = parseInt(b * 255); + + return [r, g, b]; + }; + + /** + * Sets the color from a raw RGB888 integer + * @param raw RGB888 representation of color + */ + //todo: refactor into a static method + //todo: factor out individual color spaces + //todo: add HSL, CIELAB, and CIELUV + Color.prototype.set = function (val) { + this.raw = val; + + var r = (this.raw & 0xFF0000) >> 16; + var g = (this.raw & 0x00FF00) >> 8; + var b = (this.raw & 0x0000FF); + + // BT.709 + var y = 0.2126 * r + 0.7152 * g + 0.0722 * b; + var u = -0.09991 * r - 0.33609 * g + 0.436 * b; + var v = 0.615 * r - 0.55861 * g - 0.05639 * b; + + this.rgb = { + r: r, + g: g, + b: b + }; + + this.yuv = { + y: y, + u: u, + v: v + }; + + return this; + }; + + /** + * Lighten or darken a color + * @param multiplier Amount to lighten or darken (-1 to 1) + */ + Color.prototype.lighten = function(multiplier) { + var cm = Math.min(1, Math.max(0, Math.abs(multiplier))) * (multiplier < 0 ? -1 : 1); + var bm = (255 * cm) | 0; + var cr = Math.min(255, Math.max(0, this.rgb.r + bm)); + var cg = Math.min(255, Math.max(0, this.rgb.g + bm)); + var cb = Math.min(255, Math.max(0, this.rgb.b + bm)); + var hex = Color.rgb2hex(cr, cg, cb); + return new Color(hex); + }; + + /** + * Output color in hex format + * @param addHash Add a hash character to the beginning of the output + */ + Color.prototype.toHex = function(addHash) { + return (addHash ? '#' : '') + this.raw.toString(16); + }; + + /** + * Returns whether or not current color is lighter than another color + * @param color Color to compare against + */ + Color.prototype.lighterThan = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + return this.yuv.y > color.yuv.y; + }; + + /** + * Returns the result of mixing current color with another color + * @param color Color to mix with + * @param multiplier How much to mix with the other color + */ + /* + Color.prototype.mix = function (color, multiplier) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var r = this.rgb.r; + var g = this.rgb.g; + var b = this.rgb.b; + var a = this.alpha; + + var m = typeof multiplier !== 'undefined' ? multiplier : 0.5; + + //todo: write a lerp function + r = r + m * (color.rgb.r - r); + g = g + m * (color.rgb.g - g); + b = b + m * (color.rgb.b - b); + a = a + m * (color.alpha - a); + + return new Color(Color.rgbToHex(r, g, b), { + 'alpha': a + }); + }; + */ + + /** + * Returns the result of blending another color on top of current color with alpha + * @param color Color to blend on top of current color, i.e. "Ca" + */ + //todo: see if .blendAlpha can be merged into .mix + Color.prototype.blendAlpha = function(color) { + if (!(color instanceof Color)) { + color = new Color(color); + } + + var Ca = color; + var Cb = this; + + //todo: write alpha blending function + var r = Ca.alpha * Ca.rgb.r + (1 - Ca.alpha) * Cb.rgb.r; + var g = Ca.alpha * Ca.rgb.g + (1 - Ca.alpha) * Cb.rgb.g; + var b = Ca.alpha * Ca.rgb.b + (1 - Ca.alpha) * Cb.rgb.b; + + return new Color(Color.rgb2hex(r, g, b)); + }; + + module.exports = Color; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports) { + + module.exports = { + 'version': '2.9.7', + 'svg_ns': 'http://www.w3.org/2000/svg' + }; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + var shaven = __webpack_require__(13); + + var SVG = __webpack_require__(8); + var constants = __webpack_require__(11); + var utils = __webpack_require__(7); + + var SVG_NS = constants.svg_ns; + + var templates = { + 'element': function (options) { + var tag = options.tag; + var content = options.content || ''; + delete options.tag; + delete options.content; + return [tag, content, options]; + } + }; + + //todo: deprecate tag arg, infer tag from shape object + function convertShape (shape, tag) { + return templates.element({ + 'tag': tag, + 'width': shape.width, + 'height': shape.height, + 'fill': shape.properties.fill + }); + } + + function textCss (properties) { + return utils.cssProps({ + 'fill': properties.fill, + 'font-weight': properties.font.weight, + 'font-family': properties.font.family + ', monospace', + 'font-size': properties.font.size + properties.font.units + }); + } + + function outlinePath (bgWidth, bgHeight, outlineWidth) { + var outlineOffsetWidth = outlineWidth / 2; + + return [ + 'M', outlineOffsetWidth, outlineOffsetWidth, + 'H', bgWidth - outlineOffsetWidth, + 'V', bgHeight - outlineOffsetWidth, + 'H', outlineOffsetWidth, + 'V', 0, + 'M', 0, outlineOffsetWidth, + 'L', bgWidth, bgHeight - outlineOffsetWidth, + 'M', 0, bgHeight - outlineOffsetWidth, + 'L', bgWidth, outlineOffsetWidth + ].join(' '); + } + + module.exports = function (sceneGraph, renderSettings) { + var engineSettings = renderSettings.engineSettings; + var stylesheets = engineSettings.stylesheets; + var stylesheetXml = stylesheets.map(function (stylesheet) { + return ''; + }).join('\n'); + + var holderId = 'holder_' + Number(new Date()).toString(16); + + var root = sceneGraph.root; + var textGroup = root.children.holderTextGroup; + + var css = '#' + holderId + ' text { ' + textCss(textGroup.properties) + ' } '; + + // push text down to be equally vertically aligned with canvas renderer + textGroup.y += textGroup.textPositionData.boundingBox.height * 0.8; + + var wordTags = []; + + Object.keys(textGroup.children).forEach(function (lineKey) { + var line = textGroup.children[lineKey]; + + Object.keys(line.children).forEach(function (wordKey) { + var word = line.children[wordKey]; + var x = textGroup.x + line.x + word.x; + var y = textGroup.y + line.y + word.y; + var wordTag = templates.element({ + 'tag': 'text', + 'content': word.properties.text, + 'x': x, + 'y': y + }); + + wordTags.push(wordTag); + }); + }); + + var text = templates.element({ + 'tag': 'g', + 'content': wordTags + }); + + var outline = null; + + if (root.children.holderBg.properties.outline) { + var outlineProperties = root.children.holderBg.properties.outline; + outline = templates.element({ + 'tag': 'path', + 'd': outlinePath(root.children.holderBg.width, root.children.holderBg.height, outlineProperties.width), + 'stroke-width': outlineProperties.width, + 'stroke': outlineProperties.fill, + 'fill': 'none' + }); + } + + var bg = convertShape(root.children.holderBg, 'rect'); + + var sceneContent = []; + + sceneContent.push(bg); + if (outlineProperties) { + sceneContent.push(outline); + } + sceneContent.push(text); + + var scene = templates.element({ + 'tag': 'g', + 'id': holderId, + 'content': sceneContent + }); + + var style = templates.element({ + 'tag': 'style', + //todo: figure out how to add CDATA directive + 'content': css, + 'type': 'text/css' + }); + + var defs = templates.element({ + 'tag': 'defs', + 'content': style + }); + + var svg = templates.element({ + 'tag': 'svg', + 'content': [defs, scene], + 'width': root.properties.width, + 'height': root.properties.height, + 'xmlns': SVG_NS, + 'viewBox': [0, 0, root.properties.width, root.properties.height].join(' '), + 'preserveAspectRatio': 'none' + }); + + var output = shaven(svg); + + if (/\&(x)?#[0-9A-Fa-f]/.test(output[0])) { + output[0] = output[0].replace(/&#/gm, '&#'); + } + + output = stylesheetXml + output[0]; + + var svgString = SVG.svgStringToDataURI(output, renderSettings.mode === 'background'); + return svgString; + }; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + var escape = __webpack_require__(14) + + // TODO: remove namespace + + module.exports = function shaven (array, namespace, returnObject) { + + 'use strict' + + var i = 1 + var doesEscape = true + var HTMLString + var attributeKey + var callback + var key + + + returnObject = returnObject || {} + + + function createElement (sugarString) { + + var tags = sugarString.match(/^[\w-]+/) + var element = { + tag: tags ? tags[0] : 'div', + attr: {}, + children: [] + } + var id = sugarString.match(/#([\w-]+)/) + var reference = sugarString.match(/\$([\w-]+)/) + var classNames = sugarString.match(/\.[\w-]+/g) + + + // Assign id if is set + if (id) { + element.attr.id = id[1] + + // Add element to the return object + returnObject[id[1]] = element + } + + if (reference) + returnObject[reference[1]] = element + + if (classNames) + element.attr.class = classNames.join(' ').replace(/\./g, '') + + if (sugarString.match(/&$/g)) + doesEscape = false + + return element + } + + function replacer (key, value) { + + if (value === null || value === false || value === undefined) + return + + if (typeof value !== 'string' && typeof value !== 'object') + return String(value) + + return value + } + + function escapeAttribute (string) { + return (string || string === 0) ? + String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') : + '' + } + + function escapeHTML (string) { + return String(string) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') + } + + + if (typeof array[0] === 'string') + array[0] = createElement(array[0]) + + else if (Array.isArray(array[0])) + i = 0 + + else + throw new Error( + 'First element of array must be a string, ' + + 'or an array and not ' + JSON.stringify(array[0]) + ) + + + for (; i < array.length; i++) { + + // Don't render element if value is false or null + if (array[i] === false || array[i] === null) { + array[0] = false + break + } + + // Continue with next array value if current value is undefined or true + else if (array[i] === undefined || array[i] === true) { + continue + } + + else if (typeof array[i] === 'string') { + if (doesEscape) + array[i] = escapeHTML(array[i]) + + array[0].children.push(array[i]) + } + + else if (typeof array[i] === 'number') { + + array[0].children.push(array[i]) + } + + else if (Array.isArray(array[i])) { + + if (Array.isArray(array[i][0])) { + array[i].reverse().forEach(function (subArray) { + array.splice(i + 1, 0, subArray) + }) + + if (i !== 0) + continue + i++ + } + + shaven(array[i], namespace, returnObject) + + if (array[i][0]) + array[0].children.push(array[i][0]) + } + + else if (typeof array[i] === 'function') + callback = array[i] + + + else if (typeof array[i] === 'object') { + for (attributeKey in array[i]) + if (array[i].hasOwnProperty(attributeKey)) + if (array[i][attributeKey] !== null && + array[i][attributeKey] !== false) + if (attributeKey === 'style' && + typeof array[i][attributeKey] === 'object') + array[0].attr[attributeKey] = JSON + .stringify(array[i][attributeKey], replacer) + .slice(2, -2) + .replace(/","/g, ';') + .replace(/":"/g, ':') + .replace(/\\"/g, '\'') + + else + array[0].attr[attributeKey] = array[i][attributeKey] + } + + else + throw new TypeError('"' + array[i] + '" is not allowed as a value.') + } + + + if (array[0] !== false) { + + HTMLString = '<' + array[0].tag + + for (key in array[0].attr) + if (array[0].attr.hasOwnProperty(key)) + HTMLString += ' ' + key + '="' + + escapeAttribute(array[0].attr[key]) + '"' + + HTMLString += '>' + + array[0].children.forEach(function (child) { + HTMLString += child + }) + + HTMLString += '' + + array[0] = HTMLString + } + + // Return root element on index 0 + returnObject[0] = array[0] + + if (callback) + callback(array[0]) + + // returns object containing all elements with an id and the root element + return returnObject + } + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + + /*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */ + + 'use strict'; + + /** + * Module variables. + * @private + */ + + var matchHtmlRegExp = /["'&<>]/; + + /** + * Module exports. + * @public + */ + + module.exports = escapeHtml; + + /** + * Escape special characters in the given string of html. + * + * @param {string} string The string to escape for inserting into HTML + * @return {string} + * @public + */ + + function escapeHtml(string) { + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index = 0; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: // " + escape = '"'; + break; + case 38: // & + escape = '&'; + break; + case 39: // ' + escape = '''; + break; + case 60: // < + escape = '<'; + break; + case 62: // > + escape = '>'; + break; + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index + ? html + str.substring(lastIndex, index) + : html; + } + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + var DOM = __webpack_require__(9); + var utils = __webpack_require__(7); + + module.exports = (function() { + var canvas = DOM.newEl('canvas'); + var ctx = null; + + return function(sceneGraph) { + if (ctx == null) { + ctx = canvas.getContext('2d'); + } + + var dpr = utils.canvasRatio(); + var root = sceneGraph.root; + canvas.width = dpr * root.properties.width; + canvas.height = dpr * root.properties.height ; + ctx.textBaseline = 'middle'; + + var bg = root.children.holderBg; + var bgWidth = dpr * bg.width; + var bgHeight = dpr * bg.height; + //todo: parametrize outline width (e.g. in scene object) + var outlineWidth = 2; + var outlineOffsetWidth = outlineWidth / 2; + + ctx.fillStyle = bg.properties.fill; + ctx.fillRect(0, 0, bgWidth, bgHeight); + + if (bg.properties.outline) { + //todo: abstract this into a method + ctx.strokeStyle = bg.properties.outline.fill; + ctx.lineWidth = bg.properties.outline.width; + ctx.moveTo(outlineOffsetWidth, outlineOffsetWidth); + // TL, TR, BR, BL + ctx.lineTo(bgWidth - outlineOffsetWidth, outlineOffsetWidth); + ctx.lineTo(bgWidth - outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, bgHeight - outlineOffsetWidth); + ctx.lineTo(outlineOffsetWidth, outlineOffsetWidth); + // Diagonals + ctx.moveTo(0, outlineOffsetWidth); + ctx.lineTo(bgWidth, bgHeight - outlineOffsetWidth); + ctx.moveTo(0, bgHeight - outlineOffsetWidth); + ctx.lineTo(bgWidth, outlineOffsetWidth); + ctx.stroke(); + } + + var textGroup = root.children.holderTextGroup; + ctx.font = textGroup.properties.font.weight + ' ' + (dpr * textGroup.properties.font.size) + textGroup.properties.font.units + ' ' + textGroup.properties.font.family + ', monospace'; + ctx.fillStyle = textGroup.properties.fill; + + for (var lineKey in textGroup.children) { + var line = textGroup.children[lineKey]; + for (var wordKey in line.children) { + var word = line.children[wordKey]; + var x = dpr * (textGroup.x + line.x + word.x); + var y = dpr * (textGroup.y + line.y + word.y + (textGroup.properties.leading / 2)); + + ctx.fillText(word.properties.text, x, y); + } + } + + return canvas.toDataURL('image/png'); + }; + })(); + +/***/ }) +/******/ ]) +}); +; +(function(ctx, isMeteorPackage) { + if (isMeteorPackage) { + Holder = ctx.Holder; + } +})(this, typeof Meteor !== 'undefined' && typeof Package !== 'undefined'); diff --git a/静态站点/Bootstrap5/plugs/holder/holder.min.js b/静态站点/Bootstrap5/plugs/holder/holder.min.js new file mode 100644 index 0000000..6935bf1 --- /dev/null +++ b/静态站点/Bootstrap5/plugs/holder/holder.min.js @@ -0,0 +1,14 @@ +/*! + +Holder - client side image placeholders +Version 2.9.7+5g5ho +© 2020 Ivan Malopinsky - https://imsky.co + +Site: http://holderjs.com +Issues: https://github.com/imsky/holder/issues +License: MIT + +*/ +!function(e){if(e.document){var t=e.document;t.querySelectorAll||(t.querySelectorAll=function(n){var r,i=t.createElement("style"),a=[];for(t.documentElement.firstChild.appendChild(i),t._qsa=[],i.styleSheet.cssText=n+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",e.scrollBy(0,0),i.parentNode.removeChild(i);t._qsa.length;)r=t._qsa.shift(),r.style.removeAttribute("x-qsa"),a.push(r);return t._qsa=null,a}),t.querySelector||(t.querySelector=function(e){var n=t.querySelectorAll(e);return n.length?n[0]:null}),t.getElementsByClassName||(t.getElementsByClassName=function(e){return e=String(e).replace(/^|\s+/g,"."),t.querySelectorAll(e)}),Object.keys||(Object.keys=function(e){if(e!==Object(e))throw TypeError("Object.keys called on non-object");var t,n=[];for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.push(t);return n}),Array.prototype.forEach||(Array.prototype.forEach=function(e){if(void 0===this||null===this)throw TypeError();var t=Object(this),n=t.length>>>0;if("function"!=typeof e)throw TypeError();var r,i=arguments[1];for(r=0;n>r;r++)r in t&&e.call(i,t[r],r,t)}),function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";e.atob=e.atob||function(e){e=String(e);var n,r=0,i=[],a=0,o=0;if(e=e.replace(/\s/g,""),e.length%4===0&&(e=e.replace(/=+$/,"")),e.length%4===1)throw Error("InvalidCharacterError");if(/[^+\/0-9A-Za-z]/.test(e))throw Error("InvalidCharacterError");for(;r>16&255)),i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a)),o=0,a=0),r+=1;return 12===o?(a>>=4,i.push(String.fromCharCode(255&a))):18===o&&(a>>=2,i.push(String.fromCharCode(a>>8&255)),i.push(String.fromCharCode(255&a))),i.join("")},e.btoa=e.btoa||function(e){e=String(e);var n,r,i,a,o,s,l,h=0,u=[];if(/[^\x00-\xFF]/.test(e))throw Error("InvalidCharacterError");for(;h>2,o=(3&n)<<4|r>>4,s=(15&r)<<2|i>>6,l=63&i,h===e.length+2?(s=64,l=64):h===e.length+1&&(l=64),u.push(t.charAt(a),t.charAt(o),t.charAt(s),t.charAt(l));return u.join("")}}(e),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(e){var t=this.__proto__||this.constructor.prototype;return e in this&&(!(e in t)||t[e]!==this[e])}),function(){if("performance"in e==!1&&(e.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in e.performance==!1){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),e.performance.now=function(){return Date.now()-t}}}(),e.requestAnimationFrame||(e.webkitRequestAnimationFrame&&e.webkitCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return webkitRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.webkitCancelAnimationFrame}(e):e.mozRequestAnimationFrame&&e.mozCancelAnimationFrame?!function(e){e.requestAnimationFrame=function(t){return mozRequestAnimationFrame(function(){t(e.performance.now())})},e.cancelAnimationFrame=e.mozCancelAnimationFrame}(e):!function(e){e.requestAnimationFrame=function(t){return e.setTimeout(t,1e3/60)},e.cancelAnimationFrame=e.clearTimeout}(e))}}(this),function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Holder=t():e.Holder=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){(function(t){function r(e,t,n,r){var o=i(n.substr(n.lastIndexOf(e.domain)),e);o&&a({mode:null,el:r,flags:o,engineSettings:t})}function i(e,t){var n={theme:T(O.settings.themes.gray,null),stylesheets:t.stylesheets,instanceOptions:t},r=e.indexOf("?"),i=[e];-1!==r&&(i=[e.slice(0,r),e.slice(r+1)]);var a=i[0].split("/");n.holderURL=e;var o=a[1],s=o.match(/([\d]+p?)x([\d]+p?)/);if(!s)return!1;if(n.fluid=-1!==o.indexOf("p"),n.dimensions={width:s[1].replace("p","%"),height:s[2].replace("p","%")},2===i.length){var l=v.parse(i[1]);if(w.truthy(l.ratio)){n.fluid=!0;var h=parseFloat(n.dimensions.width.replace("%","")),u=parseFloat(n.dimensions.height.replace("%",""));u=Math.floor(100*(u/h)),h=100,n.dimensions.width=h+"%",n.dimensions.height=u+"%"}if(n.auto=w.truthy(l.auto),l.bg&&(n.theme.bg=w.parseColor(l.bg)),l.fg&&(n.theme.fg=w.parseColor(l.fg)),l.bg&&!l.fg&&(n.autoFg=!0),l.theme&&n.instanceOptions.themes.hasOwnProperty(l.theme)&&(n.theme=T(n.instanceOptions.themes[l.theme],null)),l.text&&(n.text=l.text),l.textmode&&(n.textmode=l.textmode),l.size&&parseFloat(l.size)&&(n.size=parseFloat(l.size)),l.font&&(n.font=l.font),l.align&&(n.align=l.align),l.lineWrap&&(n.lineWrap=l.lineWrap),n.nowrap=w.truthy(l.nowrap),n.outline=w.truthy(l.outline),w.truthy(l.random)){O.vars.cache.themeKeys=O.vars.cache.themeKeys||Object.keys(n.instanceOptions.themes);var d=O.vars.cache.themeKeys[0|Math.random()*O.vars.cache.themeKeys.length];n.theme=T(n.instanceOptions.themes[d],null)}}return n}function a(e){var t=e.mode,n=e.el,r=e.flags,i=e.engineSettings,a=r.dimensions,s=r.theme,l=a.width+"x"+a.height;t=null==t?r.fluid?"fluid":"image":t;var d=/holder_([a-z]+)/g,c=!1;if(null!=r.text&&(s.text=r.text,"object"===n.nodeName.toLowerCase())){for(var f=s.text.split("\\n"),p=0;p1){var b,x=0,A=0,C=0;w=new s.Group("line"+C),("left"===e.align||"right"===e.align)&&(a=e.width*(1-2*(1-r)));for(var E=0;E=a||k===!0)&&(t(g,w,x,g.properties.leading),g.add(w),x=0,A+=g.properties.leading,C+=1,w=new s.Group("line"+C),w.y=A),k!==!0&&(v.moveTo(x,0),x+=m.spaceWidth+T.width,w.add(v))}if(t(g,w,x,g.properties.leading),g.add(w),"left"===e.align)g.moveTo(e.width-i,null,null);else if("right"===e.align){for(b in g.children)w=g.children[b],w.moveTo(e.width-w.width,null,null);g.moveTo(0-(e.width-i),null,null)}else{for(b in g.children)w=g.children[b],w.moveTo((g.width-w.width)/2,null,null);g.moveTo((e.width-g.width)/2,null,null)}g.moveTo(null,(e.height-g.height)/2,null),(e.height-g.height)/2<0&&g.moveTo(null,0,null)}else v=new s.Text(e.text),w=new s.Group("line0"),w.add(v),g.add(w),"left"===e.align?g.moveTo(e.width-i,null,null):"right"===e.align?g.moveTo(0-(e.width-i),null,null):g.moveTo((e.width-m.boundingBox.width)/2,null,null),g.moveTo(null,(e.height-m.boundingBox.height)/2,null);return o}function l(e,t,n,r){var i=parseInt(e,10),a=parseInt(t,10),o=Math.max(i,a),s=Math.min(i,a),l=.8*Math.min(s,o*r);return Math.round(Math.max(n,l))}function h(e){var t;t=null==e||null==e.nodeType?O.vars.resizableImages:[e];for(var n=0,r=t.length;r>n;n++){var i=t[n];if(i.holderData){var a=i.holderData.flags,s=k(i);if(s){if(!i.holderData.resizeUpdate)continue;if(a.fluid&&a.auto){var l=i.holderData.fluidConfig;switch(l.mode){case"width":s.height=s.width/l.ratio;break;case"height":s.width=s.height*l.ratio}}var h={mode:"image",holderSettings:{dimensions:s,theme:a.theme,flags:a},el:i,engineSettings:i.holderData.engineSettings};"exact"==a.textmode&&(a.exactDimensions=s,h.holderSettings.dimensions=a.dimensions),o(h)}else f(i)}}}function u(e){if(e.holderData){var t=k(e);if(t){var n=e.holderData.flags,r={fluidHeight:"%"==n.dimensions.height.slice(-1),fluidWidth:"%"==n.dimensions.width.slice(-1),mode:null,initialDimensions:t};r.fluidWidth&&!r.fluidHeight?(r.mode="width",r.ratio=r.initialDimensions.width/parseFloat(n.dimensions.height)):!r.fluidWidth&&r.fluidHeight&&(r.mode="height",r.ratio=parseFloat(n.dimensions.width)/r.initialDimensions.height),e.holderData.fluidConfig=r}else f(e)}}function d(){var e,n=[],r=Object.keys(O.vars.invisibleImages);r.forEach(function(t){e=O.vars.invisibleImages[t],k(e)&&"img"==e.nodeName.toLowerCase()&&(n.push(e),delete O.vars.invisibleImages[t])}),n.length&&j.run({images:n}),setTimeout(function(){t.requestAnimationFrame(d)},10)}function c(){O.vars.visibilityCheckStarted||(t.requestAnimationFrame(d),O.vars.visibilityCheckStarted=!0)}function f(e){e.holderData.invisibleId||(O.vars.invisibleId+=1,O.vars.invisibleImages["i"+O.vars.invisibleId]=e,e.holderData.invisibleId=O.vars.invisibleId)}function p(e){O.vars.debounceTimer||e.call(this),O.vars.debounceTimer&&t.clearTimeout(O.vars.debounceTimer),O.vars.debounceTimer=t.setTimeout(function(){O.vars.debounceTimer=null,e.call(this)},O.setup.debounce)}function g(){p(function(){h(null)})}var m=n(2),v=n(3),y=n(6),w=n(7),b=n(8),x=n(9),S=n(10),A=n(11),C=n(12),E=n(15),T=w.extend,k=w.dimensionCheck,F=A.svg_ns,j={version:A.version,addTheme:function(e,t){return null!=e&&null!=t&&(O.settings.themes[e]=t),delete O.vars.cache.themeKeys,this},addImage:function(e,t){var n=x.getNodeArray(t);return n.forEach(function(t){var n=x.newEl("img"),r={};r[O.setup.dataAttr]=e,x.setAttr(n,r),t.appendChild(n)}),this},setResizeUpdate:function(e,t){e.holderData&&(e.holderData.resizeUpdate=!!t,e.holderData.resizeUpdate&&h(e))},run:function(e){e=e||{};var n={},o=T(O.settings,e);O.vars.preempted=!0,O.vars.dataAttr=o.dataAttr||O.setup.dataAttr,n.renderer=o.renderer?o.renderer:O.setup.renderer,-1===O.setup.renderers.join(",").indexOf(n.renderer)&&(n.renderer=O.setup.supportsSVG?"svg":O.setup.supportsCanvas?"canvas":"html");var s=x.getNodeArray(o.images),l=x.getNodeArray(o.bgnodes),h=x.getNodeArray(o.stylenodes),u=x.getNodeArray(o.objects);return n.stylesheets=[],n.svgXMLStylesheet=!0,n.noFontFallback=!!o.noFontFallback,n.noBackgroundSize=!!o.noBackgroundSize,h.forEach(function(e){if(e.attributes.rel&&e.attributes.href&&"stylesheet"==e.attributes.rel.value){var t=e.attributes.href.value,r=x.newEl("a");r.href=t;var i=r.protocol+"//"+r.host+r.pathname+r.search;n.stylesheets.push(i)}}),l.forEach(function(e){if(t.getComputedStyle){var r=t.getComputedStyle(e,null).getPropertyValue("background-image"),s=e.getAttribute("data-background-src"),l=s||r,h=null,u=o.domain+"/",d=l.indexOf(u);if(0===d)h=l;else if(1===d&&"?"===l[0])h=l.slice(1);else{var c=l.substr(d).match(/([^\"]*)"?\)/);if(null!==c)h=c[1];else if(0===l.indexOf("url("))throw"Holder: unable to parse background URL: "+l}if(h){var f=i(h,o);f&&a({mode:"background",el:e,flags:f,engineSettings:n})}}}),u.forEach(function(e){var t={};try{t.data=e.getAttribute("data"),t.dataSrc=e.getAttribute(O.vars.dataAttr)}catch(i){}var a=null!=t.data&&0===t.data.indexOf(o.domain),s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain);a?r(o,n,t.data,e):s&&r(o,n,t.dataSrc,e)}),s.forEach(function(e){var t={};try{t.src=e.getAttribute("src"),t.dataSrc=e.getAttribute(O.vars.dataAttr),t.rendered=e.getAttribute("data-holder-rendered")}catch(i){}var a=null!=t.src,s=null!=t.dataSrc&&0===t.dataSrc.indexOf(o.domain),l=null!=t.rendered&&"true"==t.rendered;a?0===t.src.indexOf(o.domain)?r(o,n,t.src,e):s&&(l?r(o,n,t.dataSrc,e):!function(e,t,n,i,a){w.imageExists(e,function(e){e||r(t,n,i,a)})}(t.src,o,n,t.dataSrc,e)):s&&r(o,n,t.dataSrc,e)}),this}},O={settings:{domain:"holder.js",images:"img",objects:"object",bgnodes:"body .holderjs",stylenodes:"head link.holderjs",themes:{gray:{bg:"#EEEEEE",fg:"#AAAAAA"},social:{bg:"#3a5a97",fg:"#FFFFFF"},industrial:{bg:"#434A52",fg:"#C2F200"},sky:{bg:"#0D8FDB",fg:"#FFFFFF"},vine:{bg:"#39DBAC",fg:"#1E292C"},lava:{bg:"#F8591A",fg:"#1C2846"}}},defaults:{size:10,units:"pt",scale:1/16}},z=function(){var e=null,t=null,n=null;return function(r){var i=r.root;if(O.setup.supportsSVG){var a=!1,o=function(e){return document.createTextNode(e)};(null==e||e.parentNode!==document.body)&&(a=!0),e=b.initSVG(e,i.properties.width,i.properties.height),e.style.display="block",a&&(t=x.newEl("text",F),n=o(null),x.setAttr(t,{x:0}),t.appendChild(n),e.appendChild(t),document.body.appendChild(e),e.style.visibility="hidden",e.style.position="absolute",e.style.top="-100%",e.style.left="-100%");var s=i.children.holderTextGroup,l=s.properties;x.setAttr(t,{y:l.font.size,style:w.cssProps({"font-weight":l.font.weight,"font-size":l.font.size+l.font.units,"font-family":l.font.family})});var h=x.newEl("textarea");h.innerHTML=l.text,n.nodeValue=h.value;var u=t.getBBox(),d=Math.ceil(u.width/i.properties.width),c=l.text.split(" "),f=l.text.match(/\\n/g);d+=null==f?0:f.length,n.nodeValue=l.text.replace(/[ ]+/g,"");var p=t.getComputedTextLength(),g=u.width-p,m=Math.round(g/Math.max(1,c.length-1)),v=[];if(d>1){n.nodeValue="";for(var y=0;y=0?t:1)}function a(e){x?i(e):S.push(e)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function C(){document.removeEventListener("DOMContentLoaded",C,!1),document.readyState="complete"},!1),document.readyState="loading");var o=e.document,s=o.documentElement,l="load",h=!1,u="on"+l,d="complete",c="readyState",f="attachEvent",p="detachEvent",g="addEventListener",m="DOMContentLoaded",v="onreadystatechange",y="removeEventListener",w=g in o,b=h,x=h,S=[];if(o[c]===d)i(t);else if(w)o[g](m,n,h),e[g](l,n,h);else{o[f](v,n),e[f](u,n);try{b=null==e.frameElement&&s}catch(A){}b&&b.doScroll&&!function E(){if(!x){try{b.doScroll("left")}catch(e){return i(E,50)}r(),t()}}()}return a.version="1.4.0",a.isReady=function(){return x},a}e.exports="undefined"!=typeof window&&n(window)},function(e,t,n){var r=encodeURIComponent,i=decodeURIComponent,a=n(4),o=n(5),s=/(\w+)\[(\d+)\]/,l=/\w+\.\w+/;t.parse=function(e){if("string"!=typeof e)return{};if(e=a(e),""===e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t={},n=e.split("&"),r=0;r=0;r--)n=e.charCodeAt(r),t.unshift(n>128?["&#",n,";"].join(""):e[r]);return t.join("")},t.imageExists=function(e,t){var n=new Image;n.onerror=function(){t.call(this,!1)},n.onload=function(){t.call(this,!0)},n.src=e},t.decodeHtmlEntity=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})},t.dimensionCheck=function(e){var t={height:e.clientHeight,width:e.clientWidth};return t.height&&t.width?t:!1},t.truthy=function(e){return"string"==typeof e?"true"===e||"yes"===e||"1"===e||"on"===e||"✓"===e:!!e},t.parseColor=function(e){var t,n=/(^(?:#?)[0-9a-f]{6}$)|(^(?:#?)[0-9a-f]{3}$)/i,r=/^rgb\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,i=/^rgba\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0*\.\d{1,}|1)\)$/,a=e.match(n);if(null!==a)return t=a[1]||a[2],"#"!==t[0]?"#"+t:t;if(a=e.match(r),null!==a)return t="rgb("+a.slice(1).join(",")+")";if(a=e.match(i),null!==a){const o=function(e){return"0."+e.split(".")[1]},s=a.slice(1).map(function(e,t){return 3===t?o(e):e});return t="rgba("+s.join(",")+")"}return null},t.canvasRatio=function(){var t=1,n=1;if(e.document){var r=e.document.createElement("canvas");if(r.getContext){var i=r.getContext("2d");t=e.devicePixelRatio||1,n=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1}}return t/n}}).call(t,function(){return this}())},function(e,t,n){(function(e){var r=n(9),i="http://www.w3.org/2000/svg",a=8;t.initSVG=function(e,t,n){var o,s,l=!1;e&&e.querySelector?(s=e.querySelector("style"),null===s&&(l=!0)):(e=r.newEl("svg",i),l=!0),l&&(o=r.newEl("defs",i),s=r.newEl("style",i),r.setAttr(s,{type:"text/css"}),o.appendChild(s),e.appendChild(o)),e.webkitMatchesSelector&&e.setAttribute("xmlns",i);for(var h=0;h=0;l--){var h=s.createProcessingInstruction("xml-stylesheet",'href="'+o[l]+'" rel="stylesheet"');s.insertBefore(h,s.firstChild)}s.removeChild(s.documentElement),a=i.serializeToString(s)}var u=i.serializeToString(t);return u=u.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),a+u}}}).call(t,function(){return this}())},function(e,t){(function(e){t.newEl=function(t,n){return e.document?null==n?e.document.createElement(t):e.document.createElementNS(n,t):void 0},t.setAttr=function(e,t){for(var n in t)e.setAttribute(n,t[n])},t.createXML=function(){return e.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0},t.getNodeArray=function(t){var n=null;return"string"==typeof t?n=document.querySelectorAll(t):e.NodeList&&t instanceof e.NodeList?n=t:e.Node&&t instanceof e.Node?n=[t]:e.HTMLCollection&&t instanceof e.HTMLCollection?n=t:t instanceof Array?n=t:null===t&&(n=[]),n=Array.prototype.slice.call(n)}}).call(t,function(){return this}())},function(e,t){var n=function(e,t){"string"==typeof e&&(this.original=e,"#"===e.charAt(0)&&(e=e.slice(1)),/[^a-f0-9]+/i.test(e)||(3===e.length&&(e=e.replace(/./g,"$&$&")),6===e.length&&(this.alpha=1,t&&t.alpha&&(this.alpha=t.alpha),this.set(parseInt(e,16)))))};n.rgb2hex=function(e,t,n){function r(e){var t=(0|e).toString(16);return 16>e&&(t="0"+t),t}return[e,t,n].map(r).join("")},n.hsl2rgb=function(e,t,n){var r=e/60,i=(1-Math.abs(2*n-1))*t,a=i*(1-Math.abs(parseInt(r)%2-1)),o=n-i/2,s=0,l=0,h=0;return r>=0&&1>r?(s=i,l=a):r>=1&&2>r?(s=a,l=i):r>=2&&3>r?(l=i,h=a):r>=3&&4>r?(l=a,h=i):r>=4&&5>r?(s=a,h=i):r>=5&&6>r&&(s=i,h=a),s+=o,l+=o,h+=o,s=parseInt(255*s),l=parseInt(255*l),h=parseInt(255*h),[s,l,h]},n.prototype.set=function(e){this.raw=e;var t=(16711680&this.raw)>>16,n=(65280&this.raw)>>8,r=255&this.raw,i=.2126*t+.7152*n+.0722*r,a=-.09991*t-.33609*n+.436*r,o=.615*t-.55861*n-.05639*r;return this.rgb={r:t,g:n,b:r},this.yuv={y:i,u:a,v:o},this},n.prototype.lighten=function(e){var t=Math.min(1,Math.max(0,Math.abs(e)))*(0>e?-1:1),r=255*t|0,i=Math.min(255,Math.max(0,this.rgb.r+r)),a=Math.min(255,Math.max(0,this.rgb.g+r)),o=Math.min(255,Math.max(0,this.rgb.b+r)),s=n.rgb2hex(i,a,o);return new n(s)},n.prototype.toHex=function(e){return(e?"#":"")+this.raw.toString(16)},n.prototype.lighterThan=function(e){return e instanceof n||(e=new n(e)),this.yuv.y>e.yuv.y},n.prototype.blendAlpha=function(e){e instanceof n||(e=new n(e));var t=e,r=this,i=t.alpha*t.rgb.r+(1-t.alpha)*r.rgb.r,a=t.alpha*t.rgb.g+(1-t.alpha)*r.rgb.g,o=t.alpha*t.rgb.b+(1-t.alpha)*r.rgb.b;return new n(n.rgb2hex(i,a,o))},e.exports=n},function(e,t){e.exports={version:"2.9.7",svg_ns:"http://www.w3.org/2000/svg"}},function(e,t,n){function r(e,t){return d.element({tag:t,width:e.width,height:e.height,fill:e.properties.fill})}function i(e){return h.cssProps({fill:e.fill,"font-weight":e.font.weight,"font-family":e.font.family+", monospace","font-size":e.font.size+e.font.units})}function a(e,t,n){var r=n/2;return["M",r,r,"H",e-r,"V",t-r,"H",r,"V",0,"M",0,r,"L",e,t-r,"M",0,t-r,"L",e,r].join(" ")}var o=n(13),s=n(8),l=n(11),h=n(7),u=l.svg_ns,d={element:function(e){var t=e.tag,n=e.content||"";return delete e.tag,delete e.content,[t,n,e]}};e.exports=function(e,t){var n=t.engineSettings,l=n.stylesheets,h=l.map(function(e){return''}).join("\n"),c="holder_"+Number(new Date).toString(16),f=e.root,p=f.children.holderTextGroup,g="#"+c+" text { "+i(p.properties)+" } ";p.y+=.8*p.textPositionData.boundingBox.height;var m=[];Object.keys(p.children).forEach(function(e){var t=p.children[e];Object.keys(t.children).forEach(function(e){var n=t.children[e],r=p.x+t.x+n.x,i=p.y+t.y+n.y,a=d.element({tag:"text",content:n.properties.text,x:r,y:i});m.push(a)})});var v=d.element({tag:"g",content:m}),y=null;if(f.children.holderBg.properties.outline){var w=f.children.holderBg.properties.outline;y=d.element({tag:"path",d:a(f.children.holderBg.width,f.children.holderBg.height,w.width),"stroke-width":w.width,stroke:w.fill,fill:"none"})}var b=r(f.children.holderBg,"rect"),x=[];x.push(b),w&&x.push(y),x.push(v);var S=d.element({tag:"g",id:c,content:x}),A=d.element({tag:"style",content:g,type:"text/css"}),C=d.element({tag:"defs",content:A}),E=d.element({tag:"svg",content:[C,S],width:f.properties.width,height:f.properties.height,xmlns:u,viewBox:[0,0,f.properties.width,f.properties.height].join(" "),preserveAspectRatio:"none"}),T=o(E);/\&(x)?#[0-9A-Fa-f]/.test(T[0])&&(T[0]=T[0].replace(/&#/gm,"&#")),T=h+T[0];var k=s.svgStringToDataURI(T,"background"===t.mode);return k}},function(e,t,n){n(14);e.exports=function r(e,t,n){"use strict";function i(e){var t=e.match(/^[\w-]+/),r={tag:t?t[0]:"div",attr:{},children:[]},i=e.match(/#([\w-]+)/),a=e.match(/\$([\w-]+)/),o=e.match(/\.[\w-]+/g);return i&&(r.attr.id=i[1],n[i[1]]=r),a&&(n[a[1]]=r),o&&(r.attr["class"]=o.join(" ").replace(/\./g,"")),e.match(/&$/g)&&(f=!1),r}function a(e,t){return null!==t&&t!==!1&&void 0!==t?"string"!=typeof t&&"object"!=typeof t?String(t):t:void 0}function o(e){return e||0===e?String(e).replace(/&/g,"&").replace(/"/g,"""):""}function s(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}var l,h,u,d,c=1,f=!0;if(n=n||{},"string"==typeof e[0])e[0]=i(e[0]);else{if(!Array.isArray(e[0]))throw new Error("First element of array must be a string, or an array and not "+JSON.stringify(e[0]));c=0}for(;c",e[0]=l}return n[0]=e[0],u&&u(e[0]),n}},function(e,t){"use strict";function n(e){var t=""+e,n=r.exec(t);if(!n)return t;var i,a="",o=0,s=0;for(o=n.index;o]/;e.exports=n},function(e,t,n){var r=n(9),i=n(7);e.exports=function(){var e=r.newEl("canvas"),t=null;return function(n){null==t&&(t=e.getContext("2d"));var r=i.canvasRatio(),a=n.root;e.width=r*a.properties.width,e.height=r*a.properties.height,t.textBaseline="middle";var o=a.children.holderBg,s=r*o.width,l=r*o.height,h=2,u=h/2;t.fillStyle=o.properties.fill,t.fillRect(0,0,s,l),o.properties.outline&&(t.strokeStyle=o.properties.outline.fill,t.lineWidth=o.properties.outline.width,t.moveTo(u,u),t.lineTo(s-u,u),t.lineTo(s-u,l-u),t.lineTo(u,l-u),t.lineTo(u,u),t.moveTo(0,u),t.lineTo(s,l-u),t.moveTo(0,l-u),t.lineTo(s,u),t.stroke());var d=a.children.holderTextGroup;t.font=d.properties.font.weight+" "+r*d.properties.font.size+d.properties.font.units+" "+d.properties.font.family+", monospace",t.fillStyle=d.properties.fill;for(var c in d.children){var f=d.children[c];for(var p in f.children){var g=f.children[p],m=r*(d.x+f.x+g.x),v=r*(d.y+f.y+g.y+d.properties.leading/2); + +t.fillText(g.properties.text,m,v)}}return e.toDataURL("image/png")}}()}])}),function(e,t){t&&(Holder=e.Holder)}(this,"undefined"!=typeof Meteor&&"undefined"!=typeof Package); \ No newline at end of file