修正拍照时图片的方向
ref to http://stackoverflow.com/questions/19463126/how-to-draw-photo-with-correct-orientation-in-canvas-after-capture-photo-by-usin
541096
function orientationHelper(canvas, ctx, orientation) {
    const w = canvas.width, h = canvas.height;
    if(orientation > 4){
        canvas.width = h;
        canvas.height = w;
    }
    switch (orientation) {
        case 2:
            ctx.translate(w, 0);
            ctx.scale(-1, 1);
            break;
        case 3:
            ctx.translate(w, h);
            ctx.rotate(Math.PI);
            break;
        case 4:
            ctx.translate(0, h);
            ctx.scale(1, -1);
            break;
        case 5:
            ctx.rotate(0.5 * Math.PI);
            ctx.scale(1, -1);
            break;
        case 6:
            ctx.rotate(0.5 * Math.PI);
            ctx.translate(0, -h);
            break;
        case 7:
            ctx.rotate(0.5 * Math.PI);
            ctx.translate(w, -h);
            ctx.scale(-1, 1);
            break;
        case 8:
            ctx.rotate(-0.5 * Math.PI);
            ctx.translate(-w, 0);
            break;
    }
}
1114608
function mergeShape(decoration, vLine, hLine) {
                var decoBox = decoration.getFixRenderBox(), vLineBox = vLine.getFixRenderBox();
                vLine.translate(decoBox.width - sin15 * SHAPE_DATA_WIDTH * 3, 0);
                decoration.translate(0, vLineBox.height - decoBox.height);
                vLineBox = vLine.getFixRenderBox();
                hLine.translate(vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, 0);
                // 返回关键点数据
                return {
                    x: vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15,
                    y: 0
                };
            }
