[
  {
    "path": ".gitignore",
    "content": "node_modules"
  },
  {
    "path": ".swcrc",
    "content": "{\n  \"$schema\": \"https://json.schemastore.org/swcrc\",\n  \"minify\": false\n}"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 馒头饭\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# yzhanWeather\n![npm](https://img.shields.io/npm/v/yzhanweather)\n![npm bundle size](https://img.shields.io/bundlephobia/minzip/yzhanweather)\n![npm](https://img.shields.io/npm/dt/yzhanweather)\n[![GitHub license](https://img.shields.io/github/license/mantoufan/yzhanweather)](https://github.com/mantoufan/yzhanweather/blob/main/LICENSE)\n![ie11](https://img.shields.io/badge/IE-11-skyblue)  \nPure CSS animation for sakura, rain, snow, firefly and butterfly effects, high performance without affecting SEO   \n纯 CSS 动画实现樱花、雨、雪、萤火虫和蝴蝶飞舞背景效果，高性能且不影响 SEO  \n**1kB Series Lib** Fully functional with gzip code 1kB and keep source code readable\n## Quick Start\n### Setup\n#### Node.js\n```javascript\nnpm i yzhanweather\nimport YZhanWeather from 'yzhanweather'\n```\n#### Browser\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/yzhanweather@latest/docs/yzhanweather.min.js\"></script>\n```\n### Usage\n```javascript \nconst yzhanweather = new YZhanWeather()\nyzhanweather.run('firefly') // Options: sakura | snow | firefly | rain | butterfly \nyzhanweather.run('firefly', {\n  maxDuration: 10 // Default: 10s, this option can determine the speed of animations\n})\nyzhanweather.clear() // Stop and clear all animations\nyzhanweather.destory() // Destory the instance and free up memory\n```\n## Demo\n[Online Demo](https://mantoufan.github.io/yzhanWeather/)  \n*Note: click the select on the left-top to change weather*\n\n### GIF\nsakura  \n![](https://s2.loli.net/2023/02/26/FXZwUh5pA3P6xHT.gif)\nsnow  \n![](https://s2.loli.net/2023/02/26/TKJy1qS9LHgntFC.gif)\nfirefly   \n![](https://s2.loli.net/2023/02/26/DnhjpbHgPizZrw2.gif)\nrain  \n![](https://s2.loli.net/2023/02/26/X2RjoHuw18SslxD.gif)\nbutterfly   \n![](https://s2.loli.net/2023/02/26/QlyUdq3jeRThkNZ.gif)\n \n\n## Performance comparsion\nWe use a page from madfan including a 720P video background, collect data when rendering 40 butterflies at the same time.\n- With Old Version  \n*Note: By GIF and JavaScript in **old** folder*\n![the result of old version](https://s2.loli.net/2023/02/26/tb4m3GvEHdhxCq2.jpg)\n\n- With Pure CSS Version\n![the result of new version](https://s2.loli.net/2023/02/26/v9dJaItjX1Z6Unh.jpg)\n\nNo long tasks, almost negligible CPU and GPU usage\n\n## Config\nAll config including speed, num and css tpl are in `conf.js` under the *src* folder.  \nYou could change it and then `npm run build` your own version.   \nYou can set `maxDuration` to control the speed of animations without changing the `conf.js`"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n  <title>YZhan Weather Demo</title>\n  <style>\n    select {\n      opacity: .5\n    }\n  </style>\n</head>\n\n<body>\n  <div id=\"app\">\n    <select>\n      <option value=\"bg/sakura.jpg\">sakura</option>\n      <option value=\"bg/firefly.jpg\">firefly</option>\n      <option value=\"bg/snow.jpg\">snow</option>\n      <option value=\"bg/rain.jpg\">rain</option>\n      <option value=\"bg/butterfly.jpg\">butterfly</option>\n    </select>\n    <select>\n      <option value=\"5\">3s</option>\n      <option value=\"6\">6s</option>\n      <option value=\"10\" selected>10s</option>\n      <option value=\"15\">15s</option>\n      <option value=\"20\">20s</option>\n    </select>\n  </div>\n  <script src=\"./yzhanweather.min.js\"></script>\n  <script>\n    var yzhanweather = new YZhanWeather(), sels = document.getElementsByTagName('select')\n    function changeWallpaper() {\n      yzhanweather.run(sels[0].options[sels[0].selectedIndex].text, { maxDuration: sels[1].value })\n      document.body.style.cssText = 'background: rgba(0, 0, 0, 0) url(' + sels[0].value + ') no-repeat scroll center top / cover'\n    }\n    for (var i = 0; i < sels.length; i++) sels[i].onchange = changeWallpaper\n    changeWallpaper()\n  </script>\n</body>\n\n</html>"
  },
  {
    "path": "old/mtfWeather.js",
    "content": "(function () {\n  var d = 16,\n    os = false;\n  function of() {\n    var d = document.createElement(\"div\");\n    return \"undefined\" !== typeof d.style[\"opacity\"];\n  }\n  function g(a) {\n    a();\n  }\n  function h() {\n    var a = Object.create(null);\n    for (type in {\n      Top: \"\",\n      Left: \"\",\n    }) {\n      var b = type == \"Top\" ? \"Y\" : \"X\";\n      if (typeof window[\"page\" + b + \"Offset\"] !== \"undefined\") {\n        a[type.toLowerCase()] = window[\"page\" + b + \"Offset\"];\n      } else {\n        b = document.documentElement.clientHeight\n          ? document.documentElement\n          : document.body;\n        a[type.toLowerCase()] = b[\"scroll\" + type];\n      }\n    }\n    return a;\n  }\n  function l(s) {\n    var a = document.body,\n      b;\n    if (window.innerHeight) {\n      b = window.innerHeight;\n    } else if (a.parentElement.clientHeight) {\n      b = a.parentElement.clientHeight;\n    } else if (a && a.clientHeight) {\n      b = a.clientHeight;\n    }\n    return b - (s || 0) - d; // 安全距离，避免滚动条闪现\n  }\n  function w(s) {\n    return document.documentElement.clientWidth - (s || 0) - d; //安全距离，避免滚动条闪现\n  }\n  function i(a) {\n    this.create(a);\n  }\n  var j = false;\n  g(function () {\n    j = true;\n  });\n  var f = true,\n    m,\n    c = [];\n  window.mtfWeather = function (a, b) {\n    if (a === \"play\") {\n      f = true;\n    } else if (a === \"stop\") {\n      f = false;\n    } else {\n      if (j) {\n        os = of();\n        if (m) {\n          clearInterval(m);\n        }\n        m = setInterval(function () {\n          f && c.length < b && Math.random() < 0.1 && c.push(new i(a));\n          for (var e = h().top, d = c.length - 1; d >= 0; d--)\n            if (c[d])\n              if (\n                c[d].top < e ||\n                c[d].top > e + c[d].maxTop ||\n                (os && c[d].el.style.opacity < 0.01)\n              ) {\n                c[d].remove();\n                c[d] = null;\n                c.splice(d, 1);\n              } else {\n                c[d].move();\n                c[d].draw();\n              }\n        }, 60);\n      } else\n        g(function () {\n          mtfWeather(a, b);\n        });\n    }\n  };\n  i.prototype = {\n    common: function (o) {\n      o.style.cssText =\n        \"position:absolute;display:block;z-index:99999;width:\" +\n        o.size +\n        \"px;height:\" +\n        o.size +\n        \"px\";\n    },\n    create: function (a) {\n      switch (a) {\n        case \"雪\":\n          this.el = cache.get(\n            \"./mtf/mtfWeatherPic/snow\" + Math.floor(Math.random() * 5) + \".gif\"\n          );\n          this.el.size = (Math.random() * 40 + 10) | 0;\n          this.common(this.el);\n          this.maxLeft = w(this.el.size);\n          this.maxTop = l(this.el.size);\n          this.left = Math.random() * this.maxLeft;\n          this.top = h().top + 1;\n          this.angle = 1.5;\n          this.minAngle = 1.35;\n          this.maxAngle = 1.65;\n          this.angleDelta = 0.01;\n          this.speed = 2 + Math.random();\n          break;\n        case \"蝴蝶\":\n          this.el = cache.get(\n            \"./mtf/mtfWeatherPic/butterfly\" +\n              Math.floor(Math.random() * 5) +\n              \".gif\"\n          );\n          this.el.size = (Math.random() * 10 + 8) | 0;\n          this.common(this.el);\n          this.maxLeft = w(this.el.size);\n          this.maxTop = l(this.el.size);\n          this.left = Math.random() * this.maxLeft;\n          this.top = h().top + l() / Math.floor(1 + Math.random() * 3);\n          this.angle = 0;\n          this.minAngle = 0;\n          this.maxAngle = 2;\n          this.angleDelta = 0.01;\n          this.speed = 2.5 + Math.random();\n          break;\n        case \"光\":\n          this.el = document.createElement(\"div\");\n          this.el.size = (parseInt(Math.random() * 20) + 20) | 0;\n          this.common(this.el);\n          this.el.innerHTML = \"●\";\n          this.el.style.color = \"#f9f7bd\";\n          this.el.style.fontSize = this.el.size + \"px\";\n          this.maxLeft = w(this.el.size);\n          this.maxTop = 99999999;\n          this.left = Math.random() * this.maxLeft;\n          this.top = h().top + l(this.el.size * 1.25);\n          this.angle = 0.5;\n          this.minAngle = 0.35;\n          this.maxAngle = 0.65;\n          this.angleDelta = 0.01 * Math.random();\n          this.speed = 2 + Math.random();\n          break;\n        case \"雨\":\n          this.el = document.createElement(\"div\");\n          this.el.size = 12;\n          this.common(this.el);\n          this.el.innerHTML = \"|\";\n          this.el.style.color = \"#FFFFFF\";\n          this.el.style.fontSize = this.el.size + \"px\";\n          this.maxLeft = w(this.el.size);\n          this.maxTop = l(this.el.size);\n          this.left = Math.random() * this.maxLeft;\n          this.top = h().top + 1;\n          this.angle = 1.5;\n          this.minAngle = -0.25;\n          this.maxAngle = 0.25;\n          this.angleDelta = 0.01 * Math.random();\n          this.speed = 5 + Math.random();\n          break;\n        case \"樱花\":\n        default:\n          //默认樱花\n          this.el = cache.get(\n            \"./mtf/mtfWeatherPic/sakura\" +\n              Math.floor(Math.random() * 8) +\n              \".gif\"\n          );\n          this.el.size = (Math.random() * 8 + 10) | 0;\n          this.common(this.el);\n          this.maxLeft = w(this.el.size);\n          this.maxTop = l(this.el.size);\n          this.left = Math.random() * this.maxLeft;\n          this.top = h().top + 1;\n          this.angle = 1.5;\n          this.minAngle = 1.2;\n          this.maxAngle = 1.7;\n          this.angleDelta = 0.01 * Math.random();\n          this.speed = 2 + 1.5 * Math.random();\n          break;\n      }\n      if (os) {\n        this.el.style.opacity = 0.5 + Math.random() * 0.5;\n      }\n      document.body.appendChild(this.el);\n    },\n    move: function () {\n      if (this.angle < this.minAngle || this.angle > this.maxAngle) {\n        this.angleDelta = -this.angleDelta;\n      }\n      this.angle += this.angleDelta;\n      this.left += this.speed * Math.cos(this.angle * Math.PI);\n      this.top -= this.speed * Math.sin(this.angle * Math.PI);\n      if (this.left < 0) {\n        this.left = this.maxLeft;\n      } else if (this.left > this.maxLeft) {\n        this.left = 0;\n      }\n    },\n    draw: function () {\n      this.el.style.top = Math.round(this.top) + \"px\";\n      this.el.style.left = Math.round(this.left) + \"px\";\n      if (os) {\n        this.el.style.opacity -= 0.003;\n      }\n    },\n    remove: function () {\n      document.body.removeChild(this.el);\n      this.el = null;\n    },\n  };\n  var cache = {\n    h: Object.create(null),\n    get: function (src) {\n      var el = this.h[src];\n      if (!el) {\n        el = document.createElement(\"img\");\n        el.src = src;\n        this.h[src] = el;\n      }\n      return el.cloneNode();\n    },\n  };\n})();"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"yzhanweather\",\n  \"version\": \"1.0.5\",\n  \"description\": \"Pure CSS animation for sakura, rain, snow, firefly and butterfly effects, high performance without affecting SEO. 纯 CSS 动画实现樱花、雨、雪、萤火虫和蝴蝶飞舞背景效果，高性能且不影响 SEO\",\n  \"main\": \"docs/yzhanweather.min.js\",\n  \"files\": [\n    \"docs/yzhanweather.min.js\"\n  ],\n  \"scripts\": {\n    \"build\": \"webpack --mode production\",\n    \"dev\": \"webpack-dev-server\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git@mtf.github.com:mantoufan/yzhanWeather.git\"\n  },\n  \"keywords\": [\n    \"sakura\",\n    \"rain\",\n    \"snow\",\n    \"firefly\",\n    \"butterfly\",\n    \"pure\",\n    \"css\",\n    \"js\",\n    \"library\",\n    \"performance\",\n    \"SEO\"\n  ],\n  \"author\": \"shonwu\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@swc/core\": \"^1.3.0\",\n    \"swc-loader\": \"^0.2.3\",\n    \"webpack\": \"^5.74.0\",\n    \"webpack-cli\": \"^4.10.0\",\n    \"webpack-dev-server\": \"^5.2.1\"\n  },\n  \"dependencies\": {}\n}"
  },
  {
    "path": "src/conf.js",
    "content": "const tpl = {\n  container: {\n    style: `\n      position: fixed;\n      top: 0;\n      width: 100%;\n      height: 0;\n      display: flex;\n      justify-content: space-evenly;\n      pointer-events: none;\n    `\n  },\n  fall: {\n    styles: [\n      `animation-delay: .1s;\n       animation-duration: 4s`,\n      `animation-delay: .5s;\n       animation-duration: 5s`,\n      `animation-delay: .3s;\n       animation-duration: 3s;\n       animation-name: {keyframes2}`,\n      `animation-delay: .2s;\n       animation-duration: 3.5s;\n       animation-name: {keyframes1}`,\n      `animation-delay: .9s;\n       animation-duration: 3s;\n       animation-name: {keyframes1};\n       animation-duration: 4.5s`,\n      `animation-delay: .7s;\n       animation-duration: 5.5s;\n       animation-name: {keyframes1}`,\n      `animation-delay: .4s;\n       animation-duration: 3s`,\n      `animation-delay: .6s;\n       animation-duration: 4s;\n       animation-name: {keyframes1}`,\n      `animation-delay: .5s;\n       animation-duration: 5.5s;\n       animation-name: {keyframes2};`,\n      `animation-delay: .3s;`,\n      `animation-delay: .7s;\n       animation-duration: 3.5s`,\n      `animation-delay: .5s;\n       animation-duration: 4s`,\n       `animation-delay: .15s;\n       animation-duration: 6.5s;\n       animation-name: {keyframes2};`,\n       `animation-delay: .5s;\n       animation-duration: 6.5s;\n       animation-name: {keyframes3};`,\n       `animation-delay: .55s;\n       animation-duration: 5.5s;\n       animation-name: {keyframes3};`,\n       `animation-delay: .75s;\n       animation-duration: 7.5s;\n       animation-name: {keyframes3};`,\n    ],\n    keyframes: [\n      `from {\n        opacity: .9;\n      }\n      to {\n        transform: translate(10vw, 100vh) rotateX(45deg);\n        opacity: .2;\n      }`,\n      `from {\n        opacity: .9;\n      }\n      to {\n        transform: translate(-10vw, 100vh) rotateY(45deg);\n        opacity: .2;\n      }`,\n      `from {\n        opacity: .9;\n      }\n      to {\n        transform: translate(5vw, 100vh) rotateX(-45deg);\n        opacity: .2;\n      }`,\n      `from {\n        opacity: .9;\n      }\n      to {\n        transform: translate(-5vw, 100vh) rotateX(-45deg);\n        opacity: .2;\n      }`\n    ]\n  },\n  spread: {\n    keyframes: [\n      `from {\n        transform: translateY(50vh) rotateZ(55deg) skew(5deg, 5deg);\n        opacity: .1;\n      }\n      to {\n        transform: translate(10vw, -100%) rotateZ(45deg);\n        opacity: .9;\n      }`,\n      `from {\n        transform: translateY(50vh) rotateZ(-55deg) skew(5deg, 5deg);\n        opacity: .1;\n      }\n      to {\n        transform: translate(-10vw, -100%) rotateZ(-45deg);\n        opacity: .9;\n      }`,\n      `from {\n        transform: translateY(50vh) rotateZ(155deg) skew(-5deg, 5deg);\n        opacity: .1;\n      }\n      to {\n        transform: translate(10vw, 105vh) rotateZ(145deg);\n        opacity: .9;\n      }`,\n      `from {\n        transform: translateY(50vh) rotateZ(195deg) skew(-5deg, 5deg);\n        opacity: .1;\n      }\n      to {\n        transform: translate(-10vw, 105vh) rotateZ(185deg);\n        opacity: .9;\n      }`,\n    ]\n  },\n  snow: {\n    style: `\n      width: .5vw;\n      height: .5vw;\n      border-radius: 50%;\n      background-color: white;\n      border: 1px solid #fefefe;\n      transform: translateY(-100%);\n      animation: {keyframes0} 6s linear infinite;\n    `,\n  }\n}\nexport default {\n  sakura: {\n    num: 20,\n    containerStyle: tpl.container.style,\n    style: `\n      width: 1.5vw;\n      height: 1.5vh;\n      border-radius: 50% 0;\n      background-image: linear-gradient(to right, pink, white);\n      transform: translateY(-100%);\n      animation: {keyframes0} 5s linear infinite;\n    `,\n    styles: tpl.fall.styles,\n    keyframes: tpl.fall.keyframes\n  },\n  snow: {\n    num: 60,\n    containerStyle: tpl.container.style,\n    style: tpl.snow.style,\n    styles: tpl.fall.styles,\n    keyframes: tpl.fall.keyframes\n  },\n  rain: {\n    num: 60,\n    containerStyle: tpl.container.style,\n    style: `\n      width: .2vw;\n      height: 1vw;\n      border-radius: 30%;\n      background-color: rgba(255, 255, 255, .5);\n      transform: translateY(-100%);\n      animation: {keyframes0} 6s ease-in-out infinite;\n    `,\n    styles: tpl.fall.styles,\n    keyframes: tpl.fall.keyframes\n  },\n  firefly: {\n    num: 60,\n    containerStyle: tpl.container.style,\n    style: tpl.snow.style.replace('white', '#fff06b'),\n    styles: tpl.fall.styles,\n    keyframes: tpl.spread.keyframes\n  },\n  butterfly: {\n    num: 40,\n    containerStyle: tpl.container.style,\n    html: `\n      <div class=\"wing\"></div>\n      <div class=\"wing\"></div>\n    `,\n    style: {\n      '' : `\n        display: inline-block;\n        position: relative;\n        width: 1.25vw;\n        height: 1.25vw;\n        transform: translateY(-100%);\n        animation: {keyframes0} 6s linear infinite;\n      `,\n      '::after': `\n        position: absolute;\n        content: ' ';\n        background-color: lightgoldenrodyellow;\n        border-radius: 50%;\n        display: block;\n        left: .5vw;\n        width: .25vw;\n        height: .75vw;\n      `,\n      '.wing': `\n        position: absolute;\n        width: .75vw;\n        height: .75vw;\n        animation: wing .3s infinite ease-in-out alternate;\n      `,\n      '.wing:last-child': `\n        right: 0;\n      `,\n      '.wing:last-child::after': `\n        right: .125vw;\n        left: auto;\n      `,\n      '.wing::before': `\n        position: absolute;\n        content: ' ';\n        display: block;\n        width: .6vw;\n        height: .6vw;\n        background-color: lightyellow;\n        border-radius: 50%;\n      `,\n      '.wing::after': `\n        position: absolute;\n        content: ' ';\n        display: block;\n        top: .5vw;\n        left: .12vw;\n        width: .5vw;\n        height: .5vw;\n        background-color: lightyellow;\n        border-radius: 50%;\n      `\n    },\n    keyframe: {\n      'wing': `\n        from {\n          transform: scale(.9);\n        }\n        to {\n          transform: scale(1.1);\n        }`\n    },\n    styles: tpl.fall.styles,\n    keyframes: tpl.spread.keyframes\n  }\n}"
  },
  {
    "path": "src/yzhanweather.js",
    "content": "import CONF from './conf'\nexport default class {\n  constructor() {\n    this.wrapper = document.createElement('DIV')\n    document.body.appendChild(this.wrapper)\n    this.styleSheet = this.wrapper.appendChild(document.createElement('STYLE')).sheet\n    this.container = this.wrapper.appendChild(document.createElement('DIV'))\n  }\n  uuid() {\n    return 'xxxxxxxxxx'.replace(/x/g, _ => (Math.random() * 16 | 0).toString(16))\n  }\n  createRules(rules, nameFn, ruleFn = v => v) {\n    const names = []\n    for (const rule of rules) {\n      const name = 'yz' + this.uuid()\n      names.push(name)\n      this.styleSheet.insertRule(`${nameFn(name)} { ${ruleFn(rule)} }`, 0)\n    }\n    return names\n  }\n  createRule(rule, nameFn) {\n    for (const name in rule) {\n      this.styleSheet.insertRule(`${nameFn(name)} { ${rule[name]} }`, 0)\n    }\n  }\n  createKeyfarme(rule) {\n    this.createRule(rule, n => '@keyframes ' + n)\n  }\n  createKeyfarmes(rules) {\n    return this.createRules(rules, n => '@keyframes ' + n)\n  }\n  createStyles(rules, nameFn, keyframeNames) {\n    return this.createRules(rules, nameFn, rule => rule.replace(/\\{keyframes(\\d+)\\}/g, (_, p) => keyframeNames[p]))\n  }\n  processStyles(styles, fn) {\n    const n = styles.length\n    for (let i = 0; i < n; i++) {\n      const g = styles[i].match(/animation-duration:(?<duration>.*)/)\n      if (g === null) continue\n      fn(parseFloat(g.groups.duration), g.groups.duration, i)\n    }\n  }\n  replaceStyles(styles, config) {\n    let maxDuration = 0\n    this.processStyles(styles, duration => maxDuration < duration && (maxDuration = duration))\n    this.processStyles(styles, (duration, srcDuration, i) => {\n      const newDuration = (duration / maxDuration) * config.maxDuration\n      const dstDuration = srcDuration.replace(duration, newDuration)\n      styles[i] = styles[i].replace(srcDuration, dstDuration)\n    })\n  }\n  load(type, config) {\n    let {num, html, containerStyle, style, styles, keyframe = {}, keyframes} = CONF[type]\n    this.createKeyfarme(keyframe)\n    const keyframeNames = this.createKeyfarmes(keyframes)\n    if (typeof style === 'string') style = { '': style }  \n    this.createStyles([style['']], n => '.' + (this.container.className = n) + ' div', keyframeNames)\n    this.createStyles([containerStyle], _ => '.' + this.container.className, keyframeNames)\n    this.createRule(style, n => '.' + this.container.className + ' div' + (n[0] === ':' ? '' : ' ') + n)\n    this.replaceStyles(styles, config)\n    const classNames = this.createStyles(styles, n => ' .' + this.container.className + ' .' + n, keyframeNames)\n    const fragement = document.createDocumentFragment()\n    for (let i = 0; i < num; i++) {\n      const div = document.createElement('DIV')\n      if (html) div.innerHTML = html\n      fragement.appendChild(div).className = classNames[i % classNames.length]\n    }\n    this.container.appendChild(fragement)\n  }\n  run(type, config = { maxDuration: 10 }) {\n    this.clear()\n    this.load(type, config)\n  }\n  clear() {\n    this.container.innerHTML = ''\n    while (this.styleSheet.cssRules.length) this.styleSheet.deleteRule(0)\n  }\n  destory() {\n    this.wrapper.remove()\n    this.wrapper = this.styleSheet = this.container = null\n  }\n}"
  },
  {
    "path": "webpack.config.js",
    "content": "const { resolve } = require('path')\nmodule.exports = {\n  mode: 'development',\n  entry: './src/yzhanweather.js',\n  output: {\n    filename: 'yzhanweather.min.js',\n    path: resolve('docs'),\n    library: 'YZhanWeather',\n    libraryTarget: 'umd',\n    libraryExport: 'default',\n    globalObject: 'this',\n    environment: {\n      arrowFunction: false,\n      bigIntLiteral: false,\n      const: false,\n      destructuring: false,\n      dynamicImport: false,\n      forOf: false,\n      module: false,\n      optionalChaining: false,\n      templateLiteral: false\n    }\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        include: resolve('src'),\n        use: ['swc-loader']\n      }\n    ]\n  },\n  devServer: {\n    hot: true,\n    open: true,\n    port: 3000,\n    static: resolve('docs'),\n  }\n}"
  }
]