网页截屏

将选中元素截屏

// ==UserScript==
// @name         网页截屏
// @namespace    https://github.com/CListery
// @version      0.9
// @description  将选中元素截屏
// @license      MIT
// @author       CListery
// @require      https://cdn.jsdelivr.net/npm/html2canvas@1/dist/html2canvas.min.js
// @require      https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js
// @require      https://cdn.jsdelivr.net/npm/luna-dom-highlighter@1.0.2/luna-dom-highlighter.js
// @resource     lunaDomHighlighterCSS  https://cdn.jsdelivr.net/npm/luna-dom-highlighter/luna-dom-highlighter.css
// @match        *://*/*
// @icon         data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjMuMiIvPgogICAgPHBhdGggZD0iTTkgMkw3LjE3IDRINGMtMS4xIDAtMiAuOS0yIDJ2MTJjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yaC0zLjE3TDE1IDJIOXptMyAxNWMtMi43NiAwLTUtMi4yNC01LTVzMi4yNC01IDUtNSA1IDIuMjQgNSA1LTIuMjQgNS01IDV6Ii8+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPgo=
// @grant        GM.getResourceUrl
// @grant        GM.getResourceText
// @grant        GM_getResourceText
// ==/UserScript==

;(function () {
    'use strict',
      // licia libraries
      // Built by eustia.
      // included: h toBool evalCss root cssSupports $ contain defaults
      (function (root, factory) {
        if (typeof define === 'function' && define.amd) {
          define([], factory)
        } else if (typeof module === 'object' && module.exports) {
          module.exports = factory()
        } else {
          root._licia = factory()
        }
      })(this, function () {
        /* eslint-disable */
  
        var _licia = {}
  
        if (typeof window === 'object' && window._licia) _licia = window._licia
  
        /* ------------------------------ last ------------------------------ */
  
        var last = (_licia.last = (function (exports) {
          /* Get the last element of array.
           *
           * |Name  |Desc                     |
           * |------|-------------------------|
           * |arr   |The array to query       |
           * |return|The last element of array|
           */
  
          /* example
           * last([1, 2]); // -> 2
           */
  
          /* typescript
           * export declare function last(arr: any[]): any;
           */
  
          exports = function (arr) {
            var len = arr ? arr.length : 0
            if (len) return arr[len - 1]
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isUndef ------------------------------ */
  
        var isUndef = (_licia.isUndef = (function (exports) {
          /* Check if value is undefined.
           *
           * |Name  |Desc                      |
           * |------|--------------------------|
           * |val   |Value to check            |
           * |return|True if value is undefined|
           */
  
          /* example
           * isUndef(void 0); // -> true
           * isUndef(null); // -> false
           */
  
          /* typescript
           * export declare function isUndef(val: any): val is undefined;
           */
  
          exports = function (val) {
            return val === void 0
          }
  
          return exports
        })({}))
  
        /* ------------------------------ types ------------------------------ */
  
        var types = (_licia.types = (function (exports) {
          /* Used for typescript definitions only.
           */
  
          /* typescript
           * export declare namespace types {
           *     interface Collection<T> {}
           *     interface List<T> extends Collection<T> {
           *         [index: number]: T;
           *         length: number;
           *     }
           *     interface ListIterator<T, TResult> {
           *         (value: T, index: number, list: List<T>): TResult;
           *     }
           *     interface Dictionary<T> extends Collection<T> {
           *         [index: string]: T;
           *     }
           *     interface ObjectIterator<T, TResult> {
           *         (element: T, key: string, list: Dictionary<T>): TResult;
           *     }
           *     interface MemoIterator<T, TResult> {
           *         (prev: TResult, curr: T, index: number, list: List<T>): TResult;
           *     }
           *     interface MemoObjectIterator<T, TResult> {
           *         (prev: TResult, curr: T, key: string, list: Dictionary<T>): TResult;
           *     }
           *     type Fn<T> = (...args: any[]) => T;
           *     type AnyFn = Fn<any>;
           *     type PlainObj<T> = { [name: string]: T };
           * }
           * export declare const types: {};
           */
  
          exports = {}
  
          return exports
        })({}))
  
        /* ------------------------------ isObj ------------------------------ */
  
        var isObj = (_licia.isObj = (function (exports) {
          /* Check if value is the language type of Object.
           *
           * |Name  |Desc                      |
           * |------|--------------------------|
           * |val   |Value to check            |
           * |return|True if value is an object|
           *
           * [Language Spec](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
           */
  
          /* example
           * isObj({}); // -> true
           * isObj([]); // -> true
           */
  
          /* typescript
           * export declare function isObj(val: any): boolean;
           */
  
          exports = function (val) {
            var type = typeof val
            return !!val && (type === 'function' || type === 'object')
          }
  
          return exports
        })({}))
  
        /* ------------------------------ splitCase ------------------------------ */
  
        var splitCase = (_licia.splitCase = (function (exports) {
          /* Split different string case to an array.
           *
           * |Name  |Desc           |
           * |------|---------------|
           * |str   |String to split|
           * |return|Result array   |
           */
  
          /* example
           * splitCase('foo-bar'); // -> ['foo', 'bar']
           * splitCase('foo bar'); // -> ['foo', 'bar']
           * splitCase('foo_bar'); // -> ['foo', 'bar']
           * splitCase('foo.bar'); // -> ['foo', 'bar']
           * splitCase('fooBar'); // -> ['foo', 'bar']
           * splitCase('foo-Bar'); // -> ['foo', 'bar']
           */
  
          /* typescript
           * export declare function splitCase(str: string): string[];
           */
  
          var regUpperCase = /([A-Z])/g
          var regSeparator = /[_.\- ]+/g
          var regTrim = /(^-)|(-$)/g
          exports = function (str) {
            str = str
              .replace(regUpperCase, '-$1')
              .toLowerCase()
              .replace(regSeparator, '-')
              .replace(regTrim, '')
            return str.split('-')
          }
  
          return exports
        })({}))
  
        /* ------------------------------ camelCase ------------------------------ */
  
        var camelCase = (_licia.camelCase = (function (exports) {
          /* Convert string to "camelCase".
           *
           * |Name  |Desc              |
           * |------|------------------|
           * |str   |String to convert |
           * |return|Camel cased string|
           */
  
          /* example
           * camelCase('foo-bar'); // -> fooBar
           * camelCase('foo bar'); // -> fooBar
           * camelCase('foo_bar'); // -> fooBar
           * camelCase('foo.bar'); // -> fooBar
           */
  
          /* typescript
           * export declare function camelCase(str: string): string;
           */
  
          /* dependencies
           * splitCase
           */
          exports = function (str) {
            var arr = splitCase(str)
            var ret = arr[0]
            arr.shift()
            arr.forEach(capitalize, arr)
            ret += arr.join('')
            return ret
          }
          function capitalize(val, idx) {
            this[idx] = val.replace(/\w/, function (match) {
              return match.toUpperCase()
            })
          }
  
          return exports
        })({}))
  
        /* ------------------------------ kebabCase ------------------------------ */
  
        var kebabCase = (_licia.kebabCase = (function (exports) {
          /* Convert string to "kebabCase".
           *
           * |Name  |Desc              |
           * |------|------------------|
           * |str   |String to convert |
           * |return|Kebab cased string|
           */
  
          /* example
           * kebabCase('fooBar'); // -> foo-bar
           * kebabCase('foo bar'); // -> foo-bar
           * kebabCase('foo_bar'); // -> foo-bar
           * kebabCase('foo.bar'); // -> foo-bar
           */
  
          /* typescript
           * export declare function kebabCase(str: string): string;
           */
  
          /* dependencies
           * splitCase
           */
          exports = function (str) {
            return splitCase(str).join('-')
          }
  
          return exports
        })({}))
  
        /* ------------------------------ has ------------------------------ */
  
        var has = (_licia.has = (function (exports) {
          /* Checks if key is a direct property.
           *
           * |Name  |Desc                            |
           * |------|--------------------------------|
           * |obj   |Object to query                 |
           * |key   |Path to check                   |
           * |return|True if key is a direct property|
           */
  
          /* example
           * has({ one: 1 }, 'one'); // -> true
           */
  
          /* typescript
           * export declare function has(obj: {}, key: string): boolean;
           */
  
          var hasOwnProp = Object.prototype.hasOwnProperty
          exports = function (obj, key) {
            return hasOwnProp.call(obj, key)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ keys ------------------------------ */
  
        var keys = (_licia.keys = (function (exports) {
          /* Create an array of the own enumerable property names of object.
           *
           * |Name  |Desc                   |
           * |------|-----------------------|
           * |obj   |Object to query        |
           * |return|Array of property names|
           */
  
          /* example
           * keys({ a: 1 }); // -> ['a']
           */
  
          /* typescript
           * export declare function keys(obj: any): string[];
           */
  
          /* dependencies
           * has
           */
          if (Object.keys && !false) {
            exports = Object.keys
          } else {
            exports = function (obj) {
              var ret = []
              for (var key in obj) {
                if (has(obj, key)) ret.push(key)
              }
              return ret
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ idxOf ------------------------------ */
  
        var idxOf = (_licia.idxOf = (function (exports) {
          /* Get the index at which the first occurrence of value.
           *
           * |Name     |Desc                |
           * |---------|--------------------|
           * |arr      |Array to search     |
           * |val      |Value to search for |
           * |fromIdx=0|Index to search from|
           * |return   |Value index         |
           */
  
          /* example
           * idxOf([1, 2, 1, 2], 2, 2); // -> 3
           */
  
          /* typescript
           * export declare function idxOf(arr: any[], val: any, fromIdx?: number): number;
           */
  
          exports = function (arr, val, fromIdx) {
            return Array.prototype.indexOf.call(arr, val, fromIdx)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ create ------------------------------ */
  
        var create = (_licia.create = (function (exports) {
          /* Create new object using given object as prototype.
           *
           * |Name  |Desc                   |
           * |------|-----------------------|
           * |proto |Prototype of new object|
           * |return|Created object         |
           */
  
          /* example
           * const obj = create({ a: 1 });
           * console.log(obj.a); // -> 1
           */
  
          /* typescript
           * export declare function create(proto?: object): any;
           */
  
          /* dependencies
           * isObj
           */
          exports = function (proto) {
            if (!isObj(proto)) return {}
            if (objCreate && !false) return objCreate(proto)
            function noop() {}
            noop.prototype = proto
            return new noop()
          }
          var objCreate = Object.create
  
          return exports
        })({}))
  
        /* ------------------------------ inherits ------------------------------ */
  
        var inherits = (_licia.inherits = (function (exports) {
          /* Inherit the prototype methods from one constructor into another.
           *
           * |Name      |Desc       |
           * |----------|-----------|
           * |Class     |Child Class|
           * |SuperClass|Super Class|
           */
  
          /* example
           * function People(name) {
           *     this._name = name;
           * }
           * People.prototype = {
           *     getName: function() {
           *         return this._name;
           *     }
           * };
           * function Student(name) {
           *     this._name = name;
           * }
           * inherits(Student, People);
           * const s = new Student('RedHood');
           * s.getName(); // -> 'RedHood'
           */
  
          /* typescript
           * export declare function inherits(
           *     Class: types.AnyFn,
           *     SuperClass: types.AnyFn
           * ): void;
           */
  
          /* dependencies
           * create types
           */
          exports = function (Class, SuperClass) {
            Class.prototype = create(SuperClass.prototype)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ memoize ------------------------------ */
  
        var memoize = (_licia.memoize = (function (exports) {
          /* Memoize a given function by caching the computed result.
           *
           * |Name  |Desc                                |
           * |------|------------------------------------|
           * |fn    |Function to have its output memoized|
           * |hashFn|Function to create cache key        |
           * |return|New memoized function               |
           */
  
          /* example
           * const fibonacci = memoize(function(n) {
           *     return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
           * });
           */
  
          /* typescript
           * export declare function memoize(
           *     fn: types.AnyFn,
           *     hashFn?: types.AnyFn
           * ): types.AnyFn;
           */
  
          /* dependencies
           * has types
           */
          exports = function (fn, hashFn) {
            var memoize = function (key) {
              var cache = memoize.cache
              var address = '' + (hashFn ? hashFn.apply(this, arguments) : key)
              if (!has(cache, address)) cache[address] = fn.apply(this, arguments)
              return cache[address]
            }
            memoize.cache = {}
            return memoize
          }
  
          return exports
        })({}))
  
        /* ------------------------------ cssSupports ------------------------------ */
        _licia.cssSupports = (function (exports) {
          /* Check if browser supports a given CSS feature.
           *
           * |Name  |Desc              |
           * |------|------------------|
           * |name  |Css property name |
           * |val   |Css property value|
           * |return|True if supports  |
           */
  
          /* example
           * cssSupports('display', 'flex'); // -> true
           * cssSupports('display', 'invalid'); // -> false
           * cssSupports('text-decoration-line', 'underline'); // -> true
           * cssSupports('grid'); // -> true
           * cssSupports('invalid'); // -> false
           */
  
          /* typescript
           * export declare function cssSupports(name: string, val?: string): boolean;
           */
  
          /* dependencies
           * memoize isUndef camelCase
           */
          exports = memoize(
            function (name, value) {
              if (isUndef(value)) {
                name = camelCase(name)
                return !isUndef(style[name])
              }
              style.cssText = ''
              style.cssText = name + ':' + value
              return !!style.length
            },
            function (name, value) {
              return name + ' ' + value
            }
          )
          var style = document.createElement('p').style
  
          return exports
        })({})
  
        /* ------------------------------ optimizeCb ------------------------------ */
  
        var optimizeCb = (_licia.optimizeCb = (function (exports) {
          /* Used for function context binding.
           */
  
          /* typescript
           * export declare function optimizeCb(
           *     fn: types.AnyFn,
           *     ctx: any,
           *     argCount?: number
           * ): types.AnyFn;
           */
  
          /* dependencies
           * isUndef types
           */
          exports = function (fn, ctx, argCount) {
            if (isUndef(ctx)) return fn
            switch (argCount == null ? 3 : argCount) {
              case 1:
                return function (val) {
                  return fn.call(ctx, val)
                }
              case 3:
                return function (val, idx, collection) {
                  return fn.call(ctx, val, idx, collection)
                }
              case 4:
                return function (accumulator, val, idx, collection) {
                  return fn.call(ctx, accumulator, val, idx, collection)
                }
            }
            return function () {
              return fn.apply(ctx, arguments)
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ evalCss ------------------------------ */
        _licia.evalCss = (function (exports) {
          /* Load css into page.
           *
           * |Name  |Desc         |
           * |------|-------------|
           * |css   |Css code     |
           * |return|Style element|
           */
  
          /* example
           * evalCss('body{background:#08c}');
           */
  
          /* typescript
           * export declare function evalCss(css: string): HTMLStyleElement;
           */
  
          exports = function (css) {
            var style = document.createElement('style')
            style.textContent = css
            style.type = 'text/css'
            document.head.appendChild(style)
            return style
          }
  
          return exports
        })({})
  
        /* ------------------------------ isEl ------------------------------ */
  
        var isEl = (_licia.isEl = (function (exports) {
          /* Check if value is a DOM element.
           *
           * |Name  |Desc                          |
           * |------|------------------------------|
           * |val   |Value to check                |
           * |return|True if value is a DOM element|
           */
  
          /* example
           * isEl(document.body); // -> true
           */
  
          /* typescript
           * export declare function isEl(val: any): val is Element;
           */
  
          exports = function (val) {
            return !!(val && val.nodeType === 1)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ startWith ------------------------------ */
  
        var startWith = (_licia.startWith = (function (exports) {
          /* Check if string starts with the given target string.
           *
           * |Name  |Desc                             |
           * |------|---------------------------------|
           * |str   |String to search                 |
           * |prefix|String prefix                    |
           * |return|True if string starts with prefix|
           */
  
          /* example
           * startWith('ab', 'a'); // -> true
           */
  
          /* typescript
           * export declare function startWith(str: string, prefix: string): boolean;
           */
  
          exports = function (str, prefix) {
            return str.indexOf(prefix) === 0
          }
  
          return exports
        })({}))
  
        /* ------------------------------ identity ------------------------------ */
  
        var identity = (_licia.identity = (function (exports) {
          /* Return the first argument given.
           *
           * |Name  |Desc       |
           * |------|-----------|
           * |val   |Any value  |
           * |return|Given value|
           */
  
          /* example
           * identity('a'); // -> 'a'
           */
  
          /* typescript
           * export declare function identity<T>(val: T): T;
           */
  
          exports = function (val) {
            return val
          }
  
          return exports
        })({}))
  
        /* ------------------------------ objToStr ------------------------------ */
  
        var objToStr = (_licia.objToStr = (function (exports) {
          /* Alias of Object.prototype.toString.
           *
           * |Name  |Desc                                |
           * |------|------------------------------------|
           * |val   |Source value                        |
           * |return|String representation of given value|
           */
  
          /* example
           * objToStr(5); // -> '[object Number]'
           */
  
          /* typescript
           * export declare function objToStr(val: any): string;
           */
  
          var ObjToStr = Object.prototype.toString
          exports = function (val) {
            return ObjToStr.call(val)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isArr ------------------------------ */
  
        var isArr = (_licia.isArr = (function (exports) {
          /* Check if value is an `Array` object.
           *
           * |Name  |Desc                              |
           * |------|----------------------------------|
           * |val   |Value to check                    |
           * |return|True if value is an `Array` object|
           */
  
          /* example
           * isArr([]); // -> true
           * isArr({}); // -> false
           */
  
          /* typescript
           * export declare function isArr(val: any): val is any[];
           */
  
          /* dependencies
           * objToStr
           */
          if (Array.isArray && !false) {
            exports = Array.isArray
          } else {
            exports = function (val) {
              return objToStr(val) === '[object Array]'
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ castPath ------------------------------ */
  
        var castPath = (_licia.castPath = (function (exports) {
          /* Cast value into a property path array.
           *
           * |Name  |Desc               |
           * |------|-------------------|
           * |path  |Value to inspect   |
           * |obj   |Object to query    |
           * |return|Property path array|
           */
  
          /* example
           * castPath('a.b.c'); // -> ['a', 'b', 'c']
           * castPath(['a']); // -> ['a']
           * castPath('a[0].b'); // -> ['a', '0', 'b']
           * castPath('a.b.c', { 'a.b.c': true }); // -> ['a.b.c']
           */
  
          /* typescript
           * export declare function castPath(path: string | string[], obj?: any): string[];
           */
  
          /* dependencies
           * has isArr
           */
          exports = function (str, obj) {
            if (isArr(str)) return str
            if (obj && has(obj, str)) return [str]
            var ret = []
            str.replace(regPropName, function (match, number, quote, str) {
              ret.push(quote ? str.replace(regEscapeChar, '$1') : number || match)
            })
            return ret
          }
  
          // Lodash _stringToPath
          var regPropName =
            /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g
          var regEscapeChar = /\\(\\)?/g
  
          return exports
        })({}))
  
        /* ------------------------------ safeGet ------------------------------ */
  
        var safeGet = (_licia.safeGet = (function (exports) {
          /* Get object property, don't throw undefined error.
           *
           * |Name  |Desc                     |
           * |------|-------------------------|
           * |obj   |Object to query          |
           * |path  |Path of property to get  |
           * |return|Target value or undefined|
           */
  
          /* example
           * const obj = { a: { aa: { aaa: 1 } } };
           * safeGet(obj, 'a.aa.aaa'); // -> 1
           * safeGet(obj, ['a', 'aa']); // -> {aaa: 1}
           * safeGet(obj, 'a.b'); // -> undefined
           */
  
          /* typescript
           * export declare function safeGet(obj: any, path: string | string[]): any;
           */
  
          /* dependencies
           * isUndef castPath
           */
          exports = function (obj, path) {
            path = castPath(path, obj)
            var prop
            prop = path.shift()
            while (!isUndef(prop)) {
              obj = obj[prop]
              if (obj == null) return
              prop = path.shift()
            }
            return obj
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isFn ------------------------------ */
  
        var isFn = (_licia.isFn = (function (exports) {
          /* Check if value is a function.
           *
           * |Name  |Desc                       |
           * |------|---------------------------|
           * |val   |Value to check             |
           * |return|True if value is a function|
           *
           * Generator function is also classified as true.
           */
  
          /* example
           * isFn(function() {}); // -> true
           * isFn(function*() {}); // -> true
           * isFn(async function() {}); // -> true
           */
  
          /* typescript
           * export declare function isFn(val: any): val is Function;
           */
  
          /* dependencies
           * objToStr
           */
          exports = function (val) {
            var objStr = objToStr(val)
            return (
              objStr === '[object Function]' ||
              objStr === '[object GeneratorFunction]' ||
              objStr === '[object AsyncFunction]'
            )
          }
  
          return exports
        })({}))
  
        /* ------------------------------ getProto ------------------------------ */
  
        var getProto = (_licia.getProto = (function (exports) {
          /* Get prototype of an object.
           *
           * |Name  |Desc                                         |
           * |------|---------------------------------------------|
           * |obj   |Target object                                |
           * |return|Prototype of given object, null if not exists|
           */
  
          /* example
           * const a = {};
           * getProto(Object.create(a)); // -> a
           */
  
          /* typescript
           * export declare function getProto(obj: any): any;
           */
  
          /* dependencies
           * isObj isFn
           */
          var getPrototypeOf = Object.getPrototypeOf
          var ObjectCtr = {}.constructor
          exports = function (obj) {
            if (!isObj(obj)) return
            if (getPrototypeOf && !false) return getPrototypeOf(obj)
            var proto = obj.__proto__
            if (proto || proto === null) return proto
            if (isFn(obj.constructor)) return obj.constructor.prototype
            if (obj instanceof ObjectCtr) return ObjectCtr.prototype
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isMiniProgram ------------------------------ */
  
        var isMiniProgram = (_licia.isMiniProgram = (function (exports) {
          /* Check if running in wechat mini program.
           */
  
          /* example
           * console.log(isMiniProgram); // -> true if running in mini program.
           */
  
          /* typescript
           * export declare const isMiniProgram: boolean;
           */
  
          /* dependencies
           * isFn
           */
  
          /* eslint-disable no-undef */
          exports = typeof wx !== 'undefined' && isFn(wx.openLocation)
  
          return exports
        })({}))
  
        /* ------------------------------ isNum ------------------------------ */
  
        var isNum = (_licia.isNum = (function (exports) {
          /* Check if value is classified as a Number primitive or object.
           *
           * |Name  |Desc                                 |
           * |------|-------------------------------------|
           * |val   |Value to check                       |
           * |return|True if value is correctly classified|
           */
  
          /* example
           * isNum(5); // -> true
           * isNum(5.1); // -> true
           * isNum({}); // -> false
           */
  
          /* typescript
           * export declare function isNum(val: any): val is number;
           */
  
          /* dependencies
           * objToStr
           */
          exports = function (val) {
            return objToStr(val) === '[object Number]'
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isArrLike ------------------------------ */
  
        var isArrLike = (_licia.isArrLike = (function (exports) {
          /* Check if value is array-like.
           *
           * |Name  |Desc                       |
           * |------|---------------------------|
           * |val   |Value to check             |
           * |return|True if value is array like|
           *
           * Function returns false.
           */
  
          /* example
           * isArrLike('test'); // -> true
           * isArrLike(document.body.children); // -> true;
           * isArrLike([1, 2, 3]); // -> true
           */
  
          /* typescript
           * export declare function isArrLike(val: any): boolean;
           */
  
          /* dependencies
           * isNum isFn
           */
          var MAX_ARR_IDX = Math.pow(2, 53) - 1
          exports = function (val) {
            if (!val) return false
            var len = val.length
            return isNum(len) && len >= 0 && len <= MAX_ARR_IDX && !isFn(val)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ each ------------------------------ */
  
        var each = (_licia.each = (function (exports) {
          /* Iterate over elements of collection and invokes iterator for each element.
           *
           * |Name    |Desc                          |
           * |--------|------------------------------|
           * |obj     |Collection to iterate over    |
           * |iterator|Function invoked per iteration|
           * |ctx     |Function context              |
           */
  
          /* example
           * each({ a: 1, b: 2 }, function(val, key) {});
           */
  
          /* typescript
           * export declare function each<T>(
           *     list: types.List<T>,
           *     iterator: types.ListIterator<T, void>,
           *     ctx?: any
           * ): types.List<T>;
           * export declare function each<T>(
           *     object: types.Dictionary<T>,
           *     iterator: types.ObjectIterator<T, void>,
           *     ctx?: any
           * ): types.Collection<T>;
           */
  
          /* dependencies
           * isArrLike keys optimizeCb types
           */
          exports = function (obj, iterator, ctx) {
            iterator = optimizeCb(iterator, ctx)
            var i, len
            if (isArrLike(obj)) {
              for (i = 0, len = obj.length; i < len; i++) iterator(obj[i], i, obj)
            } else {
              var _keys = keys(obj)
              for (i = 0, len = _keys.length; i < len; i++) {
                iterator(obj[_keys[i]], _keys[i], obj)
              }
            }
            return obj
          }
  
          return exports
        })({}))
  
        /* ------------------------------ createAssigner ------------------------------ */
  
        var createAssigner = (_licia.createAssigner = (function (exports) {
          /* Used to create extend, extendOwn and defaults.
           *
           * |Name    |Desc                          |
           * |--------|------------------------------|
           * |keysFn  |Function to get object keys   |
           * |defaults|No override when set to true  |
           * |return  |Result function, extend...    |
           */
  
          /* typescript
           * export declare function createAssigner(
           *     keysFn: types.AnyFn,
           *     defaults: boolean
           * ): types.AnyFn;
           */
  
          /* dependencies
           * isUndef each types
           */
          exports = function (keysFn, defaults) {
            return function (obj) {
              each(arguments, function (src, idx) {
                if (idx === 0) return
                var keys = keysFn(src)
                each(keys, function (key) {
                  if (!defaults || isUndef(obj[key])) obj[key] = src[key]
                })
              })
              return obj
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ extendOwn ------------------------------ */
  
        var extendOwn = (_licia.extendOwn = (function (exports) {
          /* Like extend, but only copies own properties over to the destination object.
           *
           * |Name       |Desc              |
           * |-----------|------------------|
           * |destination|Destination object|
           * |...sources |Sources objects   |
           * |return     |Destination object|
           */
  
          /* example
           * extendOwn({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24}
           */
  
          /* typescript
           * export declare function extendOwn(destination: any, ...sources: any[]): any;
           */
  
          /* dependencies
           * keys createAssigner
           */
          exports = createAssigner(keys)
  
          return exports
        })({}))
  
        /* ------------------------------ values ------------------------------ */
  
        var values = (_licia.values = (function (exports) {
          /* Create an array of the own enumerable property values of object.
           *
           * |Name  |Desc                    |
           * |------|------------------------|
           * |obj   |Object to query         |
           * |return|Array of property values|
           */
  
          /* example
           * values({ one: 1, two: 2 }); // -> [1, 2]
           */
  
          /* typescript
           * export declare function values(obj: any): any[];
           */
  
          /* dependencies
           * each
           */
          exports = function (obj) {
            var ret = []
            each(obj, function (val) {
              ret.push(val)
            })
            return ret
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isStr ------------------------------ */
  
        var isStr = (_licia.isStr = (function (exports) {
          /* Check if value is a string primitive.
           *
           * |Name  |Desc                               |
           * |------|-----------------------------------|
           * |val   |Value to check                     |
           * |return|True if value is a string primitive|
           */
  
          /* example
           * isStr('licia'); // -> true
           */
  
          /* typescript
           * export declare function isStr(val: any): val is string;
           */
  
          /* dependencies
           * objToStr
           */
          exports = function (val) {
            return objToStr(val) === '[object String]'
          }
  
          return exports
        })({}))
  
        /* ------------------------------ contain ------------------------------ */
  
        var contain = (_licia.contain = (function (exports) {
          /* Check if the value is present in the list.
           *
           * |Name  |Desc                                |
           * |------|------------------------------------|
           * |target|Target object                       |
           * |val   |Value to check                      |
           * |return|True if value is present in the list|
           */
  
          /* example
           * contain([1, 2, 3], 1); // -> true
           * contain({ a: 1, b: 2 }, 1); // -> true
           * contain('abc', 'a'); // -> true
           */
  
          /* typescript
           * export declare function contain(arr: any[] | {} | string, val: any): boolean;
           */
  
          /* dependencies
           * idxOf isStr isArrLike values
           */
          exports = function (arr, val) {
            if (isStr(arr)) return arr.indexOf(val) > -1
            if (!isArrLike(arr)) arr = values(arr)
            return idxOf(arr, val) >= 0
          }
  
          return exports
        })({}))
  
        /* ------------------------------ isBrowser ------------------------------ */
  
        var isBrowser = (_licia.isBrowser = (function (exports) {
          /* Check if running in a browser.
           */
  
          /* example
           * console.log(isBrowser); // -> true if running in a browser
           */
  
          /* typescript
           * export declare const isBrowser: boolean;
           */
  
          exports =
            typeof window === 'object' && typeof document === 'object' && document.nodeType === 9
  
          return exports
        })({}))
  
        /* ------------------------------ isMatch ------------------------------ */
  
        var isMatch = (_licia.isMatch = (function (exports) {
          /* Check if keys and values in src are contained in obj.
           *
           * |Name  |Desc                              |
           * |------|----------------------------------|
           * |obj   |Object to inspect                 |
           * |src   |Object of property values to match|
           * |return|True if object is match           |
           */
  
          /* example
           * isMatch({ a: 1, b: 2 }, { a: 1 }); // -> true
           */
  
          /* typescript
           * export declare function isMatch(obj: any, src: any): boolean;
           */
  
          /* dependencies
           * keys
           */
          exports = function (obj, src) {
            var _keys = keys(src)
            var len = _keys.length
            if (obj == null) return !len
            obj = Object(obj)
            for (var i = 0; i < len; i++) {
              var key = _keys[i]
              if (src[key] !== obj[key] || !(key in obj)) return false
            }
            return true
          }
  
          return exports
        })({}))
  
        /* ------------------------------ matcher ------------------------------ */
  
        var matcher = (_licia.matcher = (function (exports) {
          /* Return a predicate function that checks if attrs are contained in an object.
           *
           * |Name  |Desc                              |
           * |------|----------------------------------|
           * |attrs |Object of property values to match|
           * |return|New predicate function            |
           */
  
          /* example
           * const filter = require('licia/filter');
           *
           * const objects = [
           *     { a: 1, b: 2, c: 3 },
           *     { a: 4, b: 5, c: 6 }
           * ];
           * filter(objects, matcher({ a: 4, c: 6 })); // -> [{a: 4, b: 5, c: 6}]
           */
  
          /* typescript
           * export declare function matcher(attrs: any): types.AnyFn;
           */
  
          /* dependencies
           * extendOwn isMatch types
           */
          exports = function (attrs) {
            attrs = extendOwn({}, attrs)
            return function (obj) {
              return isMatch(obj, attrs)
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ restArgs ------------------------------ */
  
        var restArgs = (_licia.restArgs = (function (exports) {
          /* This accumulates the arguments passed into an array, after a given index.
           *
           * |Name      |Desc                                   |
           * |----------|---------------------------------------|
           * |function  |Function that needs rest parameters    |
           * |startIndex|The start index to accumulates         |
           * |return    |Generated function with rest parameters|
           */
  
          /* example
           * const paramArr = restArgs(function(rest) {
           *     return rest;
           * });
           * paramArr(1, 2, 3, 4); // -> [1, 2, 3, 4]
           */
  
          /* typescript
           * export declare function restArgs(
           *     fn: types.AnyFn,
           *     startIndex?: number
           * ): types.AnyFn;
           */
  
          /* dependencies
           * types
           */
          exports = function (fn, startIdx) {
            startIdx = startIdx == null ? fn.length - 1 : +startIdx
            return function () {
              var len = Math.max(arguments.length - startIdx, 0)
              var rest = new Array(len)
              var i
              for (i = 0; i < len; i++) rest[i] = arguments[i + startIdx]
  
              // Call runs faster than apply.
              switch (startIdx) {
                case 0:
                  return fn.call(this, rest)
                case 1:
                  return fn.call(this, arguments[0], rest)
                case 2:
                  return fn.call(this, arguments[0], arguments[1], rest)
              }
              var args = new Array(startIdx + 1)
              for (i = 0; i < startIdx; i++) args[i] = arguments[i]
              args[startIdx] = rest
              return fn.apply(this, args)
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ mergeArr ------------------------------ */
  
        var mergeArr = (_licia.mergeArr = (function (exports) {
          /* Merge the contents of arrays together into the first array.
           *
           * |Name  |Desc                                |
           * |------|------------------------------------|
           * |first |Array to merge                      |
           * |arrays|Arrays to merge into the first array|
           * |return|First array                         |
           */
  
          /* example
           * const a = [1, 2];
           * mergeArr(a, [3, 4], [5, 6]);
           * console.log(a); // -> [1, 2, 3, 4, 5, 6]
           */
  
          /* typescript
           * export declare function mergeArr<T, U>(
           *     first: ArrayLike<T>,
           *     ...arrays: ArrayLike<U>[]
           * ): ArrayLike<T | U>;
           */
  
          /* dependencies
           * restArgs
           */
          exports = restArgs(function (first, arrays) {
            var end = first.length
            for (var i = 0, len = arrays.length; i < len; i++) {
              var arr = arrays[i]
              for (var j = 0, _len = arr.length; j < _len; j++) {
                first[end++] = arr[j]
              }
            }
            first.length = end
            return first
          })
  
          return exports
        })({}))
  
        /* ------------------------------ upperFirst ------------------------------ */
  
        var upperFirst = (_licia.upperFirst = (function (exports) {
          /* Convert the first character of string to upper case.
           *
           * |Name  |Desc             |
           * |------|-----------------|
           * |str   |String to convert|
           * |return|Converted string |
           */
  
          /* example
           * upperFirst('red'); // -> Red
           */
  
          /* typescript
           * export declare function upperFirst(str: string): string;
           */
  
          exports = function (str) {
            if (str.length < 1) return str
            return str[0].toUpperCase() + str.slice(1)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ prefix ------------------------------ */
  
        var prefix = (_licia.prefix = (function (exports) {
          /* Add vendor prefixes to a CSS attribute.
           *
           * |Name  |Desc                  |
           * |------|----------------------|
           * |name  |Property name         |
           * |return|Prefixed property name|
           *
           * ### dash
           *
           * Create a dasherize version.
           */
  
          /* example
           * prefix('text-emphasis'); // -> 'WebkitTextEmphasis'
           * prefix.dash('text-emphasis'); // -> '-webkit-text-emphasis'
           * prefix('color'); // -> 'color'
           */
  
          /* typescript
           * export declare namespace prefix {
           *     function dash(name: string): string;
           * }
           * export declare function prefix(name: string): string;
           */
  
          /* dependencies
           * memoize camelCase upperFirst has kebabCase
           */
          exports = memoize(function (name) {
            name = name.replace(regPrefixes, '')
            name = camelCase(name)
            if (has(style, name)) return name
            var i = prefixes.length
            while (i--) {
              var prefixName = prefixes[i] + upperFirst(name)
              if (has(style, prefixName)) return prefixName
            }
            return name
          })
          exports.dash = memoize(function (name) {
            var camelCaseResult = exports(name)
            return (regPrefixes.test(camelCaseResult) ? '-' : '') + kebabCase(camelCaseResult)
          })
          var prefixes = ['O', 'ms', 'Moz', 'Webkit']
          var regPrefixes = /^(O)|(ms)|(Moz)|(Webkit)|(-o-)|(-ms-)|(-moz-)|(-webkit-)/g
          var style = document.createElement('p').style
  
          return exports
        })({}))
  
        /* ------------------------------ property ------------------------------ */
  
        var property = (_licia.property = (function (exports) {
          /* Return a function that will itself return the key property of any passed-in object.
           *
           * |Name  |Desc                       |
           * |------|---------------------------|
           * |path  |Path of the property to get|
           * |return|New accessor function      |
           */
  
          /* example
           * const obj = { a: { b: 1 } };
           * property('a')(obj); // -> {b: 1}
           * property(['a', 'b'])(obj); // -> 1
           */
  
          /* typescript
           * export declare function property(path: string | string[]): types.AnyFn;
           */
  
          /* dependencies
           * isArr safeGet types
           */
          exports = function (path) {
            if (!isArr(path)) return shallowProperty(path)
            return function (obj) {
              return safeGet(obj, path)
            }
          }
          function shallowProperty(key) {
            return function (obj) {
              return obj == null ? void 0 : obj[key]
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ safeCb ------------------------------ */
  
        var safeCb = (_licia.safeCb = (function (exports) {
          /* Create callback based on input value.
           */
  
          /* typescript
           * export declare function safeCb(
           *     val?: any,
           *     ctx?: any,
           *     argCount?: number
           * ): types.AnyFn;
           */
  
          /* dependencies
           * isFn isObj isArr optimizeCb matcher identity types property
           */
          exports = function (val, ctx, argCount) {
            if (val == null) return identity
            if (isFn(val)) return optimizeCb(val, ctx, argCount)
            if (isObj(val) && !isArr(val)) return matcher(val)
            return property(val)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ filter ------------------------------ */
  
        var filter = (_licia.filter = (function (exports) {
          /* Iterates over elements of collection, returning an array of all the values that pass a truth test.
           *
           * |Name     |Desc                                   |
           * |---------|---------------------------------------|
           * |obj      |Collection to iterate over             |
           * |predicate|Function invoked per iteration         |
           * |ctx      |Predicate context                      |
           * |return   |Array of all values that pass predicate|
           */
  
          /* example
           * filter([1, 2, 3, 4, 5], function(val) {
           *     return val % 2 === 0;
           * }); // -> [2, 4]
           */
  
          /* typescript
           * export declare function filter<T>(
           *     list: types.List<T>,
           *     iterator: types.ListIterator<T, boolean>,
           *     context?: any
           * ): T[];
           * export declare function filter<T>(
           *     object: types.Dictionary<T>,
           *     iterator: types.ObjectIterator<T, boolean>,
           *     context?: any
           * ): T[];
           */
  
          /* dependencies
           * safeCb each types
           */
          exports = function (obj, predicate, ctx) {
            var ret = []
            predicate = safeCb(predicate, ctx)
            each(obj, function (val, idx, list) {
              if (predicate(val, idx, list)) ret.push(val)
            })
            return ret
          }
  
          return exports
        })({}))
  
        /* ------------------------------ unique ------------------------------ */
  
        var unique = (_licia.unique = (function (exports) {
          /* Create duplicate-free version of an array.
           *
           * |Name  |Desc                         |
           * |------|-----------------------------|
           * |arr   |Array to inspect             |
           * |cmp   |Function for comparing values|
           * |return|New duplicate free array     |
           */
  
          /* example
           * unique([1, 2, 3, 1]); // -> [1, 2, 3]
           */
  
          /* typescript
           * export declare function unique(
           *     arr: any[],
           *     cmp?: (a: any, b: any) => boolean | number
           * ): any[];
           */
  
          /* dependencies
           * filter
           */
          exports = function (arr, cmp) {
            cmp = cmp || isEqual
            return filter(arr, function (item, idx, arr) {
              var len = arr.length
              while (++idx < len) {
                if (cmp(item, arr[idx])) return false
              }
              return true
            })
          }
          function isEqual(a, b) {
            return a === b
          }
  
          return exports
        })({}))
  
        /* ------------------------------ allKeys ------------------------------ */
  
        var allKeys = (_licia.allKeys = (function (exports) {
          /* Retrieve all the names of object's own and inherited properties.
           *
           * |Name   |Desc                       |
           * |-------|---------------------------|
           * |obj    |Object to query            |
           * |options|Options                    |
           * |return |Array of all property names|
           *
           * Available options:
           *
           * |Name              |Desc                     |
           * |------------------|-------------------------|
           * |prototype=true    |Include prototype keys   |
           * |unenumerable=false|Include unenumerable keys|
           * |symbol=false      |Include symbol keys      |
           *
           * Members of Object's prototype won't be retrieved.
           */
  
          /* example
           * const obj = Object.create({ zero: 0 });
           * obj.one = 1;
           * allKeys(obj); // -> ['zero', 'one']
           */
  
          /* typescript
           * export declare namespace allKeys {
           *     interface IOptions {
           *         prototype?: boolean;
           *         unenumerable?: boolean;
           *     }
           * }
           * export declare function allKeys(
           *     obj: any,
           *     options: { symbol: true } & allKeys.IOptions
           * ): Array<string | Symbol>;
           * export declare function allKeys(
           *     obj: any,
           *     options?: ({ symbol: false } & allKeys.IOptions) | allKeys.IOptions
           * ): string[];
           */
  
          /* dependencies
           * keys getProto unique
           */
          var getOwnPropertyNames = Object.getOwnPropertyNames
          var getOwnPropertySymbols = Object.getOwnPropertySymbols
          exports = function (obj) {
            var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
              _ref$prototype = _ref.prototype,
              prototype = _ref$prototype === void 0 ? true : _ref$prototype,
              _ref$unenumerable = _ref.unenumerable,
              unenumerable = _ref$unenumerable === void 0 ? false : _ref$unenumerable,
              _ref$symbol = _ref.symbol,
              symbol = _ref$symbol === void 0 ? false : _ref$symbol
            var ret = []
            if ((unenumerable || symbol) && getOwnPropertyNames) {
              var getKeys = keys
              if (unenumerable && getOwnPropertyNames) getKeys = getOwnPropertyNames
              do {
                ret = ret.concat(getKeys(obj))
                if (symbol && getOwnPropertySymbols) {
                  ret = ret.concat(getOwnPropertySymbols(obj))
                }
              } while (prototype && (obj = getProto(obj)) && obj !== Object.prototype)
              ret = unique(ret)
            } else {
              if (prototype) {
                for (var key in obj) ret.push(key)
              } else {
                ret = keys(obj)
              }
            }
            return ret
          }
  
          return exports
        })({}))
  
        /* ------------------------------ defaults ------------------------------ */
        _licia.defaults = (function (exports) {
          /* Fill in undefined properties in object with the first value present in the following list of defaults objects.
           *
           * |Name  |Desc              |
           * |------|------------------|
           * |obj   |Destination object|
           * |...src|Sources objects   |
           * |return|Destination object|
           */
  
          /* example
           * defaults({ name: 'RedHood' }, { name: 'Unknown', age: 24 }); // -> {name: 'RedHood', age: 24}
           */
  
          /* typescript
           * export declare function defaults(obj: any, ...src: any[]): any;
           */
  
          /* dependencies
           * createAssigner allKeys
           */
          exports = createAssigner(allKeys, true)
  
          return exports
        })({})
  
        /* ------------------------------ extend ------------------------------ */
  
        var extend = (_licia.extend = (function (exports) {
          /* Copy all of the properties in the source objects over to the destination object.
           *
           * |Name       |Desc              |
           * |-----------|------------------|
           * |destination|Destination object|
           * |...sources |Sources objects   |
           * |return     |Destination object|
           */
  
          /* example
           * extend({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24}
           */
  
          /* typescript
           * export declare function extend(destination: any, ...sources: any[]): any;
           */
  
          /* dependencies
           * createAssigner allKeys
           */
          exports = createAssigner(allKeys)
  
          return exports
        })({}))
  
        /* ------------------------------ map ------------------------------ */
  
        var map = (_licia.map = (function (exports) {
          /* Create an array of values by running each element in collection through iteratee.
           *
           * |Name    |Desc                          |
           * |--------|------------------------------|
           * |object  |Collection to iterate over    |
           * |iterator|Function invoked per iteration|
           * |context |Function context              |
           * |return  |New mapped array              |
           */
  
          /* example
           * map([4, 8], function(n) {
           *     return n * n;
           * }); // -> [16, 64]
           */
  
          /* typescript
           * export declare function map<T, TResult>(
           *     list: types.List<T>,
           *     iterator: types.ListIterator<T, TResult>,
           *     context?: any
           * ): TResult[];
           * export declare function map<T, TResult>(
           *     object: types.Dictionary<T>,
           *     iterator: types.ObjectIterator<T, TResult>,
           *     context?: any
           * ): TResult[];
           */
  
          /* dependencies
           * safeCb keys isArrLike types
           */
          exports = function (obj, iterator, ctx) {
            iterator = safeCb(iterator, ctx)
            var _keys = !isArrLike(obj) && keys(obj)
            var len = (_keys || obj).length
            var results = Array(len)
            for (var i = 0; i < len; i++) {
              var curKey = _keys ? _keys[i] : i
              results[i] = iterator(obj[curKey], curKey, obj)
            }
            return results
          }
  
          return exports
        })({}))
  
        /* ------------------------------ toArr ------------------------------ */
  
        var toArr = (_licia.toArr = (function (exports) {
          /* Convert value to an array.
           *
           * |Name  |Desc            |
           * |------|----------------|
           * |val   |Value to convert|
           * |return|Converted array |
           */
  
          /* example
           * toArr({ a: 1, b: 2 }); // -> [{a: 1, b: 2}]
           * toArr('abc'); // -> ['abc']
           * toArr(1); // -> [1]
           * toArr(null); // -> []
           */
  
          /* typescript
           * export declare function toArr(val: any): any[];
           */
  
          /* dependencies
           * isArrLike map isArr isStr
           */
          exports = function (val) {
            if (!val) return []
            if (isArr(val)) return val
            if (isArrLike(val) && !isStr(val)) return map(val)
            return [val]
          }
  
          return exports
        })({}))
  
        /* ------------------------------ Class ------------------------------ */
  
        var Class = (_licia.Class = (function (exports) {
          /* Create JavaScript class.
           *
           * |Name   |Desc                             |
           * |-------|---------------------------------|
           * |methods|Public methods                   |
           * [statics|Static methods                   |
           * |return |Function used to create instances|
           */
  
          /* example
           * const People = Class({
           *     initialize: function People(name, age) {
           *         this.name = name;
           *         this.age = age;
           *     },
           *     introduce: function() {
           *         return 'I am ' + this.name + ', ' + this.age + ' years old.';
           *     }
           * });
           *
           * const Student = People.extend(
           *     {
           *         initialize: function Student(name, age, school) {
           *             this.callSuper(People, 'initialize', arguments);
           *
           *             this.school = school;
           *         },
           *         introduce: function() {
           *             return (
           *                 this.callSuper(People, 'introduce') +
           *                 '\n I study at ' +
           *                 this.school +
           *                 '.'
           *             );
           *         }
           *     },
           *     {
           *         is: function(obj) {
           *             return obj instanceof Student;
           *         }
           *     }
           * );
           *
           * const a = new Student('allen', 17, 'Hogwarts');
           * a.introduce(); // -> 'I am allen, 17 years old. \n I study at Hogwarts.'
           * Student.is(a); // -> true
           */
  
          /* typescript
           * export declare namespace Class {
           *     class Base {
           *         toString(): string;
           *     }
           *     class IConstructor extends Base {
           *         constructor(...args: any[]);
           *         static extend(methods: any, statics: any): IConstructor;
           *         static inherits(Class: types.AnyFn): void;
           *         static methods(methods: any): IConstructor;
           *         static statics(statics: any): IConstructor;
           *         [method: string]: any;
           *     }
           * }
           * export declare function Class(methods: any, statics?: any): Class.IConstructor;
           */
  
          /* dependencies
           * extend toArr inherits safeGet isMiniProgram types
           */
          exports = function (methods, statics) {
            return Base.extend(methods, statics)
          }
          function makeClass(parent, methods, statics) {
            statics = statics || {}
            var className = methods.className || safeGet(methods, 'initialize.name') || ''
            delete methods.className
            var ctor = function () {
              var args = toArr(arguments)
              return this.initialize ? this.initialize.apply(this, args) || this : this
            }
            if (!isMiniProgram) {
              // unsafe-eval CSP violation
              try {
                ctor = new Function(
                  'toArr',
                  'return function ' +
                    className +
                    '()' +
                    '{' +
                    'var args = toArr(arguments);' +
                    'return this.initialize ? this.initialize.apply(this, args) || this : this;' +
                    '};'
                )(toArr)
              } catch (e) {
                /* eslint-disable no-empty */
              }
            }
            inherits(ctor, parent)
            ctor.prototype.constructor = ctor
            ctor.extend = function (methods, statics) {
              return makeClass(ctor, methods, statics)
            }
            ctor.inherits = function (Class) {
              inherits(ctor, Class)
            }
            ctor.methods = function (methods) {
              extend(ctor.prototype, methods)
              return ctor
            }
            ctor.statics = function (statics) {
              extend(ctor, statics)
              return ctor
            }
            ctor.methods(methods).statics(statics)
            return ctor
          }
          var Base = (exports.Base = makeClass(Object, {
            className: 'Base',
            callSuper: function (parent, name, args) {
              var superMethod = parent.prototype[name]
              return superMethod.apply(this, args)
            },
            toString: function () {
              return this.constructor.name
            },
          }))
  
          return exports
        })({}))
  
        /* ------------------------------ Select ------------------------------ */
  
        var Select = (_licia.Select = (function (exports) {
          /* Simple wrapper of querySelectorAll to make dom selection easier.
           *
           * ### constructor
           *
           * |Name    |Desc               |
           * |--------|-------------------|
           * |selector|Dom selector string|
           *
           * ### find
           *
           * Get desdendants of current matched elements.
           *
           * |Name    |Desc               |
           * |--------|-------------------|
           * |selector|Dom selector string|
           *
           * ### each
           *
           * Iterate over matched elements.
           *
           * |Name|Desc                                |
           * |----|------------------------------------|
           * |fn  |Function to execute for each element|
           */
  
          /* example
           * const $test = new Select('#test');
           * $test.find('.test').each(function(idx, element) {
           *     // Manipulate dom nodes
           * });
           */
  
          /* typescript
           * export declare class Select {
           *     constructor(selector: string | Element | Document);
           *     find(selector: string): Select;
           *     each(fn: types.AnyFn): Select;
           * }
           */
  
          /* dependencies
           * Class isStr each types mergeArr
           */
          exports = Class({
            className: 'Select',
            initialize: function (selector) {
              this.length = 0
              if (!selector) return this
              if (isStr(selector)) return rootSelect.find(selector)
              if (selector.nodeType) {
                this[0] = selector
                this.length = 1
              }
            },
            find: function (selector) {
              var ret = new exports()
              this.each(function () {
                mergeArr(ret, this.querySelectorAll(selector))
              })
              return ret
            },
            each: function (fn) {
              each(this, function (element, idx) {
                fn.call(element, idx, element)
              })
              return this
            },
          })
          var rootSelect = new exports(document)
  
          return exports
        })({}))
  
        /* ------------------------------ $safeEls ------------------------------ */
  
        var $safeEls = (_licia.$safeEls = (function (exports) {
          /* Convert value into an array, if it's a string, do querySelector.
           *
           * |Name  |Desc             |
           * |------|-----------------|
           * |val   |Value to convert |
           * |return|Array of elements|
           */
  
          /* example
           * $safeEls(document.querySelector('.test'));
           * $safeEls(document.querySelectorAll('.test'));
           * $safeEls('.test'); // -> Array of elements with test class
           */
  
          /* typescript
           * export declare namespace $safeEls {
           *     type El = Element | Element[] | NodeListOf<Element> | string;
           * }
           * export declare function $safeEls(val: $safeEls.El): Element[];
           */
  
          /* dependencies
           * isStr toArr Select
           */
          exports = function (val) {
            return toArr(isStr(val) ? new Select(val) : val)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $attr ------------------------------ */
  
        var $attr = (_licia.$attr = (function (exports) {
          /* Element attribute manipulation.
           *
           * Get the value of an attribute for the first element in the set of matched elements.
           *
           * |Name   |Desc                            |
           * |-------|--------------------------------|
           * |element|Elements to manipulate          |
           * |name   |Attribute name                  |
           * |return |Attribute value of first element|
           *
           * Set one or more attributes for the set of matched elements.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |name   |Attribute name        |
           * |val    |Attribute value       |
           *
           * |Name      |Desc                                  |
           * |----------|--------------------------------------|
           * |element   |Elements to manipulate                |
           * |attributes|Object of attribute-value pairs to set|
           *
           * ### remove
           *
           * Remove an attribute from each element in the set of matched elements.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |name   |Attribute name        |
           */
  
          /* example
           * $attr('#test', 'attr1', 'test');
           * $attr('#test', 'attr1'); // -> test
           * $attr.remove('#test', 'attr1');
           * $attr('#test', {
           *     attr1: 'test',
           *     attr2: 'test'
           * });
           */
  
          /* typescript
           * export declare namespace $attr {
           *     function remove(element: $safeEls.El, name: string): void;
           * }
           * export declare function $attr(
           *     element: $safeEls.El,
           *     name: string,
           *     value: string
           * ): void;
           * export declare function $attr(
           *     element: $safeEls.El,
           *     attributes: types.PlainObj<string>
           * ): void;
           * export declare function $attr(element: $safeEls.El, name: string): string;
           */
  
          /* dependencies
           * toArr isObj isStr each isUndef $safeEls types
           */
          exports = function (els, name, val) {
            els = $safeEls(els)
            var isGetter = isUndef(val) && isStr(name)
            if (isGetter) return getAttr(els[0], name)
            var attrs = name
            if (!isObj(attrs)) {
              attrs = {}
              attrs[name] = val
            }
            setAttr(els, attrs)
          }
          exports.remove = function (els, names) {
            els = $safeEls(els)
            names = toArr(names)
            each(els, function (node) {
              each(names, function (name) {
                node.removeAttribute(name)
              })
            })
          }
          function getAttr(el, name) {
            return el.getAttribute(name)
          }
          function setAttr(els, attrs) {
            each(els, function (el) {
              each(attrs, function (val, name) {
                el.setAttribute(name, val)
              })
            })
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $css ------------------------------ */
  
        var $css = (_licia.$css = (function (exports) {
          /* Element css manipulation.
           *
           * Get the computed style properties for the first element in the set of matched elements.
           *
           * |Name   |Desc                      |
           * |-------|--------------------------|
           * |element|Elements to manipulate    |
           * |name   |Property name             |
           * |return |Css value of first element|
           *
           * Set one or more CSS properties for the set of matched elements.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |name   |Property name         |
           * |val    |Css value             |
           *
           * |Name      |Desc                            |
           * |----------|--------------------------------|
           * |element   |Elements to manipulate          |
           * |properties|Object of css-value pairs to set|
           */
  
          /* example
           * $css('#test', {
           *     color: '#fff',
           *     background: 'black',
           *     opacity: 0.5
           * });
           * $css('#test', 'display', 'block');
           * $css('#test', 'color'); // -> #fff
           */
  
          /* typescript
           * export declare function $css(element: $safeEls.El, name: string): string;
           * export declare function $css(
           *     element: $safeEls.El,
           *     name: string,
           *     val: string
           * ): void;
           * export declare function $css(
           *     element: $safeEls.El,
           *     properties: types.PlainObj<string | number>
           * ): void;
           */
  
          /* dependencies
           * isStr isObj kebabCase isUndef contain isNum $safeEls prefix each types
           */
          exports = function (nodes, name, val) {
            nodes = $safeEls(nodes)
            var isGetter = isUndef(val) && isStr(name)
            if (isGetter) return getCss(nodes[0], name)
            var css = name
            if (!isObj(css)) {
              css = {}
              css[name] = val
            }
            setCss(nodes, css)
          }
          function getCss(node, name) {
            return node.style[prefix(name)] || getComputedStyle(node, '').getPropertyValue(name)
          }
          function setCss(nodes, css) {
            each(nodes, function (node) {
              var cssText = ';'
              each(css, function (val, key) {
                key = prefix.dash(key)
                cssText += key + ':' + addPx(key, val) + ';'
              })
              node.style.cssText += cssText
            })
          }
          var cssNumProps = [
            'column-count',
            'columns',
            'font-weight',
            'line-weight',
            'opacity',
            'z-index',
            'zoom',
          ]
          function addPx(key, val) {
            var needPx = isNum(val) && !contain(cssNumProps, kebabCase(key))
            return needPx ? val + 'px' : val
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $data ------------------------------ */
  
        var $data = (_licia.$data = (function (exports) {
          /* Wrapper of $attr, adds data- prefix to keys.
           */
  
          /* example
           * $data('#test', 'attr1', 'eustia');
           */
  
          /* typescript
           * export declare function $data(
           *     element: $safeEls.El,
           *     name: string,
           *     value: string
           * ): void;
           * export declare function $data(
           *     element: $safeEls.El,
           *     attributes: types.PlainObj<string>
           * ): void;
           * export declare function $data(element: $safeEls.El, name: string): string;
           */
  
          /* eslint-disable no-unused-vars */
  
          /* dependencies
           * $attr isStr isObj each $safeEls types
           */
          exports = function (nodes, name, val) {
            var dataName = name
            if (isStr(name)) dataName = 'data-' + name
            if (isObj(name)) {
              dataName = {}
              each(name, function (val, key) {
                dataName['data-' + key] = val
              })
            }
            return $attr(nodes, dataName, val)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $insert ------------------------------ */
  
        var $insert = (_licia.$insert = (function (exports) {
          /* Insert html on different position.
           *
           * ### before
           *
           * Insert content before elements.
           *
           * ### after
           *
           * Insert content after elements.
           *
           * ### prepend
           *
           * Insert content to the beginning of elements.
           *
           * ### append
           *
           * Insert content to the end of elements.
           *
           * |Name   |Desc                   |
           * |-------|-----------------------|
           * |element|Elements to manipulate |
           * |content|Html strings or element|
           */
  
          /* example
           * // <div id="test"><div class="mark"></div></div>
           * $insert.before('#test', '<div>licia</div>');
           * // -> <div>licia</div><div id="test"><div class="mark"></div></div>
           * $insert.after('#test', '<div>licia</div>');
           * // -> <div id="test"><div class="mark"></div></div><div>licia</div>
           * $insert.prepend('#test', '<div>licia</div>');
           * // -> <div id="test"><div>licia</div><div class="mark"></div></div>
           * $insert.append('#test', '<div>licia</div>');
           * // -> <div id="test"><div class="mark"></div><div>licia</div></div>
           */
  
          /* typescript
           * export declare namespace $insert {
           *     type IInsert = (element: $safeEls.El, content: string | Element) => void;
           * }
           * export declare const $insert: {
           *     before: $insert.IInsert;
           *     after: $insert.IInsert;
           *     append: $insert.IInsert;
           *     prepend: $insert.IInsert;
           * };
           */
  
          /* dependencies
           * each $safeEls isStr
           */
          exports = {
            before: insertFactory('beforebegin'),
            after: insertFactory('afterend'),
            append: insertFactory('beforeend'),
            prepend: insertFactory('afterbegin'),
          }
          function insertFactory(type) {
            return function (nodes, val) {
              nodes = $safeEls(nodes)
              each(nodes, function (node) {
                if (isStr(val)) {
                  node.insertAdjacentHTML(type, val)
                } else {
                  var parentNode = node.parentNode
                  switch (type) {
                    case 'beforebegin':
                      if (parentNode) {
                        parentNode.insertBefore(val, node)
                      }
                      break
                    case 'afterend':
                      if (parentNode) {
                        parentNode.insertBefore(val, node.nextSibling)
                      }
                      break
                    case 'beforeend':
                      node.appendChild(val)
                      break
                    case 'afterbegin':
                      node.prepend(val)
                      break
                  }
                }
              })
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $offset ------------------------------ */
  
        var $offset = (_licia.$offset = (function (exports) {
          /* Get the position of the element in document.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to get offset|
           * |return |Element position      |
           */
  
          /* example
           * $offset('#test'); // -> {left: 0, top: 0, width: 0, height: 0}
           */
  
          /* typescript
           * export declare namespace $offset {
           *     interface IOffset {
           *         left: number;
           *         top: number;
           *         width: number;
           *         height: number;
           *     }
           * }
           * export declare function $offset(element: $safeEls.El): $offset.IOffset;
           */
  
          /* dependencies
           * $safeEls
           */
          exports = function (els) {
            els = $safeEls(els)
            var el = els[0]
            var clientRect = el.getBoundingClientRect()
            return {
              left: clientRect.left + window.pageXOffset,
              top: clientRect.top + window.pageYOffset,
              width: Math.round(clientRect.width),
              height: Math.round(clientRect.height),
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $property ------------------------------ */
  
        var $property = (_licia.$property = (function (exports) {
          /* Element property html, text, val getter and setter.
           *
           * ### html
           *
           * Get the HTML contents of the first element in the set of matched elements or
           * set the HTML contents of every matched element.
           *
           * ### text
           *
           * Get the combined text contents of each element in the set of matched
           * elements, including their descendants, or set the text contents of the
           * matched elements.
           *
           * ### val
           *
           * Get the current value of the first element in the set of matched elements or
           * set the value of every matched element.
           */
  
          /* example
           * $property.html('#test', 'licia');
           * $property.html('#test'); // -> licia
           */
  
          /* typescript
           * export declare namespace $property {
           *     interface IProperty {
           *         (element: $safeEls.El, value: string): void;
           *         (element: $safeEls.El): string;
           *     }
           * }
           * export declare const $property: {
           *     html: $property.IProperty;
           *     val: $property.IProperty;
           *     text: $property.IProperty;
           * };
           */
  
          /* dependencies
           * isUndef each $safeEls
           */
          exports = {
            html: propFactory('innerHTML'),
            text: propFactory('textContent'),
            val: propFactory('value'),
          }
          function propFactory(name) {
            return function (nodes, val) {
              nodes = $safeEls(nodes)
              var node = nodes[0]
              if (isUndef(val)) {
                return node ? node[name] : ''
              }
              if (!node) return
              each(nodes, function (node) {
                node[name] = val
              })
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $remove ------------------------------ */
  
        var $remove = (_licia.$remove = (function (exports) {
          /* Remove the set of matched elements from the DOM.
           *
           * |Name   |Desc              |
           * |-------|------------------|
           * |element|Elements to delete|
           */
  
          /* example
           * $remove('#test');
           */
  
          /* typescript
           * export declare function $remove(element: $safeEls.El);
           */
  
          /* dependencies
           * each $safeEls
           */
          exports = function (els) {
            els = $safeEls(els)
            each(els, function (el) {
              var parent = el.parentNode
              if (parent) parent.removeChild(el)
            })
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $show ------------------------------ */
  
        var $show = (_licia.$show = (function (exports) {
          /* Show elements.
           *
           * |Name   |Desc            |
           * |-------|----------------|
           * |element|Elements to show|
           */
  
          /* example
           * $show('#test');
           */
  
          /* typescript
           * export declare function $show(element: $safeEls.El): void;
           */
  
          /* dependencies
           * each $safeEls
           */
          exports = function (els) {
            els = $safeEls(els)
            each(els, function (el) {
              if (isHidden(el)) {
                el.style.display = getDefDisplay(el.nodeName)
              }
            })
          }
          function isHidden(el) {
            return getComputedStyle(el, '').getPropertyValue('display') == 'none'
          }
          var elDisplay = {}
          function getDefDisplay(elName) {
            var el, display
            if (!elDisplay[elName]) {
              el = document.createElement(elName)
              document.documentElement.appendChild(el)
              display = getComputedStyle(el, '').getPropertyValue('display')
              el.parentNode.removeChild(el)
              display == 'none' && (display = 'block')
              elDisplay[elName] = display
            }
            return elDisplay[elName]
          }
  
          return exports
        })({}))
  
        /* ------------------------------ delegate ------------------------------ */
  
        var delegate = (_licia.delegate = (function (exports) {
          /* Event delegation.
           *
           * ### add
           *
           * Add event delegation.
           *
           * |Name    |Desc          |
           * |--------|--------------|
           * |el      |Parent element|
           * |type    |Event type    |
           * |selector|Match selector|
           * |cb      |Event callback|
           *
           * ### remove
           *
           * Remove event delegation.
           */
  
          /* example
           * const container = document.getElementById('container');
           * function clickHandler() {
           *     // Do something...
           * }
           * delegate.add(container, 'click', '.children', clickHandler);
           * delegate.remove(container, 'click', '.children', clickHandler);
           */
  
          /* typescript
           * export declare const delegate: {
           *     add(el: Element, type: string, selector: string, cb: types.AnyFn): void;
           *     remove(el: Element, type: string, selector: string, cb: types.AnyFn): void;
           * };
           */
  
          /* dependencies
           * Class contain types
           */
          function retTrue() {
            return true
          }
          function retFalse() {
            return false
          }
          function trigger(e) {
            var handlers = this.events[e.type]
            var handler
            var handlerQueue = formatHandlers.call(this, e, handlers)
            e = new exports.Event(e)
            var i = 0,
              j,
              matched,
              ret
            while ((matched = handlerQueue[i++]) && !e.isPropagationStopped()) {
              e.curTarget = matched.el
              j = 0
              while ((handler = matched.handlers[j++]) && !e.isImmediatePropagationStopped()) {
                ret = handler.handler.apply(matched.el, [e])
                if (ret === false) {
                  e.preventDefault()
                  e.stopPropagation()
                }
              }
            }
          }
          function formatHandlers(e, handlers) {
            var current = e.target
            var ret = []
            var delegateCount = handlers.delegateCount
            var selector
            var matches
            var handler
            var i
            if (current.nodeType) {
              for (; current !== this; current = current.parentNode || this) {
                matches = []
                for (i = 0; i < delegateCount; i++) {
                  handler = handlers[i]
                  selector = handler.selector + ' '
                  if (matches[selector] === undefined) {
                    matches[selector] = contain(this.querySelectorAll(selector), current)
                  }
                  if (matches[selector]) matches.push(handler)
                }
                if (matches.length)
                  ret.push({
                    el: current,
                    handlers: matches,
                  })
              }
            }
            if (delegateCount < handlers.length) {
              ret.push({
                el: this,
                handlers: handlers.slice(delegateCount),
              })
            }
            return ret
          }
          exports = {
            add: function (el, type, selector, fn) {
              var handler = {
                selector: selector,
                handler: fn,
              }
              var handlers
              if (!el.events) el.events = {}
              if (!(handlers = el.events[type])) {
                handlers = el.events[type] = []
                handlers.delegateCount = 0
                el.addEventListener(
                  type,
                  function () {
                    trigger.apply(el, arguments)
                  },
                  false
                )
              }
              selector
                ? handlers.splice(handlers.delegateCount++, 0, handler)
                : handlers.push(handler)
            },
            remove: function (el, type, selector, fn) {
              var events = el.events
              if (!events || !events[type]) return
              var handlers = events[type]
              var i = handlers.length
              var handler
              while (i--) {
                handler = handlers[i]
                if ((!selector || handler.selector == selector) && handler.handler == fn) {
                  handlers.splice(i, 1)
                  if (handler.selector) {
                    handlers.delegateCount--
                  }
                }
              }
            },
            Event: Class({
              className: 'Event',
              initialize: function Event(e) {
                this.origEvent = e
              },
              isDefaultPrevented: retFalse,
              isPropagationStopped: retFalse,
              isImmediatePropagationStopped: retFalse,
              preventDefault: function () {
                var e = this.origEvent
                this.isDefaultPrevented = retTrue
                if (e && e.preventDefault) e.preventDefault()
              },
              stopPropagation: function () {
                var e = this.origEvent
                this.isPropagationStopped = retTrue
                if (e && e.stopPropagation) e.stopPropagation()
              },
              stopImmediatePropagation: function () {
                var e = this.origEvent
                this.isImmediatePropagationStopped = retTrue
                if (e && e.stopImmediatePropagation) e.stopImmediatePropagation()
                this.stopPropagation()
              },
            }),
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $event ------------------------------ */
  
        var $event = (_licia.$event = (function (exports) {
          /* bind events to certain dom elements.
           */
  
          /* example
           * function clickHandler() {
           *     // Do something...
           * }
           * $event.on('#test', 'click', clickHandler);
           * $event.off('#test', 'click', clickHandler);
           */
  
          /* typescript
           * export declare const $event: {
           *     on(
           *         element: $safeEls.El,
           *         event: string,
           *         selector: string,
           *         handler: types.AnyFn
           *     ): void;
           *     on(element: $safeEls.El, event: string, handler: types.AnyFn): void;
           *     off(
           *         element: $safeEls.El,
           *         event: string,
           *         selector: string,
           *         handler: types.AnyFn
           *     ): void;
           *     off(element: $safeEls.El, event: string, handler: types.AnyFn): void;
           * };
           */
  
          /* dependencies
           * delegate isUndef $safeEls each types
           */
          exports = {
            on: eventFactory('add'),
            off: eventFactory('remove'),
          }
          function eventFactory(type) {
            return function (nodes, event, selector, handler) {
              nodes = $safeEls(nodes)
              if (isUndef(handler)) {
                handler = selector
                selector = undefined
              }
              each(nodes, function (node) {
                delegate[type](node, event, selector, handler)
              })
            }
          }
  
          return exports
        })({}))
  
        /* ------------------------------ some ------------------------------ */
  
        var some = (_licia.some = (function (exports) {
          /* Check if predicate return truthy for any element.
           *
           * |Name     |Desc                                          |
           * |---------|----------------------------------------------|
           * |obj      |Collection to iterate over                    |
           * |predicate|Function to invoked per iteration             |
           * |ctx      |Predicate context                             |
           * |return   |True if any element passes the predicate check|
           */
  
          /* example
           * some([2, 5], function(val) {
           *     return val % 2 === 0;
           * }); // -> true
           */
  
          /* typescript
           * export declare function some<T>(
           *     list: types.List<T>,
           *     iterator?: types.ListIterator<T, boolean>,
           *     context?: any
           * ): boolean;
           * export declare function some<T>(
           *     object: types.Dictionary<T>,
           *     iterator?: types.ObjectIterator<T, boolean>,
           *     context?: any
           * ): boolean;
           */
  
          /* dependencies
           * safeCb isArrLike keys types
           */
          exports = function (obj, predicate, ctx) {
            predicate = safeCb(predicate, ctx)
            var _keys = !isArrLike(obj) && keys(obj)
            var len = (_keys || obj).length
            for (var i = 0; i < len; i++) {
              var key = _keys ? _keys[i] : i
              if (predicate(obj[key], key, obj)) return true
            }
            return false
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $class ------------------------------ */
  
        var $class = (_licia.$class = (function (exports) {
          /* Element class manipulations.
           *
           * ### add
           *
           * Add the specified class(es) to each element in the set of matched elements.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |names  |Classes to add        |
           *
           * ### has
           *
           * Determine whether any of the matched elements are assigned the given class.
           *
           * |Name   |Desc                                 |
           * |-------|-------------------------------------|
           * |element|Elements to manipulate               |
           * |name   |Class name                           |
           * |return |True if elements has given class name|
           *
           * ### toggle
           *
           * Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |name   |Class name to toggle  |
           *
           * ### remove
           *
           * Remove a single class, multiple classes, or all classes from each element in the set of matched elements.
           *
           * |Name   |Desc                  |
           * |-------|----------------------|
           * |element|Elements to manipulate|
           * |name   |Class names to remove |
           */
  
          /* example
           * $class.add('#test', 'class1');
           * $class.add('#test', ['class1', 'class2']);
           * $class.has('#test', 'class1'); // -> true
           * $class.remove('#test', 'class1');
           * $class.has('#test', 'class1'); // -> false
           * $class.toggle('#test', 'class1');
           * $class.has('#test', 'class1'); // -> true
           */
  
          /* typescript
           * export declare const $class: {
           *     add(element: $safeEls.El, name: string | string[]): void;
           *     has(element: $safeEls.El, name: string): boolean;
           *     toggle(element: $safeEls.El, name: string): void;
           *     remove(element: $safeEls.El, name: string): void;
           * };
           */
  
          /* dependencies
           * toArr some $safeEls isStr each
           */
          exports = {
            add: function (els, name) {
              els = $safeEls(els)
              var names = safeName(name)
              each(els, function (el) {
                var classList = []
                each(names, function (name) {
                  if (!exports.has(el, name)) classList.push(name)
                })
                if (classList.length !== 0) {
                  el.className += (el.className ? ' ' : '') + classList.join(' ')
                }
              })
            },
            has: function (els, name) {
              els = $safeEls(els)
              var regName = new RegExp('(^|\\s)' + name + '(\\s|$)')
              return some(els, function (el) {
                return regName.test(el.className)
              })
            },
            toggle: function (els, name) {
              els = $safeEls(els)
              each(els, function (el) {
                if (!exports.has(el, name)) return exports.add(el, name)
                exports.remove(el, name)
              })
            },
            remove: function (els, name) {
              els = $safeEls(els)
              var names = safeName(name)
              each(els, function (el) {
                each(names, function (name) {
                  el.classList.remove(name)
                })
              })
            },
          }
          function safeName(name) {
            return isStr(name) ? name.split(/\s+/) : toArr(name)
          }
  
          return exports
        })({}))
  
        /* ------------------------------ $ ------------------------------ */
        _licia.$ = (function (exports) {
          /* jQuery like style dom manipulator.
           *
           * ### Available methods
           *
           * offset, hide, show, first, last, get, eq, on, off, html, text, val, css, attr,
           * data, rmAttr, remove, addClass, rmClass, toggleClass, hasClass, append, prepend,
           * before, after
           */
  
          /* example
           * const $btn = $('#btn');
           * $btn.html('eustia');
           * $btn.addClass('btn');
           * $btn.show();
           * $btn.on('click', function() {
           *     // Do something...
           * });
           */
  
          /* typescript
           * export declare namespace $ {
           *     class $ extends Select {
           *         find(selector: string): $;
           *         each(fn: types.AnyFn): $;
           *         offset(): $offset.IOffset;
           *         hide(): $;
           *         show(): $;
           *         first(): $;
           *         last(): $;
           *         get(index: number): Element;
           *         eq(index: number): $;
           *         on(event: string, selector: string, handler: types.AnyFn): $;
           *         on(event: string, handler: types.AnyFn): $;
           *         off(event: string, selector: string, handler: types.AnyFn): $;
           *         off(event: string, handler: types.AnyFn): $;
           *         html(): string;
           *         html(value: string): $;
           *         text(): string;
           *         text(value: string): $;
           *         val(): string;
           *         val(value: string): $;
           *         css(name: string): string;
           *         css(name: string, value: string): $;
           *         css(properties: types.PlainObj<string | number>): $;
           *         attr(name: string): string;
           *         attr(name: string, value: string): $;
           *         attr(attributes: types.PlainObj<string>): $;
           *         data(name: string): string;
           *         data(name: string, value: string): $;
           *         data(attributes: types.PlainObj<string>): $;
           *         rmAttr(name: string): $;
           *         remove(): $;
           *         addClass(name: string | string[]): $;
           *         rmClass(name: string): $;
           *         toggleClass(name: string): $;
           *         hasClass(name: string): boolean;
           *         parent(): $;
           *         append(content: string | Element): $;
           *         prepend(content: string | Element): $;
           *         before(content: string | Element): $;
           *         after(content: string | Element): $;
           *     }
           * }
           * declare function $(selector: string | Element | Document): $.$;
           */
  
          /* dependencies
           * Select $offset $show $css $attr $property last $remove $data $event $class $insert isUndef isStr types
           */
          exports = function (selector) {
            return new Select(selector)
          }
          Select.methods({
            offset: function () {
              return $offset(this)
            },
            hide: function () {
              return this.css('display', 'none')
            },
            show: function () {
              $show(this)
              return this
            },
            first: function () {
              return exports(this[0])
            },
            last: function () {
              return exports(last(this))
            },
            get: function (idx) {
              return this[idx]
            },
            eq: function (idx) {
              return exports(this[idx])
            },
            on: function (event, selector, handler) {
              $event.on(this, event, selector, handler)
              return this
            },
            off: function (event, selector, handler) {
              $event.off(this, event, selector, handler)
              return this
            },
            html: function (val) {
              var result = $property.html(this, val)
              if (isUndef(val)) return result
              return this
            },
            text: function (val) {
              var result = $property.text(this, val)
              if (isUndef(val)) return result
              return this
            },
            val: function (val) {
              var result = $property.val(this, val)
              if (isUndef(val)) return result
              return this
            },
            css: function (name, val) {
              var result = $css(this, name, val)
              if (isGetter(name, val)) return result
              return this
            },
            attr: function (name, val) {
              var result = $attr(this, name, val)
              if (isGetter(name, val)) return result
              return this
            },
            data: function (name, val) {
              var result = $data(this, name, val)
              if (isGetter(name, val)) return result
              return this
            },
            rmAttr: function (name) {
              $attr.remove(this, name)
              return this
            },
            remove: function () {
              $remove(this)
              return this
            },
            addClass: function (name) {
              $class.add(this, name)
              return this
            },
            rmClass: function (name) {
              $class.remove(this, name)
              return this
            },
            toggleClass: function (name) {
              $class.toggle(this, name)
              return this
            },
            hasClass: function (name) {
              return $class.has(this, name)
            },
            parent: function () {
              return exports(this[0].parentNode)
            },
            append: function (val) {
              $insert.append(this, val)
              return this
            },
            prepend: function (val) {
              $insert.prepend(this, val)
              return this
            },
            before: function (val) {
              $insert.before(this, val)
              return this
            },
            after: function (val) {
              $insert.after(this, val)
              return this
            },
          })
          var isGetter = function (name, val) {
            return isUndef(val) && isStr(name)
          }
  
          return exports
        })({})
  
        /* ------------------------------ h ------------------------------ */
        _licia.h = (function (exports) {
          /* Create html with JavaScript.
           *
           * |Name    |Desc           |
           * |--------|---------------|
           * |tag     |Tag name       |
           * |attrs   |Attributes     |
           * |...child|Children       |
           * |return  |Created element|
           */
  
          /* example
           * const el = h(
           *     'div#test.title',
           *     {
           *         onclick: function() {},
           *         title: 'test'
           *     },
           *     'inner text'
           * );
           * document.body.appendChild(el);
           */
  
          /* typescript
           * export declare function h(
           *     tag: string,
           *     attrs?: types.PlainObj<any>,
           *     ...child: Array<string | HTMLElement>
           * ): HTMLElement;
           */
  
          /* dependencies
           * isEl isStr startWith $class $css each isFn types
           */
          exports = function (tag, attrs) {
            for (
              var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2;
              _key < _len;
              _key++
            ) {
              children[_key - 2] = arguments[_key]
            }
            if (isEl(attrs) || isStr(attrs)) {
              children.unshift(attrs)
              attrs = null
            }
            if (!attrs) attrs = {}
            var _parseTag = parseTag(tag),
              tagName = _parseTag.tagName,
              id = _parseTag.id,
              classes = _parseTag.classes
            var el = document.createElement(tagName)
            if (id) el.setAttribute('id', id)
            $class.add(el, classes)
            each(children, function (child) {
              if (isStr(child)) {
                el.appendChild(document.createTextNode(child))
              } else if (isEl(child)) {
                el.appendChild(child)
              }
            })
            each(attrs, function (val, key) {
              if (isStr(val)) {
                el.setAttribute(key, val)
              } else if (isFn(val) && startWith(key, 'on')) {
                el.addEventListener(key.slice(2), val, false)
              } else if (key === 'style') {
                $css(el, val)
              }
            })
            return el
          }
          function parseTag(tag) {
            var tagName = 'div'
            var id = ''
            var classes = []
            var words = []
            var word = ''
            for (var i = 0, len = tag.length; i < len; i++) {
              var c = tag[i]
              if (c === '#' || c === '.') {
                words.push(word)
                word = c
              } else {
                word += c
              }
            }
            words.push(word)
            for (var _i = 0, _len2 = words.length; _i < _len2; _i++) {
              word = words[_i]
              if (!word) continue
              if (startWith(word, '#')) {
                id = word.slice(1)
              } else if (startWith(word, '.')) {
                classes.push(word.slice(1))
              } else {
                tagName = word
              }
            }
            return {
              tagName: tagName,
              id: id,
              classes: classes,
            }
          }
  
          return exports
        })({})
  
        /* ------------------------------ root ------------------------------ */
        _licia.root = (function (exports) {
          /* Root object reference, `global` in nodeJs, `window` in browser. */
  
          /* typescript
           * export declare const root: any;
           */
  
          /* dependencies
           * isBrowser
           */
          exports = isBrowser ? window : global
  
          return exports
        })({})
  
        /* ------------------------------ toBool ------------------------------ */
        _licia.toBool = (function (exports) {
          /* Convert value to a boolean.
           *
           * |Name  |Desc             |
           * |------|-----------------|
           * |val   |Value to convert |
           * |return|Converted boolean|
           */
  
          /* example
           * toBool(true); // -> true
           * toBool(null); // -> false
           * toBool(1); // -> true
           * toBool(0); // -> false
           * toBool('0'); // -> false
           * toBool('1'); // -> true
           * toBool('false'); // -> false
           */
  
          /* typescript
           * export declare function toBool(val: any): boolean;
           */
  
          /* dependencies
           * isStr
           */
          exports = function (val) {
            if (isStr(val)) {
              val = val.toLowerCase()
              return val !== '0' && val !== '' && val !== 'false'
            }
            return !!val
          }
  
          return exports
        })({})
  
        return _licia
      })
  
    let domHighlighter
    let highlightConfig
    let isCssLoaded = false
    let $container
    let isHighlighterInited = false
    const showInfo = _licia.cssSupports('clip-path', 'polygon(50% 0px, 0px 100%, 100% 100%)')
    const hasTouchSupport = 'ontouchstart' in _licia.root
  
    function initDomHighlighter() {
      if (isHighlighterInited) {
        return
      }
      let container = _licia.h('div', {
        class: '__chobitsu-hide__',
        style: {
          all: 'initial',
        },
      })
      $container = _licia.$(container)
      document.documentElement.appendChild(container)
  
      let domHighlighterContainer = null
      let shadowRoot = null
      if (container.attachShadow) {
        shadowRoot = container.attachShadow({ mode: 'open' })
      } else if (container.createShadowRoot) {
        shadowRoot = container.createShadowRoot()
      }
      if (shadowRoot) {
        if (typeof GM_getResourceText == 'undefined') {
          GM.getResourceText = GM_getResourceText = async function (aResourceName) {
            let res = await (await fetch(await GM.getResourceUrl(aResourceName))).text()
            let saveRes = await GM.getValue(aResourceName)
            if (typeof saveRes === 'undefined') {
              GM.setValue(aResourceName, res)
            } else {
              return saveRes
            }
            return res
          }
        }
  
        // console.log('111111111', GM.getResourceText);
        // console.log('222222222', GM_getResourceText);
  
        const css = GM_getResourceText('lunaDomHighlighterCSS').replace(
          '/*# sourceMappingURL=luna-dom-highlighter.css.map*/',
          ''
        )
  
        // console.log(css);
  
        const style = document.createElement('style')
        style.textContent = css
        style.type = 'text/css'
        shadowRoot.appendChild(style)
        domHighlighterContainer = document.createElement('div')
        shadowRoot.appendChild(domHighlighterContainer)
      } else {
        domHighlighterContainer = document.createElement('div')
        container.appendChild(domHighlighterContainer)
        if (!isCssLoaded) {
          _licia.evalCss(css)
          isCssLoaded = true
        }
      }
  
      highlightConfig = {
        showRulers: false,
        showExtensionLines: false,
        contrastAlgorithm: 'aa',
        showInfo: showInfo,
        showStyles: true,
        showAccessibilityInfo: false,
        colorFormat: 'hex',
        contentColor: 'rgba(111, 168, 220, .66)',
        paddingColor: 'rgba(147, 196, 125, .55)',
        borderColor: 'rgba(255, 229, 153, .66)',
        marginColor: 'rgba(246, 178, 107, .66)',
        monitorResize: _licia.toBool(_licia.root.ResizeObserver),
      }
      console.log(highlightConfig)
      domHighlighter = new LunaDomHighlighter(domHighlighterContainer, highlightConfig)
  
      window.addEventListener('resize', resizeHandler)
  
      isHighlighterInited = true
    }
  
    const viewportSize = _licia.h('div', {
      class: '__chobitsu-hide__',
      style: {
        position: 'fixed',
        right: 0,
        top: 0,
        background: '#fff',
        fontSize: 13,
        opacity: 0.5,
        padding: '4px 6px',
      },
    })
    let showViewportSizeOnResize = false
  
    function resizeHandler() {
      if (!showViewportSizeOnResize) return
  
      $viewportSize.text(`${window.innerWidth}px × ${window.innerHeight}px`)
      if (viewportSizeTimer) {
        clearTimeout(viewportSizeTimer)
      } else {
        document.documentElement.appendChild(viewportSize)
      }
      viewportSizeTimer = setTimeout(() => {
        $viewportSize.remove()
        viewportSizeTimer = null
      }, 1000)
    }
    const $viewportSize = _licia.$(viewportSize)
    let viewportSizeTimer
  
    function getElementFromPoint(e) {
      if (hasTouchSupport) {
        const touch = e.touches[0] || e.changedTouches[0]
        return document.elementFromPoint(touch.clientX, touch.clientY)
      }
  
      return document.elementFromPoint(e.clientX, e.clientY)
    }
  
    function isValidNode(node) {
      if (node.nodeType === 1) {
        const className = node.getAttribute('class') || ''
        if (
          _licia.contain(className, '__chobitsu-hide__') ||
          _licia.contain(className, 'html2canvas-container')
        ) {
          return false
        }
      }
  
      const isValid = !(node.nodeType === 3 && trim(node.nodeValue || '') === '')
      if (isValid && node.parentNode) {
        return isValidNode(node.parentNode)
      }
  
      return isValid
    }
  
    function moveListener(e) {
      const node = getElementFromPoint(e)
      if (!node || !isValidNode(node)) {
        return
      }
      if (node.nodeType !== 1 && node.nodeType !== 3) return
  
      _licia.defaults(highlightConfig, {
        contentColor: 'transparent',
        paddingColor: 'transparent',
        borderColor: 'transparent',
        marginColor: 'transparent',
      })
      if (!showInfo) {
        _licia.extend(highlightConfig, {
          showInfo: false,
        })
      }
      domHighlighter.highlight(node, highlightConfig)
    }
  
    function outListener() {
      domHighlighter.hide()
    }
  
    function clicklistener(event) {
      console.log(event.target)
  
      window.disableHighlight()
  
      $('#cancelhtml2canvas').text('正在生成截图...')
  
      html2canvas(event.target, { scale: 3, allowTaint: true, useCORS: true }).then((canvas) => {
        canvas.toBlob(function (blob) {
          let url = window.URL.createObjectURL(blob)
          window.open(url)
          setTimeout(() => {
            document.onkeydown = window.keydown_listener
          }, 0);
          $('#tryhtml2canvas').show()
          $('#cancelhtml2canvas').hide()
        })
      })
    }
  
    function addEvent(type, listener) {
      document.documentElement.addEventListener(type, listener, true)
    }
  
    function removeEvent(type, listener) {
      document.documentElement.removeEventListener(type, listener, true)
    }
  
    window.enableHighlight = function () {
      initDomHighlighter()
      addEvent('mousemove', moveListener)
      addEvent('mouseout', outListener)
      addEvent('click', clicklistener)
    }
  
    window.disableHighlight = function () {
      if (isHighlighterInited) {
        domHighlighter.destroy()
        $container.remove()
        window.removeEventListener('resize', resizeHandler)
        removeEvent('mousemove', moveListener)
        removeEvent('mouseout', outListener)
        removeEvent('click', clicklistener)
        isHighlighterInited = false
      }
    }
  
    window.captureHTML = () => {
      console.log('captureHTML...')
  
      // let handle = (event) => {
      //   document.querySelector('html').removeEventListener('click', handle)
      //   console.log(event.target)
  
      //   html2canvas(event.target, { scale: 3, allowTaint: true, useCORS: true }).then((canvas) => {
      //     canvas.toBlob(function (blob) {
      //       let url = window.URL.createObjectURL(blob)
      //       window.open(url)
  
      //       $('#tryhtml2canvas').show()
      //     })
      //   })
      // }
  
      // setTimeout(() => {
      //   document.querySelector('html').addEventListener('click', handle)
      // }, 0)
  
      setTimeout(() => {
        window.keydown_listener = document.onkeydown
        document.onkeydown = (e) => {
          let keyNum = window.event ? e.keyCode : e.which
          console.log('按键:', keyNum)
          if (keyNum === 27) {
            window.disableHighlight()
            setTimeout(() => {
              document.onkeydown = window.keydown_listener
            }, 0);
            $('#tryhtml2canvas').show()
            $('#cancelhtml2canvas').hide()
          }
        }
        window.enableHighlight()
      }, 0)
  
      $('#cancelhtml2canvas').text('按 ESC 取消截图')
      $('#cancelhtml2canvas').show()
      $('#tryhtml2canvas').hide()
    }
  
    let capturediv = document.createElement('div')
    capturediv.innerHTML = `
    <div id="tryhtml2canvas"
      style="background-image: linear-gradient(0deg, #558b2f, #7cb342);cursor: pointer; opacity: 0.7; position: fixed;display: flex;bottom: 40px;right: 40px;z-index: 100001;width: 50px;height: 50px;border-radius: 50%;box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);-webkit-box-pack: center;-webkit-justify-content: center;-webkit-box-align: center;-webkit-align-items: center;">
      <div style="overflow: hidden;">
        <img
          src="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjMuMiIvPgogICAgPHBhdGggZD0iTTkgMkw3LjE3IDRINGMtMS4xIDAtMiAuOS0yIDJ2MTJjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yaC0zLjE3TDE1IDJIOXptMyAxNWMtMi43NiAwLTUtMi4yNC01LTVzMi4yNC01IDUtNSA1IDIuMjQgNSA1LTIuMjQgNS01IDV6Ii8+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPgo="
          alt="Try html2canvas" style="transform: translateX(-210px); filter: drop-shadow(210px 0 0 black);">
      </div>
    </div>
    `
    document.body.appendChild(capturediv)
  
    let canceldiv = document.createElement('div')
    canceldiv.innerHTML = `
    <div id="cancelhtml2canvas"
      style="background-color: rgba(170, 170, 170, 0.8); cursor: pointer; position: fixed; display: none; bottom: 40px; right: 40px; z-index: 100001; padding: 10px; font-size: 20px; color: darkred; box-shadow: rgba(0, 0, 0, 0.14) 0px 2px 2px 0px, rgba(0, 0, 0, 0.12) 0px 1px 5px 0px, rgba(0, 0, 0, 0.2) 0px 3px 1px -2px; -webkit-box-pack: center; justify-content: center; -webkit-box-align: center; align-items: center;">
      <div style="overflow: hidden;">按 ESC 取消截图</div>
    </div>
    `
    document.body.appendChild(canceldiv)
  
    let tryhtml2canvasE = capturediv.querySelector('#tryhtml2canvas')
    tryhtml2canvasE.onmouseenter = () => {
      tryhtml2canvasE.style.opacity = 1
    }
    tryhtml2canvasE.onmouseleave = () => {
      tryhtml2canvasE.style.opacity = 0.7
    }
  
    let isDragging = false
    let startX, startY, offsetX, offsetY
  
    const onMouseMove = (event) => {
      if (!isDragging) return
      console.log("onMouseMove")
      const currentX = event.clientX
      const currentY = event.clientY
      const dx = currentX - startX
      const dy = currentY - startY
  
      if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
        tryhtml2canvasE.style.left = `${currentX - offsetX}px`
        tryhtml2canvasE.style.top = `${currentY - offsetY}px`
        tryhtml2canvasE.removeEventListener('click', window.captureHTML)
      }
    }
  
    const onMouseDown = (event) => {
      console.log("onMouseDown")
      isDragging = true
      startX = event.clientX
      startY = event.clientY
      offsetX = startX - tryhtml2canvasE.getBoundingClientRect().left
      offsetY = startY - tryhtml2canvasE.getBoundingClientRect().top
      tryhtml2canvasE.style.cursor = 'grabbing'
      document.addEventListener('mousemove', onMouseMove)
      document.addEventListener('mouseup', onMouseUp)
    }
  
    const onMouseUp = (event) => {
      if (isDragging) {
        console.log("onMouseUp")
        isDragging = false
        tryhtml2canvasE.style.cursor = 'pointer'
        setTimeout(() => {
          tryhtml2canvasE.addEventListener('click', window.captureHTML)
        }, 0);
        document.removeEventListener('mousemove', onMouseMove)
        document.removeEventListener('mouseup', onMouseUp)
      }
    }
  
    tryhtml2canvasE.addEventListener('mousedown', onMouseDown)
    tryhtml2canvasE.addEventListener('click', window.captureHTML)
  })()