572710
function processNodeRule (nodeRule, imageReplaces, coll2x, coll3x) {
    var img, imgKey, __url
    _.each(nodeRule.declarations, function(e){
        if(e.property == 'background-image'){
            __url = __getURL(e.value)
            img = img || imageReplaces[__url]
            imgKey = img? __url: imgKey
        }
    })
    if(!img) return
    // 修改节点
    updateNodeByMerge(nodeRule, __generatorCSSObj(img))
    // 更新2x 3x 收集器
    updateCollectMX(imgKey, imageReplaces, nodeRule.selectors, coll2x, coll3x)

    function __getURL(bgURL){
        return _.trim(bgURL.split('url').join(''), '()"\'')
    }
    function __generatorCSSObj(img){
        return {
            "background-image": "url("+img.sprite+")",
            "background-position":  "-"+img.x+"px -"+img.y+"px"
        }
    }
}
82095
function transfromAliapp(node) {
  const attrs = node.attrs || {}
  if (node.tag === 'icon') {
    const iconTypeNoSupport = ['circle', 'info_circle']
    if (iconTypeNoSupport.includes(attrs.type)) {
      console.warn(`支付宝小程序 <icon> 不支持 type: ${attrs.type}, 会导致页面不渲染。`)
    }
  }
  if (node.tag === 'scroll-view') {
    const nameMapping = {
      bindscrolltoupper: 'onScrollToUpper',
      bindscrolltolower: 'onScrollToLower'
    }
    replaceAttrNames(nameMapping)
  }

  if (node.tag === 'picker-view') {
    const nameMapping = {
      'indicator-style': 'indicatorStyle'
    }
    replaceAttrNames(nameMapping)
  }

  if (node.tag === 'slider') {
    const nameMapping = {
      'block-size': 'handleSize',
      'block-color': 'handleColor'
    }
    replaceAttrNames(nameMapping)
  }

  if (node.tag === 'image') {
    const nameMapping = {
      'lazy-load': 'lazyLoad'
    }
    replaceAttrNames(nameMapping)
  }

  if (node.tag === 'canvas') {
    const nameMapping = {
      'canvas-id': 'id'
    }
    replaceAttrNames(nameMapping)
  }

  if (node.tag === 'map') {
    const nameMapping = {
      'bindmarkertap': 'onMarkerTap',
      'bindcallouttap': 'onCalloutTap',
      'bindcontroltap': 'onControlTap',
      'bindregionchange': 'onRegionChange'
    }
    replaceAttrNames(nameMapping)
  }

  return node

  function replaceAttrNames(nameMapping) {
    Object.keys(nameMapping).forEach(name => {
      const value = attrs[name]
      if (value) {
        attrs[nameMapping[name]] = value;
        delete attrs[name];
      }
    })
  }
}
1166822
function(csspath) {
        var self = this;

        /**
         * 获取文件内容
         * @type {String}
         */
        var content = grunt.file.read(csspath);

        /**
         * 匹配
         * 1. url(a.png)
         * 2. url('http://i1.static.dp/s/c/i/b.png')
         * 3. url("./c.png")
         */
        var reg = /url\(\s*(['"]?)([^"'\)]*)\1\s*\)/g;

        /**
         * 用以标识文件是否有修改
         * 有修改为1，反之为0
         */
        // var changed = 0;

        /**
         * 返回所有匹配
         * 例：matches[0] 为 "url(a.png)"
         */
        var matches = {};

        var m;

        /**
         * 涉及的所有图片路径
         * @type {Array}
         */
        var image_paths = [];

        /**
         * 判断路径是否为相对路径
         * 例：  http://i2.static.dp/s/c/i/a.png 返回 true
         *      c/i/a.png 返回false
         */

        function isRelative(imgpath) {
            return !/^http:\/\//.test(imgpath);
        }

        /**
         * 将文件content中的相对地址替换为绝对地址
         */
        function replaceMatch(match,i) {
            /**
             * 匹配 url('path/to/image.png')
             * 中的 path/to/image.png
             */

            var reg = /\(\s*(['"]?)([^'"\)]*)\1\s*\)/,
                parsed = "",
                imgpath = match.match(reg)[2],
                parsed_url;

            /**
             * 若非相对路径则取得其相对路径进行parse
             */
            parsed = self.calculateImagePath(csspath,imgpath,!isRelative(imgpath));

            if(!parsed){
                return;
            }
            // image_paths.push((parsed.name+parsed.ext).substr(1));

            parsed_url = "url(" + self.connector(parsed) + ")";

            if(parsed_url !== match){
                matches[match] = parsed_url;
            }
        }


        while(m = reg.exec(content)){
            replaceMatch(m[0]);
        }

        var key_regx;
        for(var key in matches){
            key_regx = key.replace(/([\.\?\*\+\$\[\]\\\(\)\{\}\-\/])/g, "\\$1");
            key_regx = new RegExp(key_regx,"g");
            content = content.replace(key_regx,matches[key]);
        }

        /**
         * 循环处理所有匹配
         */
        // matches && matches.forEach(replaceMatch);

        return content;
    }
1187227
function (_this) {
    var menuLeft;
    var menuTop;

    // 菜单位置和方向
    var position;
    var align;

    // window 窗口的宽度和高度
    var windowHeight = $window.height();
    var windowWidth = $window.width();

    // 配置参数
    var gutter = _this.options.gutter;
    var isCovered = _this.isCovered;
    var isFixed = _this.options.fixed;

    // 动画方向参数
    var transformOriginX;
    var transformOriginY;

    // 菜单的原始宽度和高度
    var menuWidth = _this.$menu.width();
    var menuHeight = _this.$menu.height();

    var $anchor = _this.$anchor;

    // 触发菜单的元素在窗口中的位置
    var anchorTmp = $anchor[0].getBoundingClientRect();
    var anchorTop = anchorTmp.top;
    var anchorLeft = anchorTmp.left;
    var anchorHeight = anchorTmp.height;
    var anchorWidth = anchorTmp.width;
    var anchorBottom = windowHeight - anchorTop - anchorHeight;
    var anchorRight = windowWidth - anchorLeft - anchorWidth;

    // 触发元素相对其拥有定位属性的父元素的位置
    var anchorOffsetTop = $anchor[0].offsetTop;
    var anchorOffsetLeft = $anchor[0].offsetLeft;

    // ===============================
    // ================= 自动判断菜单位置
    // ===============================
    if (_this.options.position === 'auto') {

      // 判断下方是否放得下菜单
      if (anchorBottom + (isCovered ? anchorHeight : 0) > menuHeight + gutter) {
        position = 'bottom';
      }

      // 判断上方是否放得下菜单
      else if (anchorTop + (isCovered ? anchorHeight : 0) > menuHeight + gutter) {
        position = 'top';
      }

      // 上下都放不下，居中显示
      else {
        position = 'center';
      }
    } else {
      position = _this.options.position;
    }

    // ===============================
    // ============== 自动判断菜单对齐方式
    // ===============================
    if (_this.options.align === 'auto') {

      // 判断右侧是否放得下菜单
      if (anchorRight + anchorWidth > menuWidth + gutter) {
        align = 'left';
      }

      // 判断左侧是否放得下菜单
      else if (anchorLeft + anchorWidth > menuWidth + gutter) {
        align = 'right';
      }

      // 左右都放不下，居中显示
      else {
        align = 'center';
      }
    } else {
      align = _this.options.align;
    }

    // ===============================
    // ==================== 设置菜单位置
    // ===============================
    if (position === 'bottom') {
      transformOriginY = '0';

      menuTop =
        (isCovered ? 0 : anchorHeight) +
        (isFixed ? anchorTop : anchorOffsetTop);

    } else if (position === 'top') {
      transformOriginY = '100%';

      menuTop =
        (isCovered ? anchorHeight : 0) +
        (isFixed ? (anchorTop - menuHeight) : (anchorOffsetTop - menuHeight));

    } else {
      transformOriginY = '50%';

      // =====================在窗口中居中
      // 显示的菜单的高度，简单菜单高度不超过窗口高度，若超过了则在菜单内部显示滚动条
      // 级联菜单内部不允许出现滚动条
      var menuHeightTemp = menuHeight;

      // 简单菜单比窗口高时，限制菜单高度
      if (!_this.isCascade) {
        if (menuHeight + gutter * 2 > windowHeight) {
          menuHeightTemp = windowHeight - gutter * 2;
          _this.$menu.height(menuHeightTemp);
        }
      }

      menuTop =
        (windowHeight - menuHeightTemp) / 2 +
        (isFixed ? 0 : (anchorOffsetTop - anchorTop));
    }

    _this.$menu.css('top', menuTop + 'px');

    // ===============================
    // ================= 设置菜单对齐方式
    // ===============================
    if (align === 'left') {
      transformOriginX = '0';

      menuLeft = isFixed ? anchorLeft : anchorOffsetLeft;

    } else if (align === 'right') {
      transformOriginX = '100%';

      menuLeft = isFixed ?
        (anchorLeft + anchorWidth - menuWidth) :
        (anchorOffsetLeft + anchorWidth - menuWidth);
    } else {
      transformOriginX = '50%';

      //=======================在窗口中居中
      // 显示的菜单的宽度，菜单宽度不能超过窗口宽度
      var menuWidthTemp = menuWidth;

      // 菜单比窗口宽，限制菜单宽度
      if (menuWidth + gutter * 2 > windowWidth) {
        menuWidthTemp = windowWidth - gutter * 2;
        _this.$menu.width(menuWidthTemp);
      }

      menuLeft =
        (windowWidth - menuWidthTemp) / 2 +
        (isFixed ? 0 : anchorOffsetLeft - anchorLeft);
    }

    _this.$menu.css('left', menuLeft + 'px');

    // 设置菜单动画方向
    _this.$menu.transformOrigin(transformOriginX + ' ' + transformOriginY);
  }
121474
function(_style){
            var _list  = _style.split(':'),
                _prop  = _list[0],
                _value = _list[1],
                _node  = this.__node;
            // 需要解析=号
            if(_value.indexOf('=') > -1){
                var _a = parseInt(_e._$getStyle(_node,_prop))||0;
                var _b = parseInt(_value.split('=')[1]);
                if(_value.indexOf('+') > -1)
                    _value = _a + _b;
                else
                    _value = _a - _b;
            }
            // 需要加单位
            if(_h.__doCheckProp(_prop)){
                if(_value.toString().indexOf('px') < 0)
                    _value += 'px';
            }
            this.__propMap[_prop] = _value;
        }
1028202
function (cfg) {
    this._cfg = merge({
      delay: 400
    }, cfg)

    // 事件订阅数组
    this._subs = {
      on: [],
      after: []
    }

    // 当前信息
    this.info = this.getInfo()

    // 绑定事件回调上下文
    this._onWinOrientationChange = bind(this._onWinOrientationChange, this)

    // 绑定窗口切换事件
    window.addEventListener(EVT_ORIENTATION_CHANGE, this._onWinOrientationChange, false)
  }
1144580
function fixOldRadialGradient (args) {
	let position = args[0];
	if (position && position[0] && position[1]) {
		// 第一个参数为坐标，则将这个参数中的值的单位转换为px
		position = position.map(px);
		// 在坐标参数最前面添加`at`关键字
		position.unshift("at");

		const size = args[3] && args[3][0];
		if (size != null) {
			// 将尺寸信息加入结果集
			position.unshift(px(size));
		}
		// 返回结果
		return position;
	}
}
1006796
function (_this) {
    // 抽屉栏滑动手势控制
    var openNavEventHandler;
    var touchStartX;
    var touchStartY;
    var swipeStartX;
    var swiping = false;
    var maybeSwiping = false;
    var $body = $('body');

    // 手势触发的范围
    var swipeAreaWidth = 24;

    function enableSwipeHandling() {
      if (!openNavEventHandler) {
        $body.on('touchstart', onBodyTouchStart);
        openNavEventHandler = onBodyTouchStart;
      }
    }

    function setPosition(translateX, closeTransform) {
      var rtlTranslateMultiplier = _this.position === 'right' ? -1 : 1;
      var transformCSS = 'translate(' + (-1 * rtlTranslateMultiplier * translateX) + 'px, 0) !important;';
      _this.$drawer.css(
        'cssText',
        'transform:' + transformCSS + (closeTransform ? 'transition: initial !important;' : '')
      );
    }

    function cleanPosition() {
      _this.$drawer.css({
        transform: '',
        transition: '',
      });
    }

    function getMaxTranslateX() {
      return _this.$drawer.width() + 10;
    }

    function getTranslateX(currentX) {
      return Math.min(
        Math.max(
          swiping === 'closing' ? (swipeStartX - currentX) : (getMaxTranslateX() + swipeStartX - currentX),
          0
        ),
        getMaxTranslateX()
      );
    }

    function onBodyTouchStart(event) {
      touchStartX = event.touches[0].pageX;
      if (_this.position === 'right') {
        touchStartX = $body.width() - touchStartX;
      }

      touchStartY = event.touches[0].pageY;

      if (_this.state !== 'opened') {
        if (touchStartX > swipeAreaWidth || openNavEventHandler !== onBodyTouchStart) {
          return;
        }
      }

      maybeSwiping = true;

      $body.on({
        touchmove: onBodyTouchMove,
        touchend: onBodyTouchEnd,
        touchcancel: onBodyTouchMove,
      });
    }

    function onBodyTouchMove(event) {
      var touchX = event.touches[0].pageX;
      if (_this.position === 'right') {
        touchX = $body.width() - touchX;
      }

      var touchY = event.touches[0].pageY;

      if (swiping) {
        setPosition(getTranslateX(touchX), true);
      } else if (maybeSwiping) {
        var dXAbs = Math.abs(touchX - touchStartX);
        var dYAbs = Math.abs(touchY - touchStartY);
        var threshold = 8;

        if (dXAbs > threshold && dYAbs <= threshold) {
          swipeStartX = touchX;
          swiping = _this.state === 'opened' ? 'closing' : 'opening';
          $.lockScreen();
          setPosition(getTranslateX(touchX), true);
        } else if (dXAbs <= threshold && dYAbs > threshold) {
          onBodyTouchEnd();
        }
      }
    }

    function onBodyTouchEnd(event) {
      if (swiping) {
        var touchX = event.changedTouches[0].pageX;
        if (_this.position === 'right') {
          touchX = $body.width() - touchX;
        }

        var translateRatio = getTranslateX(touchX) / getMaxTranslateX();

        maybeSwiping = false;
        var swipingState = swiping;
        swiping = null;

        if (swipingState === 'opening') {
          if (translateRatio < 0.92) {
            cleanPosition();
            _this.open();
          } else {
            cleanPosition();
          }
        } else {
          if (translateRatio > 0.08) {
            cleanPosition();
            _this.close();
          } else {
            cleanPosition();
          }
        }

        $.unlockScreen();
      } else {
        maybeSwiping = false;
      }

      $body.off({
        touchmove: onBodyTouchMove,
        touchend: onBodyTouchEnd,
        touchcancel: onBodyTouchMove,
      });
    }

    if (_this.options.swipe) {
      enableSwipeHandling();
    }
  }
840476
function getBackgroundImageUrl(jqCur, jqContainer) {
    var computedStyle = getStyle(jqCur, jqContainer).computedStyle;

    if (!computedStyle) {
        return '';
    }

    // 这里不能够直接使用jQuery获取style的方式，因为有可能这个并没有写在其中

    // 获得 background-image 的设置，例如 'url("https://pic.url.cn/hy_personal_room/1210697536/12106975361512129362/640")';
    var backgroundImage = computedStyle.backgroundImage;

    // 正则匹配找出实际的 url 地址，例如 https://pic.url.cn/hy_personal_room/1210697536/12106975361512129362/640
    var matchResult = backgroundImage.match(/url\("(.*)"\)/) || [];

    return matchResult[1] || '';
}
1270528
function fixRadialGradient (args) {
	let firstArg = [];
	let position;

	// 分析所有参数，将坐标参数和关键字剔除出args并单独保存
	args = args.filter((subArg) => {
		let hasKeyWord;
		subArg.forEach((word, i) => {
			if (keyWordMap[word]) {
				// 查找需要转换的关键字
				subArg[i] = keyWordMap[word];
				hasKeyWord = true;
			} else if (/^(?:circle|ellipse|\w+-\w+)$/.test(word)) {
				// 查找是否有其他的关键字
				hasKeyWord = true;
			}
		});
		if (hasKeyWord) {
			// subArg中如果有关键字，将它存入firstArg
			firstArg = firstArg.concat(subArg);
			return false;
		} else if (subArg.every((word) => {
			return word === "center" || directionMap[word] || parseNum(word);
		})) {
			// 如果subArg是坐标信息将它存入position
			position = subArg;
			return false;
		}
		return true;
	});

	if (position) {
		// 在坐标参数最前面添加`at`关键字
		position.unshift("at");
		firstArg = firstArg.concat(position);
	}

	if (firstArg.length) {
		// 如果收集到了firstArg，将其加入args的最前面
		args.unshift(firstArg);
	}

	return args;
}
1244824
function(points, panLines, smoothFactor) {

                var result = {};

                Utils.each(points, function(point, index) {

                    //当前平移线
                    var currentPanLine = panLines[index],
                        //平移线中点
                        center = currentPanLine.center,

                        //移动距离
                        distance = {
                            x: center.x - point.x,
                            y: center.y - point.y
                        };

                    var currentResult = result[index] = {
                        points: [],
                        center: {
                            x: point.x,
                            y: point.y
                        }
                    };

                    //计算控制点到顶点的距离， 并且应用平滑系数到距离上
                    Utils.each(currentPanLine.points, function(controlPoint, index) {
                        var moved = {
                            x: controlPoint.x - distance.x,
                            y: controlPoint.y - distance.y
                        };
                        var vertex = currentResult.center;
                        var dx = moved.x - vertex.x;
                        var dy = moved.y - vertex.y;
                        moved.x = vertex.x + smoothFactor * dx;
                        moved.y = vertex.y + smoothFactor * dy;
                        currentResult.points.push(moved);
                    });

                });

                return result;

            }
67073
function generateImage({
    fontSize = null,
    color = '#fff',
    background = '#616161',
    text = '',
    size = [600, 200],
  }) {
    const width = size[0],
      height = size[1],
      fontFamily = 'sans-serif';

    if (!fontSize) { // 取宽度的 1/8
      fontSize = (width / 8).toFixed();
    }
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    canvas.width = width;
    canvas.height = height;
    ctx.fillStyle = background;
    ctx.fillRect(0, 0, width, height);

    // 背景上设置小点
    ctx.fillStyle = contrast(background);
    const pointX = width / 2;
    const pointY = height / 2;
    for (let i = 0; i < pointY; i++) {
      for (let j = 0; j < pointX; j++) {
        ctx.fillRect(i * 20 + 9, j * 20 + 9, 2, 2);
      }
    }

    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillStyle = color;
    ctx.font = `bold ${fontSize}px ${fontFamily}`;
    ctx.fillText(text, (width / 2), (height / 2), width);

    return canvas.toDataURL('image/png');
  }
819614
function() {
                // 获取现有颜色映射
                //     resource => color_index
                var colorMapping = this._getResourceColorIndexMapping();

                var resource, used, i;

                used = [];

                // 抽取已经使用的值到 used 数组
                for (resource in colorMapping) {
                    if (Object.prototype.hasOwnProperty.call(colorMapping, resource)) {
                        used.push(colorMapping[resource]);
                    }
                }

                // 枚举所有的可用值，如果还没被使用，返回
                for (i = 0; i < RESOURCE_COLOR_SERIES.length; i++) {
                    if (!~used.indexOf(i)) return i;
                }

                // 没有可用的颜色了
                return -1;
            }
702746
public static void createImage(String str, Font font, Color backgroundColor, Color fontColor, ImageOutputStream out) throws IORuntimeException {
		// 获取font的样式应用在str上的整个矩形
		Rectangle2D r = font.getStringBounds(str, new FontRenderContext(AffineTransform.getScaleInstance(1, 1), false, false));
		int unitHeight = (int) Math.floor(r.getHeight());// 获取单个字符的高度
		// 获取整个str用了font样式的宽度这里用四舍五入后+1保证宽度绝对能容纳这个字符串作为图片的宽度
		int width = (int) Math.round(r.getWidth()) + 1;
		int height = unitHeight + 3;// 把单个字符的高度+3保证高度绝对能容纳字符串作为图片的高度
		// 创建图片
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
		Graphics g = image.getGraphics();
		g.setColor(backgroundColor);
		g.fillRect(0, 0, width, height);// 先用背景色填充整张图片,也就是背景
		g.setColor(fontColor);
		g.setFont(font);// 设置画笔字体
		g.drawString(str, 0, font.getSize());// 画出字符串
		g.dispose();
		writePng(image, out);
	}
82756
function transformAliappEventAttr(node) {
  var attrs = node.attrs;
  if (!attrs) return node;
  var commonEventMapping = {
    touchstart: 'TouchStart',
    touchmove: 'TouchMove',
    touchend: 'TouchEnd',
    touchcancel: 'TouchCancel',
    longtap: 'LongTap'
  };
  // capture-bind:* , capture-catch:* 支付宝不支持所以忽略
  Object.keys(attrs).forEach(function (key) {
    var matches = key.match(MATCH_EVENT_ATTR);
    if (!matches) return;

    var _matches = _slicedToArray(matches, 3),
        g = _matches[0],
        eventStartKey = _matches[1],
        eventName = _matches[2];
    // bind:* , bindtap => onTap
    // catch:* , catchtap => catchTap


    var evtName = commonEventMapping[eventName];
    if (!evtName) {
      evtName = eventName[0].toUpperCase() + eventName.slice(1);
    }
    var attr = 'on' + evtName;
    var value = attrs[key];
    attrs[attr] = value === '' ? true : value;
    delete attrs[key];
  });
  return node;
}