<commit_before>(function(root, factory) {
    if(typeof define === 'function' && define.amd) {
        define([], factory);
    } else {
        root['MobileImgViewer'] = factory();
    }
}(this, function() {
	var _isShow = false;
	//构造函数
	function MobileImgViewer(opts){
		//构造函数需要的参数
		this.wrap = opts.dom;
		this.ctn = opts.ctn;
		this.backBtn = opts.backBtn || "";
		this.menu = opts.menu || [];
		//构造四步
		this.init();
		this.combine();
		this.renderDOM();
		this.bindDOM();
	}

	//menu相关
	var Menu = {
		show: function(){
			var $menu = document.getElementsByClassName("viewer-menu")[0];
			$menu.className = "viewer-menu";
		},
		hide: function(){
			var $menu = document.getElementsByClassName("viewer-menu")[0];
			$menu.className = "viewer-menu hide";
		}
	}
	//第一步 -- 初始化
	MobileImgViewer.prototype.init = function() {
		//设定窗口比率
		this.radio = document.body.scrollHeight/document.body.scrollWidth;
		//设定一页的宽度
		this.scaleW = document.body.scrollWidth;
		//设定初始的索引值
		this.idx = 0;
	};
	//第一步 -- 组合
	MobileImgViewer.prototype.combine = function(){
		var self = this;
		var list = [];
		var targetArr = self.ctn.getElementsByClassName("swipe-target");
		for(var i=0,len=targetArr.length; i<len; i++){
			list.push({
				dom: targetArr[i],
				img : targetArr[i].src,
				title: targetArr[i].title,
				width: targetArr[i].width,
				height: targetArr[i].height
			});

			//闭包绑定
			(function(i){
				targetArr[i].onclick = function(){
					self.show(list[i], i);
				}
			})(i);
		}
		self.list = list;
	}
	//第三步 -- 根据数据渲染DOM
	MobileImgViewer.prototype.renderDOM = function(){
		var data = this.list;
		var len = data.length;
		//生成节点
		var backWording = this.backBtn.toString() || "";
		var $viewer = document.createElement("div");
		$viewer.id = "viewer";
		$viewer.className = "hide";
		$viewer.innerHTML = '
\

\

<'+backWording+'[1/6]
\

...
\

\

';

		//主要图片节点
		document.getElementsByTagName("body")[0].appendChild($viewer);
		var wrap = document.getElementById("viewer-box");
		this.wrap = wrap;
		this.outer = document.createElement('ul');
		this.outer.className = "viewer-list";

		for(var i = 0; i < len; i++){
			var li = document.createElement('li');
			var item = data[i];
			li.style.width = document.body.scrollWidth +'px';
			li.style.height = (document.body.scrollHeight - 45)+ 'px';
			li.style.webkitTransform = 'translate3d('+ i*this.scaleW +'px, 0, 0)';
			if(item){
				//根据窗口的比例与图片的比例来确定
				//图片是根据宽度来等比缩放还是根据高度来等比缩放
				if(item['height']/item['width'] > this.radio){
					li.innerHTML = '';
				}else{
					li.innerHTML = '';
				}
			}
			this.outer.appendChild(li);
		}

		//菜单节点
		if(this.menu.length != 0){
			var $menu = document.createElement('ul');
			$menu.className = "viewer-menu hide";
			for(var i=0,len=this.menu.length; i<len; i++){
				var em = this.menu[i];
				var $li = document.createElement('li');
				$li.textContent = em["btn"];
				$li.addEventListener("touchend", function(e){
					em["callback"](e);
					$menu.className = "viewer-menu hide";
				});
				$menu.appendChild($li);
			}
			wrap.appendChild($menu);
		}
		//UL的宽度和画布宽度一致
		this.outer.style.width = this.scaleW +'px';
		//console.log(wrap.getElementsByClassName("viewer-head")[0]);
		wrap.style.height = document.body.scrollHeight + 'px';
		wrap.appendChild(this.outer);
	};

	MobileImgViewer.prototype.show = function(target, idx){
		var self = this;
		document.getElementById("viewer").className = "";
		setTimeout(function(){
			self.wrap.className = "anm-swipe";
		},0);
		_isShow = true;

		//隐藏不必要的节点
		var lis = self.outer.getElementsByTagName('li');
		for(var i=0;i<lis.length;i++){
			if(i == idx){
				lis[i].className = "";
			}else{
				lis[i].className = "hide";
			}
		}

		self.goIndex(idx);
		self.setIndex(idx);
	}

	MobileImgViewer.prototype.hide = function(){
		var self = this;
		document.getElementById("viewer-box").className = "";
		_isShow = false;

		//隐藏不必要的节点
		var lis = self.outer.getElementsByTagName('li');
		for(var i=0;i<lis.length;i++){
			if(i == self.idx){
				lis[i].className = "";
			}else{
				lis[i].className = "hide";
			}
		}
	}

	//改变图片张数文字
	MobileImgViewer.prototype.setIndex = function(n){
		var self = this;
		self.wrap.getElementsByClassName("viewer-count")[0].innerHTML = "["+(n+1)+"/"+self.list.length+"]"
	}

	//设置展示的图片，有动画
	MobileImgViewer.prototype.goIndex = function(n){
		var idx = this.idx;
		var lis = this.outer.getElementsByTagName('li');
		var len = this.list.length;
		var cidx;

		//如果传数字 2,3 之类可以使得直接滑动到该索引
		if(typeof n == 'number'){
			cidx = n;
		//如果是传字符则为索引的变化
		}else if(typeof n == 'string'){
			cidx = idx + n*1;
		}

		//当索引右超出
		if(cidx > len-1){
			cidx = len - 1;
		//当索引左超出
		}else if(cidx < 0){
			cidx = 0;
		}

		//保留当前索引值
		this.idx = cidx;

		//改变过渡的方式，从无动画变为有动画
		lis[cidx].style.webkitTransition = '-webkit-transform 0.2s ease-out';
		lis[cidx-1] && (lis[cidx-1].style.webkitTransition = '-webkit-transform 0.2s ease-out');
		lis[cidx+1] && (lis[cidx+1].style.webkitTransition = '-webkit-transform 0.2s ease-out');

		//改变动画后所应该的位移值
		lis[cidx].style.webkitTransform = 'translate3d(0, 0, 0)';
		lis[cidx-1] && (lis[cidx-1].style.webkitTransform = 'translate3d(-'+ this.scaleW +'px, 0, 0)');
		lis[cidx+1] && (lis[cidx+1].style.webkitTransform = 'translate3d('+ this.scaleW +'px, 0, 0)');

	};

	//第四步 -- 绑定 DOM 事件
	MobileImgViewer.prototype.bindDOM = function(){
		var self = this;
		var scaleW = self.scaleW;
		var outer = self.outer;
		var len = self.list.length;

		//手指按下的处理事件
		var startHandler = function(evt){

			//记录刚刚开始按下的时间
			self.startTime = new Date() * 1;

			//记录手指按下的坐标
			self.startX = evt.touches[0].pageX;

			//清除偏移量
			self.offsetX = 0;

			//事件对象
			var target = evt.target;
			while(target.nodeName != 'LI' && target.nodeName != 'BODY'){
				target = target.parentNode;
			}
			self.target = target;

			//隐藏不必要的节点，但要开始展示左右节点
			var lis = self.outer.getElementsByTagName('li');
			var cidx = self.idx;
			for(var i=0;i<lis.length;i++){
				if(i == cidx-1 || i == cidx || i == cidx+1){
					lis[i].className = "";
				}else{
					lis[i].className = "hide";
				}
			}

			//隐藏菜单
			Menu.hide();
		};

		//手指移动的处理事件
		var moveHandler = function(evt){
			//兼容chrome android，阻止浏览器默认行为
			evt.preventDefault();

			//计算手指的偏移量
			self.offsetX = evt.targetTouches[0].pageX - self.startX;

			var lis = outer.getElementsByTagName('li');
			//起始索引
			var i = self.idx - 1;
			//结束索引
			var m = i + 3;

			//最小化改变DOM属性
			for(i; i < m; i++){
				lis[i] && (lis[i].style.webkitTransition = '-webkit-transform 0s ease-out');
				lis[i] && (lis[i].style.webkitTransform = 'translate3d('+ ((i-self.idx)*self.scaleW + self.offsetX) +'px, 0, 0)');
			}
		};

		//手指抬起的处理事件
		var endHandler = function(evt){
			evt.preventDefault();

			//边界就翻页值
			var boundary = scaleW/6;

			//手指抬起的时间值
			var endTime = new Date() * 1;

			//所有列表项
			var lis = outer.getElementsByTagName('li');

			//当手指移动时间超过300ms 的时候，按位移算
			if(endTime - self.startTime > 300){
				if(self.offsetX >= boundary){
					self.goIndex('-1');
				}else if(self.offsetX < 0 && self.offsetX < -boundary){
					self.goIndex('+1');
				}else{
					self.goIndex('0');
				}
			}else{
				//优化
				//快速移动也能使得翻页
				if(self.offsetX > 50){
					self.goIndex('-1');
				}else if(self.offsetX < -50){
					self.goIndex('+1');
				}else{
					self.hide();
					self.goIndex('0');
				}
			}

			self.setIndex(self.idx);
		};

		//绑定事件
		outer.addEventListener('touchstart', startHandler);
		outer.addEventListener('touchmove', moveHandler);
		outer.addEventListener('touchend', endHandler);

		//滑动隐藏
		document.getElementById("viewer-box").addEventListener("webkitTransitionEnd", function(){

			if(_isShow == false){
				document.getElementById("viewer").className = "hide";
				_isShow = true;
			}else{
				//console.log(self.idx);
			}

		}, false);

		//点击隐藏
		self.wrap.getElementsByClassName("viewer-back")[0].addEventListener("touchend", function(){
			self.hide();
			Menu.hide();
		}, false);

		//menu按钮点击
		self.wrap.getElementsByClassName("viewer-more")[0].addEventListener("touchend", function(){
			var $menu = self.wrap.getElementsByClassName("viewer-menu")[0];
			if($menu.className.indexOf("hide") >= 0){
				Menu.show();
			}else{
				Menu.hide();
			}
			//viewer-menu
		}, false);
	};

	return MobileImgViewer;
}))<commit_msg>fix the bug of menu<commit_after>(function(root, factory) {
    if(typeof define === 'function' && define.amd) {
        define([], factory);
    } else {
        root['MobileImgViewer'] = factory();
    }
}(this, function() {
    var _isShow = false;
    //构造函数
    function MobileImgViewer(opts) {
        //构造函数需要的参数
        this.wrap = opts.dom;
        this.ctn = opts.ctn;
        this.backBtn = opts.backBtn || "";
        this.menu = opts.menu || [];
        //构造四步
        this.init();
        this.combine();
        this.renderDOM();
        this.bindDOM();
    }

    //menu相关
    var Menu = {
        show: function() {
            var $menu = document.getElementsByClassName("viewer-menu")[0];
            $menu.className = "viewer-menu";
        },
        hide: function() {
            var $menu = document.getElementsByClassName("viewer-menu")[0];
            $menu.className = "viewer-menu hide";
        }
    }
    //第一步 -- 初始化
    MobileImgViewer.prototype.init = function() {
        //设定窗口比率
        this.radio = document.body.scrollHeight / document.body.scrollWidth;
        //设定一页的宽度
        this.scaleW = document.body.scrollWidth;
        //设定初始的索引值
        this.idx = 0;
    };
    //第一步 -- 组合
    MobileImgViewer.prototype.combine = function() {
        var self = this;
        var list = [];
        var targetArr = self.ctn.getElementsByClassName("swipe-target");
        for(var i = 0, len = targetArr.length; i < len; i++) {
            list.push({
                dom: targetArr[i],
                img: targetArr[i].src,
                title: targetArr[i].title,
                width: targetArr[i].width,
                height: targetArr[i].height
            });

            //闭包绑定
            (function(i) {
                targetArr[i].onclick = function() {
                    self.show(list[i], i);
                }
            })(i);
        }
        self.list = list;
    }
    //第三步 -- 根据数据渲染DOM
    MobileImgViewer.prototype.renderDOM = function() {
        var data = this.list;
        var len = data.length;
        //生成节点
        var backWording = this.backBtn.toString() || "";
        var $viewer = document.createElement("div");
        $viewer.id = "viewer";
        $viewer.className = "hide";
        $viewer.innerHTML = '
\

\

<' + backWording + '[1/6]
\

...
\

\

';

        //主要图片节点
        document.getElementsByTagName("body")[0].appendChild($viewer);
        var wrap = document.getElementById("viewer-box");
        this.wrap = wrap;
        this.outer = document.createElement('ul');
        this.outer.className = "viewer-list";

        for(var i = 0; i < len; i++) {
            var li = document.createElement('li');
            var item = data[i];
            li.style.width = document.body.scrollWidth + 'px';
            li.style.height = (document.body.scrollHeight - 45) + 'px';
            li.style.webkitTransform = 'translate3d(' + i * this.scaleW + 'px, 0, 0)';
            if(item) {
                //根据窗口的比例与图片的比例来确定
                //图片是根据宽度来等比缩放还是根据高度来等比缩放
                if(item['height'] / item['width'] > this.radio) {
                    li.innerHTML = '';
                } else {
                    li.innerHTML = '';
                }
            }
            this.outer.appendChild(li);
        }

        //菜单节点
        if(this.menu.length != 0) {
            var $menu = document.createElement('ul');
            $menu.className = "viewer-menu hide";
            for(var i = 0, len = this.menu.length; i < len; i++) {
                (function(n, menu) {
                    var em = menu[n];
                    var $li = document.createElement('li');
                    $li.textContent = em["btn"];
                    $li.addEventListener("touchend", function(e) {
                        console.log(e);
                        em["callback"](e);
                        $menu.className = "viewer-menu hide";
                    });
                    $menu.appendChild($li);
                })(i, this.menu);
            }
            wrap.appendChild($menu);
        }
        //UL的宽度和画布宽度一致
        this.outer.style.width = this.scaleW + 'px';
        //console.log(wrap.getElementsByClassName("viewer-head")[0]);
        wrap.style.height = document.body.scrollHeight + 'px';
        wrap.appendChild(this.outer);
    };

    MobileImgViewer.prototype.show = function(target, idx) {
        var self = this;
        document.getElementById("viewer").className = "";
        setTimeout(function() {
            self.wrap.className = "anm-swipe";
        }, 0);
        _isShow = true;

        //隐藏不必要的节点
        var lis = self.outer.getElementsByTagName('li');
        for(var i = 0; i < lis.length; i++) {
            if(i == idx) {
                lis[i].className = "";
            } else {
                lis[i].className = "hide";
            }
        }

        self.goIndex(idx);
        self.setIndex(idx);
    }

    MobileImgViewer.prototype.hide = function() {
        var self = this;
        document.getElementById("viewer-box").className = "";
        _isShow = false;

        //隐藏不必要的节点
        var lis = self.outer.getElementsByTagName('li');
        for(var i = 0; i < lis.length; i++) {
            if(i == self.idx) {
                lis[i].className = "";
            } else {
                lis[i].className = "hide";
            }
        }
    }

    //改变图片张数文字
    MobileImgViewer.prototype.setIndex = function(n) {
        var self = this;
        self.wrap.getElementsByClassName("viewer-count")[0].innerHTML = "[" + (n + 1) + "/" + self.list.length + "]"
    }

    //设置展示的图片，有动画
    MobileImgViewer.prototype.goIndex = function(n) {
        var idx = this.idx;
        var lis = this.outer.getElementsByTagName('li');
        var len = this.list.length;
        var cidx;

        //如果传数字 2,3 之类可以使得直接滑动到该索引
        if(typeof n == 'number') {
            cidx = n;
            //如果是传字符则为索引的变化
        } else if(typeof n == 'string') {
            cidx = idx + n * 1;
        }

        //当索引右超出
        if(cidx > len - 1) {
            cidx = len - 1;
            //当索引左超出
        } else if(cidx < 0) {
            cidx = 0;
        }

        //保留当前索引值
        this.idx = cidx;

        //改变过渡的方式，从无动画变为有动画
        lis[cidx].style.webkitTransition = '-webkit-transform 0.2s ease-out';
        lis[cidx - 1] && (lis[cidx - 1].style.webkitTransition = '-webkit-transform 0.2s ease-out');
        lis[cidx + 1] && (lis[cidx + 1].style.webkitTransition = '-webkit-transform 0.2s ease-out');

        //改变动画后所应该的位移值
        lis[cidx].style.webkitTransform = 'translate3d(0, 0, 0)';
        lis[cidx - 1] && (lis[cidx - 1].style.webkitTransform = 'translate3d(-' + this.scaleW + 'px, 0, 0)');
        lis[cidx + 1] && (lis[cidx + 1].style.webkitTransform = 'translate3d(' + this.scaleW + 'px, 0, 0)');

    };

    //第四步 -- 绑定 DOM 事件
    MobileImgViewer.prototype.bindDOM = function() {
        var self = this;
        var scaleW = self.scaleW;
        var outer = self.outer;
        var len = self.list.length;

        //手指按下的处理事件
        var startHandler = function(evt) {

            //记录刚刚开始按下的时间
            self.startTime = new Date() * 1;

            //记录手指按下的坐标
            self.startX = evt.touches[0].pageX;

            //清除偏移量
            self.offsetX = 0;

            //事件对象
            var target = evt.target;
            while(target.nodeName != 'LI' && target.nodeName != 'BODY') {
                target = target.parentNode;
            }
            self.target = target;

            //隐藏不必要的节点，但要开始展示左右节点
            var lis = self.outer.getElementsByTagName('li');
            var cidx = self.idx;
            for(var i = 0; i < lis.length; i++) {
                if(i == cidx - 1 || i == cidx || i == cidx + 1) {
                    lis[i].className = "";
                } else {
                    lis[i].className = "hide";
                }
            }

            //隐藏菜单
            Menu.hide();
        };

        //手指移动的处理事件
        var moveHandler = function(evt) {
            //兼容chrome android，阻止浏览器默认行为
            evt.preventDefault();

            //计算手指的偏移量
            self.offsetX = evt.targetTouches[0].pageX - self.startX;

            var lis = outer.getElementsByTagName('li');
            //起始索引
            var i = self.idx - 1;
            //结束索引
            var m = i + 3;

            //最小化改变DOM属性
            for(i; i < m; i++) {
                lis[i] && (lis[i].style.webkitTransition = '-webkit-transform 0s ease-out');
                lis[i] && (lis[i].style.webkitTransform = 'translate3d(' + ((i - self.idx) * self.scaleW + self.offsetX) + 'px, 0, 0)');
            }
        };

        //手指抬起的处理事件
        var endHandler = function(evt) {
            evt.preventDefault();

            //边界就翻页值
            var boundary = scaleW / 6;

            //手指抬起的时间值
            var endTime = new Date() * 1;

            //所有列表项
            var lis = outer.getElementsByTagName('li');

            //当手指移动时间超过300ms 的时候，按位移算
            if(endTime - self.startTime > 300) {
                if(self.offsetX >= boundary) {
                    self.goIndex('-1');
                } else if(self.offsetX < 0 && self.offsetX < -boundary) {
                    self.goIndex('+1');
                } else {
                    self.goIndex('0');
                }
            } else {
                //优化
                //快速移动也能使得翻页
                if(self.offsetX > 50) {
                    self.goIndex('-1');
                } else if(self.offsetX < -50) {
                    self.goIndex('+1');
                } else {
                    self.hide();
                    self.goIndex('0');
                }
            }

            self.setIndex(self.idx);
        };

        //绑定事件
        outer.addEventListener('touchstart', startHandler);
        outer.addEventListener('touchmove', moveHandler);
        outer.addEventListener('touchend', endHandler);

        //滑动隐藏
        document.getElementById("viewer-box").addEventListener("webkitTransitionEnd", function() {

            if(_isShow == false) {
                document.getElementById("viewer").className = "hide";
                _isShow = true;
            } else {
                //console.log(self.idx);
            }

        }, false);

        //点击隐藏
        self.wrap.getElementsByClassName("viewer-back")[0].addEventListener("touchend", function() {
            self.hide();
            Menu.hide();
        }, false);

        //menu按钮点击
        self.wrap.getElementsByClassName("viewer-more")[0].addEventListener("touchend", function() {
            var $menu = self.wrap.getElementsByClassName("viewer-menu")[0];
            if($menu.className.indexOf("hide") >= 0) {
                Menu.show();
            } else {
                Menu.hide();
            }
            //viewer-menu
        }, false);
    };

    return MobileImgViewer;
}))<|endoftext|>


<commit_before>module.exports = (context, opts = {}) => {
  const env = process.env.BABEL_ENV || process.env.NODE_ENV
  const isDevelopment = env === 'development'
  const useTypescript = opts.typescript

  return {
    presets: [
      // Browsers are taken from the browserslist field in package.json
      [
        require('@babel/preset-env').default,
        {
          modules: false,
          useBuiltIns: 'usage',
          // Enable stage 4 proposals, like array.flatMap
          shippedProposals: true,
          // Use new corejs version
          corejs: { version: 3, proposals: true },
        },
      ],
      [
        require('@babel/preset-react').default,
        {
          // Adds component stack to warning messages
          // Adds __self attribute to JSX which React will use for some warnings
          development: isDevelopment,
          // Will use the native built-in instead of trying to polyfill
          // behavior for any plugins that require one.
          useBuiltIns: true,
        },
      ],
      ...(useTypescript ? [require('@babel/preset-typescript').default] : []),
    ],
    plugins: [
      require('babel-plugin-lodash'),
      require('babel-plugin-macros'),

      // ----------- Stage 0 -----------
      require('@babel/plugin-proposal-function-bind').default,

      // ----------- Stage 1 -----------
      require('@babel/plugin-proposal-export-default-from').default,
      require('@babel/plugin-proposal-logical-assignment-operators').default,
      require('@babel/plugin-proposal-optional-chaining').default,
      [require('@babel/plugin-proposal-pipeline-operator').default, { proposal: 'smart' }],
      require('@babel/plugin-proposal-nullish-coalescing-operator').default,
      require('@babel/plugin-proposal-do-expressions').default,

      // ----------- Stage 2 -----------
      // Use the default proposal when it will be finalized
      [require('@babel/plugin-proposal-decorators').default, { legacy: true }],
      require('@babel/plugin-proposal-function-sent').default,
      require('@babel/plugin-proposal-export-namespace-from').default,
      require('@babel/plugin-proposal-numeric-separator').default,
      require('@babel/plugin-proposal-throw-expressions').default,

      // ----------- Stage 3 -----------
      require('@babel/plugin-syntax-dynamic-import').default,
      require('@babel/plugin-syntax-import-meta').default,
      // Enable loose mode to use assignment instead of defineProperty
      // See discussion in https://github.com/facebook/create-react-app/issues/4263
      [require('@babel/plugin-proposal-class-properties').default, { loose: true }],
      require('@babel/plugin-proposal-json-strings').default,
    ],
  }
}
<commit_msg>fix: 🔨  Use correct pipeline proposal<commit_after>module.exports = (context, opts = {}) => {
  const env = process.env.BABEL_ENV || process.env.NODE_ENV
  const isDevelopment = env === 'development'
  const useTypescript = opts.typescript

  return {
    presets: [
      // Browsers are taken from the browserslist field in package.json
      [
        require('@babel/preset-env').default,
        {
          modules: false,
          useBuiltIns: 'usage',
          // Enable stage 4 proposals, like array.flatMap
          shippedProposals: true,
          // Use new corejs version
          corejs: { version: 3, proposals: true },
        },
      ],
      [
        require('@babel/preset-react').default,
        {
          // Adds component stack to warning messages
          // Adds __self attribute to JSX which React will use for some warnings
          development: isDevelopment,
          // Will use the native built-in instead of trying to polyfill
          // behavior for any plugins that require one.
          useBuiltIns: true,
        },
      ],
      ...(useTypescript ? [require('@babel/preset-typescript').default] : []),
    ],
    plugins: [
      require('babel-plugin-lodash'),
      require('babel-plugin-macros'),

      // ----------- Stage 0 -----------
      require('@babel/plugin-proposal-function-bind').default,

      // ----------- Stage 1 -----------
      require('@babel/plugin-proposal-export-default-from').default,
      require('@babel/plugin-proposal-logical-assignment-operators').default,
      require('@babel/plugin-proposal-optional-chaining').default,
      [require('@babel/plugin-proposal-pipeline-operator').default, { proposal: 'minimal' }],
      require('@babel/plugin-proposal-nullish-coalescing-operator').default,
      require('@babel/plugin-proposal-do-expressions').default,

      // ----------- Stage 2 -----------
      // Use the default proposal when it will be finalized
      [require('@babel/plugin-proposal-decorators').default, { legacy: true }],
      require('@babel/plugin-proposal-function-sent').default,
      require('@babel/plugin-proposal-export-namespace-from').default,
      require('@babel/plugin-proposal-numeric-separator').default,
      require('@babel/plugin-proposal-throw-expressions').default,

      // ----------- Stage 3 -----------
      require('@babel/plugin-syntax-dynamic-import').default,
      require('@babel/plugin-syntax-import-meta').default,
      // Enable loose mode to use assignment instead of defineProperty
      // See discussion in https://github.com/facebook/create-react-app/issues/4263
      [require('@babel/plugin-proposal-class-properties').default, { loose: true }],
      require('@babel/plugin-proposal-json-strings').default,
    ],
  }
}
<|endoftext|>


<commit_before>/* eslint dot-notation: 0 */
/* eslint global-require: 0 */
global.shellStartTime = Date.now();
var util = require('util')

console.inspect = function consoleInspect(val) {
  console.log(util.inspect(val, true, depth=7, colorize=true));
}

const app = require('electron').app;
const path = require('path');
const mkdirp = require('mkdirp');

if (typeof process.setFdLimit === 'function') {
  process.setFdLimit(1024);
}

const setupConfigDir = (args) => {
  let defaultDirName = ".nylas-mail";
  if (args.devMode) {
    defaultDirName = ".nylas-dev";
  }
  if (args.specMode) {
    defaultDirName = ".nylas-spec";
  }
  let configDirPath = path.join(app.getPath('home'), defaultDirName);

  if (args.configDirPath) {
    configDirPath = args.configDirPath;
  } else if (process.env.NYLAS_HOME) {
    configDirPath = process.env.NYLAS_HOME;
  }

  mkdirp.sync(configDirPath);
  process.env.NYLAS_HOME = configDirPath;
  return configDirPath;
};

const setupCompileCache = (configDirPath) => {
  const compileCache = require('../compile-cache');
  return compileCache.setHomeDirectory(configDirPath);
};

const setupErrorLogger = (args = {}) => {
  const ErrorLogger = require('../error-logger');
  const errorLogger = new ErrorLogger({
    inSpecMode: args.specMode,
    inDevMode: args.devMode,
    resourcePath: args.resourcePath,
  });
  process.on('uncaughtException', errorLogger.reportError);
  process.on('unhandledRejection', errorLogger.reportError);
  return errorLogger;
};

const declareOptions = (argv) => {
  const optimist = require('optimist');
  const options = optimist(argv);
  options.usage("Nylas Mail v" + (app.getVersion()) + "\n\nUsage: n1 [options]\n\nRun N1: The open source extensible email client\n\n`n1 --dev` to start the client in dev mode.\n\n`n1 --test` to run unit tests.");
  options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.');
  options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.');
  options.boolean('safe').describe('safe', 'Do not load packages from ~/.nylas-mail/packages or ~/.nylas/dev/packages.');
  options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.');
  options.alias('l', 'log-file').string('l').describe('l', 'Log all test output to file.');
  options.alias('c', 'config-dir-path').string('c').describe('c', 'Override the path to the N1 configuration directory');
  options.alias('s', 'spec-directory').string('s').describe('s', 'Override the directory from which to run package specs');
  options.alias('f', 'spec-file-pattern').string('f').describe('f', 'Override the default file regex to determine which tests should run (defaults to "-spec\.(coffee|js|jsx|cjsx|es6|es)$" )');
  options.alias('v', 'version').boolean('v').describe('v', 'Print the version.');
  options.alias('b', 'background').boolean('b').describe('b', 'Start N1 in the background');
  return options;
};

const parseCommandLine = (argv) => {
  const version = app.getVersion();
  const options = declareOptions(argv.slice(1));
  const args = options.argv;

  if (args.help) {
    process.stdout.write(options.help());
    process.exit(0);
  }
  if (args.version) {
    process.stdout.write(version + "\n");
    process.exit(0);
  }
  const devMode = args['dev'] || args['test'];
  const logFile = args['log-file'];
  const specMode = args['test'];
  const jUnitXmlPath = args['junit-xml'];
  const safeMode = args['safe'];
  const background = args['background'];
  const configDirPath = args['config-dir-path'];
  const specDirectory = args['spec-directory'];
  const specFilePattern = args['spec-file-pattern'];
  const showSpecsInWindow = specMode === "window";
  const resourcePath = path.resolve(args['resource-path'] != null ? args['resource-path'] : path.dirname(path.dirname(__dirname)));
  const urlsToOpen = [];
  const pathsToOpen = [];

  // On Windows and Linux, mailto and file opens are passed in argv. Go through
  // the items and pluck out things that look like mailto:, nylas:, file paths
  let ignoreNext = false;
  for (let i = 1; i < argv.length; i ++) {
    const arg = argv[i];
    if (ignoreNext) {
      ignoreNext = false;
      continue;
    }
    if (arg.includes('executed-from') || arg.includes('squirrel')) {
      ignoreNext = true;
      continue;
    }
    if (arg === resourcePath) {
      continue;
    }
    if (arg.startsWith('mailto:') || arg.startsWith('nylas:')) {
      urlsToOpen.push(arg);
    } else if ((arg[0] !== '-') && (/[\/|\\]/.test(arg))) {
      pathsToOpen.push(arg);
    }
  }

  if (args['path-environment']) {
    process.env.PATH = args['path-environment'];
  }

  return {
    version,
    devMode,
    background,
    logFile,
    specMode,
    jUnitXmlPath,
    safeMode,
    configDirPath,
    specDirectory,
    specFilePattern,
    showSpecsInWindow,
    resourcePath,
    urlsToOpen,
    pathsToOpen,
  };
};

const handleStartupEventWithSquirrel = () => {
  if (process.platform !== 'win32') {
    return false;
  }
  const options = {
    allowEscalation: false,
    registerDefaultIfPossible: false,
  };

  const WindowsUpdater = require('./windows-updater');
  const squirrelCommand = process.argv[1];

  switch (squirrelCommand) {
    case '--squirrel-install':
      WindowsUpdater.createRegistryEntries(options, () =>
        WindowsUpdater.createShortcuts(() =>
          app.quit()
        )
      )
      return true
    case '--squirrel-updated':
      WindowsUpdater.createRegistryEntries(options, () =>
        WindowsUpdater.updateShortcuts(() =>
          app.quit()
        )
      )
      return true
    case '--squirrel-uninstall':
      WindowsUpdater.removeShortcuts(() =>
        app.quit()
      )
      return true
    case '--squirrel-obsolete':
      app.quit()
      return true
    default:
      return false
  }
};

const start = () => {
  app.setAppUserModelId('com.squirrel.nylas.nylas');
  if (handleStartupEventWithSquirrel()) {
    return;
  }

  const options = parseCommandLine(process.argv);

  if (!options.devMode) {
    const otherInstanceRunning = app.makeSingleInstance((commandLine) => {
      const otherOpts = parseCommandLine(commandLine);
      global.application.handleLaunchOptions(otherOpts);
    });

    if (otherInstanceRunning) {
      console.log("Exiting because another instance of the app is already running.")
      app.quit();
    }
  }

  global.errorLogger = setupErrorLogger(options);
  const configDirPath = setupConfigDir(options);
  options.configDirPath = configDirPath;
  setupCompileCache(configDirPath);

  const onOpenFileBeforeReady = (event, file) => {
    event.preventDefault();
    options.pathsToOpen.push(file);
  };

  const onOpenUrlBeforeReady = (event, url) => {
    event.preventDefault();
    options.urlsToOpen.push(url);
  };

  app.on('open-url', onOpenUrlBeforeReady);
  app.on('open-file', onOpenFileBeforeReady);
  app.on('ready', () => {
    app.removeListener('open-file', onOpenFileBeforeReady);
    app.removeListener('open-url', onOpenUrlBeforeReady);
    const Application = require(path.join(options.resourcePath, 'src', 'browser', 'application')).default;
    global.application = new Application();
    global.application.start(options);
    if (!options.specMode) {
      console.log("App load time: " + (Date.now() - global.shellStartTime) + "ms");
    }
  });
};

start();
<commit_msg>fix(cli): s/n1/nylas-mail/<commit_after>/* eslint dot-notation: 0 */
/* eslint global-require: 0 */
global.shellStartTime = Date.now();
var util = require('util')

console.inspect = function consoleInspect(val) {
  console.log(util.inspect(val, true, depth=7, colorize=true));
}

const app = require('electron').app;
const path = require('path');
const mkdirp = require('mkdirp');

if (typeof process.setFdLimit === 'function') {
  process.setFdLimit(1024);
}

const setupConfigDir = (args) => {
  let defaultDirName = ".nylas-mail";
  if (args.devMode) {
    defaultDirName = ".nylas-dev";
  }
  if (args.specMode) {
    defaultDirName = ".nylas-spec";
  }
  let configDirPath = path.join(app.getPath('home'), defaultDirName);

  if (args.configDirPath) {
    configDirPath = args.configDirPath;
  } else if (process.env.NYLAS_HOME) {
    configDirPath = process.env.NYLAS_HOME;
  }

  mkdirp.sync(configDirPath);
  process.env.NYLAS_HOME = configDirPath;
  return configDirPath;
};

const setupCompileCache = (configDirPath) => {
  const compileCache = require('../compile-cache');
  return compileCache.setHomeDirectory(configDirPath);
};

const setupErrorLogger = (args = {}) => {
  const ErrorLogger = require('../error-logger');
  const errorLogger = new ErrorLogger({
    inSpecMode: args.specMode,
    inDevMode: args.devMode,
    resourcePath: args.resourcePath,
  });
  process.on('uncaughtException', errorLogger.reportError);
  process.on('unhandledRejection', errorLogger.reportError);
  return errorLogger;
};

const declareOptions = (argv) => {
  const optimist = require('optimist');
  const options = optimist(argv);
  options.usage("Nylas Mail v" + (app.getVersion()) + "\n\nUsage: nylas-mail [options]\n\nRun Nylas Mail: The open source extensible email client\n\n`nylas-mail --dev` to start the client in dev mode.\n\n`n1 --test` to run unit tests.");
  options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.');
  options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.');
  options.boolean('safe').describe('safe', 'Do not load packages from ~/.nylas-mail/packages or ~/.nylas/dev/packages.');
  options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.');
  options.alias('l', 'log-file').string('l').describe('l', 'Log all test output to file.');
  options.alias('c', 'config-dir-path').string('c').describe('c', 'Override the path to the Nylas Mail configuration directory');
  options.alias('s', 'spec-directory').string('s').describe('s', 'Override the directory from which to run package specs');
  options.alias('f', 'spec-file-pattern').string('f').describe('f', 'Override the default file regex to determine which tests should run (defaults to "-spec\.(coffee|js|jsx|cjsx|es6|es)$" )');
  options.alias('v', 'version').boolean('v').describe('v', 'Print the version.');
  options.alias('b', 'background').boolean('b').describe('b', 'Start Nylas Mail in the background');
  return options;
};

const parseCommandLine = (argv) => {
  const version = app.getVersion();
  const options = declareOptions(argv.slice(1));
  const args = options.argv;

  if (args.help) {
    process.stdout.write(options.help());
    process.exit(0);
  }
  if (args.version) {
    process.stdout.write(version + "\n");
    process.exit(0);
  }
  const devMode = args['dev'] || args['test'];
  const logFile = args['log-file'];
  const specMode = args['test'];
  const jUnitXmlPath = args['junit-xml'];
  const safeMode = args['safe'];
  const background = args['background'];
  const configDirPath = args['config-dir-path'];
  const specDirectory = args['spec-directory'];
  const specFilePattern = args['spec-file-pattern'];
  const showSpecsInWindow = specMode === "window";
  const resourcePath = path.resolve(args['resource-path'] != null ? args['resource-path'] : path.dirname(path.dirname(__dirname)));
  const urlsToOpen = [];
  const pathsToOpen = [];

  // On Windows and Linux, mailto and file opens are passed in argv. Go through
  // the items and pluck out things that look like mailto:, nylas:, file paths
  let ignoreNext = false;
  for (let i = 1; i < argv.length; i ++) {
    const arg = argv[i];
    if (ignoreNext) {
      ignoreNext = false;
      continue;
    }
    if (arg.includes('executed-from') || arg.includes('squirrel')) {
      ignoreNext = true;
      continue;
    }
    if (arg === resourcePath) {
      continue;
    }
    if (arg.startsWith('mailto:') || arg.startsWith('nylas:')) {
      urlsToOpen.push(arg);
    } else if ((arg[0] !== '-') && (/[\/|\\]/.test(arg))) {
      pathsToOpen.push(arg);
    }
  }

  if (args['path-environment']) {
    process.env.PATH = args['path-environment'];
  }

  return {
    version,
    devMode,
    background,
    logFile,
    specMode,
    jUnitXmlPath,
    safeMode,
    configDirPath,
    specDirectory,
    specFilePattern,
    showSpecsInWindow,
    resourcePath,
    urlsToOpen,
    pathsToOpen,
  };
};

const handleStartupEventWithSquirrel = () => {
  if (process.platform !== 'win32') {
    return false;
  }
  const options = {
    allowEscalation: false,
    registerDefaultIfPossible: false,
  };

  const WindowsUpdater = require('./windows-updater');
  const squirrelCommand = process.argv[1];

  switch (squirrelCommand) {
    case '--squirrel-install':
      WindowsUpdater.createRegistryEntries(options, () =>
        WindowsUpdater.createShortcuts(() =>
          app.quit()
        )
      )
      return true
    case '--squirrel-updated':
      WindowsUpdater.createRegistryEntries(options, () =>
        WindowsUpdater.updateShortcuts(() =>
          app.quit()
        )
      )
      return true
    case '--squirrel-uninstall':
      WindowsUpdater.removeShortcuts(() =>
        app.quit()
      )
      return true
    case '--squirrel-obsolete':
      app.quit()
      return true
    default:
      return false
  }
};

const start = () => {
  app.setAppUserModelId('com.squirrel.nylas.nylas');
  if (handleStartupEventWithSquirrel()) {
    return;
  }

  const options = parseCommandLine(process.argv);

  if (!options.devMode) {
    const otherInstanceRunning = app.makeSingleInstance((commandLine) => {
      const otherOpts = parseCommandLine(commandLine);
      global.application.handleLaunchOptions(otherOpts);
    });

    if (otherInstanceRunning) {
      console.log("Exiting because another instance of the app is already running.")
      app.quit();
    }
  }

  global.errorLogger = setupErrorLogger(options);
  const configDirPath = setupConfigDir(options);
  options.configDirPath = configDirPath;
  setupCompileCache(configDirPath);

  const onOpenFileBeforeReady = (event, file) => {
    event.preventDefault();
    options.pathsToOpen.push(file);
  };

  const onOpenUrlBeforeReady = (event, url) => {
    event.preventDefault();
    options.urlsToOpen.push(url);
  };

  app.on('open-url', onOpenUrlBeforeReady);
  app.on('open-file', onOpenFileBeforeReady);
  app.on('ready', () => {
    app.removeListener('open-file', onOpenFileBeforeReady);
    app.removeListener('open-url', onOpenUrlBeforeReady);
    const Application = require(path.join(options.resourcePath, 'src', 'browser', 'application')).default;
    global.application = new Application();
    global.application.start(options);
    if (!options.specMode) {
      console.log("App load time: " + (Date.now() - global.shellStartTime) + "ms");
    }
  });
};

start();
<|endoftext|>


<commit_before>import isString from 'lodash/isString'
import {v4 as uuid} from 'uuid'

import randomChar from '../helpers/random-char'

export default function Schedule(data={}) {
	const baseSchedule = {
		id: uuid(),
		active: false,

		index: 1,
		title: `Schedule ${randomChar().toUpperCase()}`,

		clbids: [],
		year: 0,
		semester: 0,
	}

	let schedule = {
		...baseSchedule,
		...data,
	}

	if (!isString(schedule.id)) {
		throw new TypeError('Schedule id must be a string.')
	}

	if (typeof schedule.year === 'string') {
		schedule.year = parseInt(schedule.year, 10)
	}

	if (typeof schedule.semester === 'string') {
		schedule.semester = parseInt(schedule.semester, 10)
	}

	return schedule
}
<commit_msg>add metadata to schedules<commit_after>import isString from 'lodash/isString'
import {v4 as uuid} from 'uuid'

import randomChar from '../helpers/random-char'

export default function Schedule(data={}) {
	const baseSchedule = {
		id: uuid(),
		active: false,

		index: 1,
		title: `Schedule ${randomChar().toUpperCase()}`,

		clbids: [],
		year: 0,
		semester: 0,

		metadata: {},
	}

	let schedule = {
		...baseSchedule,
		...data,
	}

	if (!isString(schedule.id)) {
		throw new TypeError('Schedule id must be a string.')
	}

	if (typeof schedule.year === 'string') {
		schedule.year = parseInt(schedule.year, 10)
	}

	if (typeof schedule.semester === 'string') {
		schedule.semester = parseInt(schedule.semester, 10)
	}

	return schedule
}
<|endoftext|>


<commit_before>module.exports = (bot, logger, helper) => {
  const Whatanime = require('whatanimega-helper')

  const Format = class {
    constructor (time) {
      this.time = time
      return true
    }
    get hour () {
      return this.pad(Math.floor(this.time / (60 * 60)))
    }
    get min () {
      return this.pad(Math.floor(this.time % (60 * 60) / 60))
    }
    get sec () {
      return this.pad(Math.floor(this.time % 60))
    }
    pad (s) {
      return (s < 10 ? '0' : '') + s
    }
  }

  bot.on('message', async (msg) => {
    if (Math.round((new Date()).getTime() / 1000) - msg.date >= 180) return
    let photo
    if (!msg.photo) {
      if (!/^(?:무슨애니|whatanime|\/무슨애니|\/whatanime|무슨애니\?|anime)$/.test(msg.text) ||
        !msg.reply_to_message || !msg.reply_to_message.photo) {
        const chatid = msg.chat.id
        let temp
        try {
          // eslint-disable-next-line
          let send
          [send, temp] = await Promise.all([
            bot.sendChatAction(chatid, 'typing'),
            helper.getlang(msg, logger)
          ])
          await bot.sendMessage(chatid, '📺❗ ' + temp.text(msg.chat.type, 'command.whatanime.info'), {
            reply_to_message_id: msg.message_id,
            parse_mode: 'HTML',
            reply_markup: {
              force_reply: true, selective: true
            }
          })
          logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: valid,')
        } catch (e) {
          logger.error('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
          logger.debug(e.stack)
        }
        return
      } else {
        photo = msg.reply_to_message.photo[msg.reply_to_message.photo.length - 1].file_id
      }
    } else {
      if (!/^(?:무슨애니|whatanime|\/무슨애니|\/whatanime|무슨애니\?|anime)$/.test(msg.caption)) {
        if (!msg.reply_to_message && !msg.reply_to_message.photo &&
          msg.reply_to_message.from.username !== global.botinfo.username &&
          !msg.reply_to_message.text.match(/📺❗/)) {
          const chatid = msg.chat.id
          let temp
          try {
            // eslint-disable-next-line
            let send
            [send, temp] = await Promise.all([
              bot.sendChatAction(chatid, 'typing'),
              helper.getlang(msg, logger)
            ])
            await bot.sendMessage(chatid, '📺❗ ' + temp.text(msg.chat.type, 'command.whatanime.info'), {
              reply_to_message_id: msg.message_id,
              parse_mode: 'HTML',
              reply_markup: {
                force_reply: true, selective: true
              }
            })
            logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: valid,')
          } catch (e) {
            logger.error('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
            logger.debug(e.stack)
          }
          return
        } else {
          photo = msg.photo[msg.photo.length - 1].file_id
        }
      } else {
        photo = msg.photo[msg.photo.length - 1].file_id
      }
    }

    const chatid = msg.chat.id
    let temp
    try {
      logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: command received')
      // eslint-disable-next-line
      let send
      [send, temp] = await Promise.all([
        bot.sendChatAction(chatid, 'typing'),
        helper.getlang(msg, logger)
      ])

      const query = new Whatanime(global.config.apikey.whatanime)

      const url = await bot.getFileLink(photo)
      const response = await query.search(url)
      const result = response.docs[0]
      let resultMessage = ''
      if (result.anime.toLowerCase() !== result.title_english.toLowerCase()) {
        resultMessage = temp.textb(msg.chat.type, 'command.whatanime.name') + ': ' + result.title + '\n' +
          temp.textb(msg.chat.type, 'command.whatanime.english') + ': ' + result.title_english + '\n'
      } else {
        resultMessage = temp.textb(msg.chat.type, 'command.whatanime.name') + ': ' + result.anime + '\n'
      }
      const time = new Format(result.at)
      resultMessage = resultMessage +
        temp.textb(msg.chat.type, 'command.whatanime.episode') + ' ' + result.episode + '\n' +
        temp.textb(msg.chat.type, 'command.whatanime.time') + ': ' +
        (time.hour === '00' ? '' : time.hour + ' : ') + time.min + ' : ' + time.sec + '\n' +
        temp.textb(msg.chat.type, 'command.whatanime.match') + ': ' + (result.similarity * 100).toFixed(2) + '%'
      if (result.similarity > 70) {
        await bot.sendMessage(chatid, resultMessage + '\n' + temp.text(msg.chat.type, 'command.whatanime.incorrect'), {
          parse_mode: 'HTML',
          disable_web_page_preview: true,
          reply_to_message_id: msg.message_id
        })
      } else {
        const animeVideo = await query.previewVideo(result.season, result.anime, result.filename, result.at, result.tokenthumb)
        await Promise.all([
          bot.sendMessage(chatid, resultMessage, {
            parse_mode: 'HTML',
            disable_web_page_preview: true,
            reply_to_message_id: msg.message_id
          }),
          bot.sendVideo(chatid, animeVideo, {
            reply_to_message_id: msg.message_id
          })
        ])
      }
      logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: valid')
    } catch (e) {
      logger.error('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
      logger.debug(e.stack)
    }
  })
}
<commit_msg>오류 수정<commit_after>module.exports = (bot, logger, helper) => {
  const Whatanime = require('whatanimega-helper')

  const Format = class {
    constructor (time) {
      this.time = time
      return true
    }
    get hour () {
      return this.pad(Math.floor(this.time / (60 * 60)))
    }
    get min () {
      return this.pad(Math.floor(this.time % (60 * 60) / 60))
    }
    get sec () {
      return this.pad(Math.floor(this.time % 60))
    }
    pad (s) {
      return (s < 10 ? '0' : '') + s
    }
  }

  const failure = async (chatid, msg) => {
    let temp
    try {
      // eslint-disable-next-line
      let send
      [send, temp] = await Promise.all([
        bot.sendChatAction(chatid, 'typing'),
        helper.getlang(msg, logger)
      ])
      await bot.sendMessage(chatid, '📺❗ ' + temp.text(msg.chat.type, 'command.whatanime.info'), {
        reply_to_message_id: msg.message_id,
        parse_mode: 'HTML',
        reply_markup: {
          force_reply: true, selective: true
        }
      })
      logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: valid,')
    } catch (e) {
      logger.error('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
      logger.debug(e.stack)
    }
  }

  const success = async (chatid, msg, photo) => {
    let temp
    try {
      logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: command received')
      // eslint-disable-next-line
      let send
      [send, temp] = await Promise.all([
        bot.sendChatAction(chatid, 'typing'),
        helper.getlang(msg, logger)
      ])

      const query = new Whatanime(global.config.apikey.whatanime)

      const url = await bot.getFileLink(photo)
      const response = await query.search(url)
      const result = response.docs[0]
      let resultMessage = ''
      if (result.anime.toLowerCase() !== result.title_english.toLowerCase()) {
        resultMessage = temp.textb(msg.chat.type, 'command.whatanime.name') + ': ' + result.title + '\n' +
          temp.textb(msg.chat.type, 'command.whatanime.english') + ': ' + result.title_english + '\n'
      } else {
        resultMessage = temp.textb(msg.chat.type, 'command.whatanime.name') + ': ' + result.anime + '\n'
      }
      const time = new Format(result.at)
      resultMessage = resultMessage +
        temp.textb(msg.chat.type, 'command.whatanime.episode') + ' ' + result.episode + '\n' +
        temp.textb(msg.chat.type, 'command.whatanime.time') + ': ' +
        (time.hour === '00' ? '' : time.hour + ' : ') + time.min + ' : ' + time.sec + '\n' +
        temp.textb(msg.chat.type, 'command.whatanime.match') + ': ' + (result.similarity * 100).toFixed(2) + '%'
      if (result.similarity > 70) {
        await bot.sendMessage(chatid, resultMessage + '\n' + temp.text(msg.chat.type, 'command.whatanime.incorrect'), {
          parse_mode: 'HTML',
          disable_web_page_preview: true,
          reply_to_message_id: msg.message_id
        })
      } else {
        const animeVideo = await query.previewVideo(result.season, result.anime, result.filename, result.at, result.tokenthumb)
        await Promise.all([
          bot.sendMessage(chatid, resultMessage, {
            parse_mode: 'HTML',
            disable_web_page_preview: true,
            reply_to_message_id: msg.message_id
          }),
          bot.sendVideo(chatid, animeVideo, {
            reply_to_message_id: msg.message_id
          })
        ])
      }
      logger.info('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: valid')
    } catch (e) {
      logger.error('chatid: ' + chatid + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
      logger.debug(e.stack)
    }
  }

  bot.on('message', async (msg) => {
    try {
      if (Math.round((new Date()).getTime() / 1000) - msg.date >= 180) return
      if (!msg.photo) {
        if (/^(?:무슨애니|whatanime|\/무슨애니|\/whatanime|무슨애니\?|anime)$/.test(msg.text) &&
          msg.reply_to_message && msg.reply_to_message.photo) {
          await success(msg.chat.id, msg, msg.reply_to_message.photo[msg.reply_to_message.photo.length - 1].file_id)
        } else if (/^\/(?:무슨애니|whatanime)$/.test(msg.text)) {
          await failure(msg.chat.id, msg)
        }
      } else {
        if (!/^(?:무슨애니|whatanime|\/무슨애니|\/whatanime|무슨애니\?|anime)$/.test(msg.caption)) {
          if (!msg.reply_to_message && !msg.reply_to_message.photo &&
            msg.reply_to_message.from.username !== global.botinfo.username) {
            if (!msg.reply_to_message.text.match(/📺❗/)) {
              await failure(msg.chat.id, msg)
            } else {
              await success(msg.chat.id, msg, msg.photo[msg.photo.length - 1].file_id)
            }
          } else {
            await success(msg.chat.id, msg, msg.photo[msg.photo.length - 1].file_id)
          }
        }
      }
    } catch (e) {
      logger.error('chatid: ' + msg.chat.id + ', username: ' + helper.getuser(msg.from) + ', lang: ' + msg.from.language_code + ', command: whatanime, type: error')
      logger.debug(e.stack)
    }
  })
}
<|endoftext|>


<commit_before>// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

// Here we generate the /dist files that allow widget embedding

var path = require('path');

var version = require('./package.json').version;

var rules = [
  { test: /\.css$/, use: ['style-loader', 'css-loader'] },
  // jquery-ui loads some images
  { test: /\.(jpg|png|gif)$/, use: 'file-loader' },
  // required to load font-awesome
  {
    test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/font-woff',
      },
    },
  },
  {
    test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/font-woff',
      },
    },
  },
  {
    test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/octet-stream',
      },
    },
  },
  { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: 'file-loader' },
  {
    test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'image/svg+xml',
      },
    },
  },
];

var publicPath =
  'https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@' +
  version +
  '/dist/';

module.exports = [
  {
    // script that renders widgets using the standard embedding and can only render standard controls
    entry: './lib/embed.js',
    output: {
      filename: 'embed.js',
      path: path.resolve(__dirname, 'dist'),
      publicPath: publicPath,
    },
    devtool: 'source-map',
    module: { rules: rules },
    mode: 'production',
  },
  {
    // script that renders widgets using the amd embedding and can render third-party custom widgets
    entry: './lib/embed-amd-render.js',
    output: {
      filename: 'embed-amd-render.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
    },
    module: { rules: rules },
    mode: 'production',
  },
  {
    // embed library that depends on requirejs, and can load third-party widgets dynamically
    entry: './lib/libembed-amd.js',
    output: {
      library: '@jupyter-widgets/html-manager/dist/libembed-amd',
      filename: 'libembed-amd.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    mode: 'production',
  },
  {
    // @jupyter-widgets/html-manager
    entry: './lib/index.js',
    output: {
      library: '@jupyter-widgets/html-manager',
      filename: 'index.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    externals: ['@jupyter-widgets/base', '@jupyter-widgets/controls'],
    mode: 'production',
  },
  {
    // @jupyter-widgets/base
    entry: '@jupyter-widgets/base/lib/index',
    output: {
      library: '@jupyter-widgets/base',
      filename: 'base.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    mode: 'production',
  },
  {
    // @jupyter-widgets/controls
    entry: '@jupyter-widgets/controls/lib/index',
    output: {
      library: '@jupyter-widgets/controls',
      filename: 'controls.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    externals: ['@jupyter-widgets/base'],
    mode: 'production',
  },
];
<commit_msg>Attempt to fixing docs's "process is not defined" issue<commit_after>// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

// Here we generate the /dist files that allow widget embedding

var path = require('path');
var webpack = require('webpack');

var version = require('./package.json').version;

var rules = [
  { test: /\.css$/, use: ['style-loader', 'css-loader'] },
  // jquery-ui loads some images
  { test: /\.(jpg|png|gif)$/, use: 'file-loader' },
  // required to load font-awesome
  {
    test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/font-woff',
      },
    },
  },
  {
    test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/font-woff',
      },
    },
  },
  {
    test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'application/octet-stream',
      },
    },
  },
  { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: 'file-loader' },
  {
    test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
    use: {
      loader: 'url-loader',
      options: {
        limit: 10000,
        mimetype: 'image/svg+xml',
      },
    },
  },
];

var publicPath =
  'https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@' +
  version +
  '/dist/';

var plugins = [
  new webpack.DefinePlugin({
    // Needed for Blueprint. See https://github.com/palantir/blueprint/issues/4393
    'process.env': '{}',
    // Needed for various packages using cwd(), like the path polyfill
    process: { cwd: () => '/' },
  }),
];

module.exports = [
  {
    // script that renders widgets using the standard embedding and can only render standard controls
    entry: './lib/embed.js',
    output: {
      filename: 'embed.js',
      path: path.resolve(__dirname, 'dist'),
      publicPath: publicPath,
    },
    devtool: 'source-map',
    module: { rules: rules },
    mode: 'production',
    plugins: plugins,
  },
  {
    // script that renders widgets using the amd embedding and can render third-party custom widgets
    entry: './lib/embed-amd-render.js',
    output: {
      filename: 'embed-amd-render.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
    },
    module: { rules: rules },
    mode: 'production',
    plugins: plugins,
  },
  {
    // embed library that depends on requirejs, and can load third-party widgets dynamically
    entry: './lib/libembed-amd.js',
    output: {
      library: '@jupyter-widgets/html-manager/dist/libembed-amd',
      filename: 'libembed-amd.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    mode: 'production',
    plugins: plugins,
  },
  {
    // @jupyter-widgets/html-manager
    entry: './lib/index.js',
    output: {
      library: '@jupyter-widgets/html-manager',
      filename: 'index.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    externals: ['@jupyter-widgets/base', '@jupyter-widgets/controls'],
    mode: 'production',
    plugins: plugins,
  },
  {
    // @jupyter-widgets/base
    entry: '@jupyter-widgets/base/lib/index',
    output: {
      library: '@jupyter-widgets/base',
      filename: 'base.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    mode: 'production',
    plugins: plugins,
  },
  {
    // @jupyter-widgets/controls
    entry: '@jupyter-widgets/controls/lib/index',
    output: {
      library: '@jupyter-widgets/controls',
      filename: 'controls.js',
      path: path.resolve(__dirname, 'dist', 'amd'),
      publicPath: publicPath,
      libraryTarget: 'amd',
    },
    module: { rules: rules },
    externals: ['@jupyter-widgets/base'],
    mode: 'production',
    plugins: plugins,
  },
];
<|endoftext|>


<commit_before>
const exampleGroups = [
  {
    title: 'Explorable Explanations',
    examples: [
      {
        label: 'The Math of Card Shuffling',
        subtitle: "Riffling from factory order to complete randomness.",
        href: 'https://fredhohman.com/card-shuffling/',
        image: 'cards.png',
        sourceUrl: "https://github.com/fredhohman/card-shuffling"
      },
      {
        label: 'How to Tune a Guitar',
        subtitle: "An interactive audio guide with guitars and a little music theory.",
        href: 'https://mathisonian.github.io/idyll/how-to-tune-a-guitar/',
        image: 'how-to-tune-a-guitar.png'
      },
      {
        label: 'The Barnes-Hut Approximation',
        subtitle: "Efficient computation of N-body forces",
        href: 'https://jheer.github.io/barnes-hut/',
        image: 'barnes-hut.png',
        sourceUrl: "https://github.com/jheer/barnes-hut"
      },
      {
        label: 'Kernel Density Estimation',
        subtitle: 'An interactive explanation of the statistical technique',
        href: 'https://mathisonian.github.io/kde/',
        image: 'kde.png',
        sourceUrl: "https://github.com/mathisonian/kde"
      },
      {
        label: 'The Etymology of Trig Functions',
        subtitle: 'A graphic walkthrough of mathematical history',
        href: 'https://mathisonian.github.io/trig/etymology/',
        image: 'trig.png',
        sourceUrl: "https://github.com/mathisonian/trig/"
      },
      {
        label: 'Travelling Salesman Algorithms',
        subtitle: 'From Naive to Christofide',
        href: 'https://cse442-17f.github.io/Traveling-Salesman-Algorithms/',
        image: 'travelling-salesman.png'
      },
      {
        label: 'Multi-Armed Bandits',
        subtitle: 'An exploration of epsilon greedy and UCB1 algorithms',
        href: 'https://cse442-17f.github.io/LinUCB/',
        image: 'multi-armed-bandits.png'
      },
      {
        label: 'The Explanation & Comparison of Graph Searches',
        subtitle: 'A walkthrough of depth first, breadth first, and A* search algorithms',
        href: 'https://cse442-17f.github.io/A-Star-Search/',
        image: 'a-star-2.png'
      },
      {
        label: 'Stepping Into the Filter',
        subtitle: "Understanding the edge detection algorithms in your smartphone",
        href: 'https://cse442-17f.github.io/Sobel-Laplacian-and-Canny-Edge-Detection-Algorithms/',
        image: 'sobel-3.png'
      },
      {
        label: 'Sequence Alignment with Dynamic Programming',
        subtitle: 'The Smith-Waterman Algorithm',
        href: 'https://cse442-17f.github.io/Prims-and-A-Star/',
        image: 'smith-waterman.png'
      },
      {
        label: 'Conflict Driven Clause Learning',
        subtitle: 'The Boolean Satisfiability Problem',
        href: 'https://cse442-17f.github.io/Conflict-Driven-Clause-Learning/',
        image: 'conflict-driven.png'
      },
      {
        label: 'Efficient Collision Detection',
        subtitle: "The Gilbert-Johnson-Keerthi distance algorithm",
        href: 'https://cse442-17f.github.io/Gilbert-Johnson-Keerthi-Distance-Algorithm/',
        image: 'collision.png'
      },
    ],
  },
  {
    title : 'Articles and Blog Posts',
    examples: [
      {
        label: 'A Comic Introduction to Idyll',
        subtitle: 'See how Idyll can be used with CSS grid to create a comic-style layout.',
        href: 'https://mathisonian.github.io/idyll-comic/',
        image: 'https://mathisonian.github.io/idyll-comic/static/share.png',
        sourceUrl: "https://github.com/mathisonian/idyll-comic/"
      },
      {
        label: 'Autumn Colormaps',
        subtitle: 'A look at trees, colormaps, and chroma.js',
        href: 'https://mathisonian.github.io/idyll/fall-colors/',
        image: 'https://mathisonian.github.io/idyll/fall-colors/images/share.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/fall-colors"
      },
      {
        label: 'Who Shapes the Open Web?',
        subtitle: 'An interactive tool to explore membership in W3C working groups.',
        href: 'https://mathisonian.github.io/who-shapes-the-open-web/',
        image: 'https://mathisonian.github.io/who-shapes-the-open-web//images/share.png',
        sourceUrl: "https://github.com/mathisonian/who-shapes-the-open-web/"
      },
      {
        label: 'From Nothing to Something in WebGL Using regl',
        href: 'https://rreusser.github.io/from-nothing-to-something-in-webgl-with-regl/',
        image: 'hello-regl.png',
        sourceUrl: "https://github.com/rreusser/rreusser.github.io/tree/master/src/src/from-nothing-to-something-in-webgl-with-regl"
      },
      {
        label: 'Seattle PD’s Dashcam Problem',
        subtitle: 'Visualizing 27 million frames of video lost over four years',
        href: 'https://mathisonian.github.io/dashcam/',
        image: 'https://mathisonian.github.io/dashcam/images/share.png',
        sourceUrl: "https://github.com/mathisonian/dashcam"
      },
      {
        label: 'The United Complaints of America',
        subtitle: 'Analyzing over 700,000 complaints sent to the Consumer Financial Protection Bureau',
        href: 'https://mathisonian.github.io/consumer-complaints/',
        image: 'complaints-2.gif',
        sourceUrl: 'https://github.com/mathisonian/consumer-complaints'
      },
      {
        label: 'Lorenz Attractor',
        href: 'https://mathisonian.github.io/lorenz/',
        image: 'lorenz.png',
        sourceUrl: 'https://github.com/mathisonian/lorenz'
      },
      {
        label: 'Nonlinear Sliders',
        href: 'https://mathisonian.github.io/idyll/nonlinear-sliders/',
        image: 'nonlinear.png',
        sourceUrl: 'https://github.com/mathisonian/idyll/tree/master/nonlinear-sliders'
      },
    ]
  },
  {
    title: 'Tutorials',
    examples: [{
      label: 'Announcing idyll.pub',
      subtitle: "Publish interactive blog posts and explorable explanations with Idyll's free hosting service.",
      href: 'https://idyll.pub/post/announcing-idyll-pub-0a3eff0661df3446a915700d/',
      image: 'https://idyll.pub/post/announcing-idyll-pub-0a3eff0661df3446a915700d/static/images/share.png',
      sourceUrl: "https://github.com/mathisonian/announcing-idyll-pub"
      },{
      label: 'Scaffolding Interactives',
      subtitle: 'Rapidly create scroll- and step-based interactives with Idyll',
      href: 'https://mathisonian.github.io/idyll/scaffolding-interactives/',
      image: 'scaffolding-interactives.gif',
      sourceUrl: "https://github.com/mathisonian/scaffolding-interactives"
      },
      {
        label: 'Take a Walk on the Idyll Side',
        subtitle: 'Exploring new ways to create interactive documents',
        href: 'https://mathisonian.github.io/idyll/a-walk-on-the-idyll-side/',
        image: 'walk-on-the-idyll-side.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/introducing-idyll"
      }, {
        label: 'D3',
        href: 'https://idyll-lang.github.io/idyll-d3-component/',
        image: 'd3.png',
        sourceUrl: "https://github.com/idyll-lang/idyll-d3-component/tree/master/examples/basic"
      },
      {
        label: 'regl',
        href: 'https://idyll-lang.github.io/idyll-regl-component/',
        image: 'regl.png',
        sourceUrl: "https://github.com/idyll-lang/idyll-regl-component/tree/master/examples/basic"
      },
      {
        label: 'Vega Lite',
        href: 'https://idyll-lang.github.io/examples/csv/',
        image: 'vl.png',
        sourceUrl: "https://github.com/idyll-lang/examples/tree/master/csv"
      },
      {
        label: 'Firebase',
        href: 'https://mathisonian.github.io/idyll/firebase/',
        image: 'firebase.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/firebase"
      },
      {
        label: 'Apparatus',
        href: 'https://mathisonian.com/writing/apparatus',
        image: 'apparatus.png',
        sourceUrl: 'https://github.com/mathisonian/mathisonian.github.io/blob/master/pages/writing/apparatus.js'
      }
    ],
  },
  // {
  //   title: 'Other examples',
  //   examples: [

  //     {
  //       label: 'Scrolly Idyll',
  //       href: 'https://idyll-lang.github.io/idyll/scroll/',
  //       image: 'scroll.gif',
  //     },
  //   ],
  // },
]

function slugify(text)
{
  return text.toString().split(/([A-Z][a-z]+)/).join('-').toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}

const indexedItems = {};
exampleGroups.forEach((group) => {
  group.examples.forEach((example) => {
    const slug = slugify(example.label);
    indexedItems[slug] = example;
  })
})

export { indexedItems };
export default exampleGroups;<commit_msg>add DR example<commit_after>
const exampleGroups = [
  {
    title: 'Explorable Explanations',
    examples: [
      {
        label: "The Beginner's Guide to Dimensionality Reduction",
        subtitle: "Explore the methods that data scientists use to visualize high-dimensional data.",
        href: 'https://idyll.pub/post/dimensionality-reduction-293e465c2a3443e8941b016d/',
        image: 'https://idyll.pub/post/dimensionality-reduction-293e465c2a3443e8941b016d/static/images/share.png',
        sourceUrl: "https://github.com/mathisonian/dimensionality-reduction"
      },
      {
        label: 'The Math of Card Shuffling',
        subtitle: "Riffling from factory order to complete randomness.",
        href: 'https://fredhohman.com/card-shuffling/',
        image: 'cards.png',
        sourceUrl: "https://github.com/fredhohman/card-shuffling"
      },
      {
        label: 'How to Tune a Guitar',
        subtitle: "An interactive audio guide with guitars and a little music theory.",
        href: 'https://mathisonian.github.io/idyll/how-to-tune-a-guitar/',
        image: 'how-to-tune-a-guitar.png'
      },
      {
        label: 'The Barnes-Hut Approximation',
        subtitle: "Efficient computation of N-body forces",
        href: 'https://jheer.github.io/barnes-hut/',
        image: 'barnes-hut.png',
        sourceUrl: "https://github.com/jheer/barnes-hut"
      },
      {
        label: 'Kernel Density Estimation',
        subtitle: 'An interactive explanation of the statistical technique',
        href: 'https://mathisonian.github.io/kde/',
        image: 'kde.png',
        sourceUrl: "https://github.com/mathisonian/kde"
      },
      {
        label: 'The Etymology of Trig Functions',
        subtitle: 'A graphic walkthrough of mathematical history',
        href: 'https://mathisonian.github.io/trig/etymology/',
        image: 'trig.png',
        sourceUrl: "https://github.com/mathisonian/trig/"
      },
      {
        label: 'Travelling Salesman Algorithms',
        subtitle: 'From Naive to Christofide',
        href: 'https://cse442-17f.github.io/Traveling-Salesman-Algorithms/',
        image: 'travelling-salesman.png'
      },
      {
        label: 'Multi-Armed Bandits',
        subtitle: 'An exploration of epsilon greedy and UCB1 algorithms',
        href: 'https://cse442-17f.github.io/LinUCB/',
        image: 'multi-armed-bandits.png'
      },
      {
        label: 'The Explanation & Comparison of Graph Searches',
        subtitle: 'A walkthrough of depth first, breadth first, and A* search algorithms',
        href: 'https://cse442-17f.github.io/A-Star-Search/',
        image: 'a-star-2.png'
      },
      {
        label: 'Stepping Into the Filter',
        subtitle: "Understanding the edge detection algorithms in your smartphone",
        href: 'https://cse442-17f.github.io/Sobel-Laplacian-and-Canny-Edge-Detection-Algorithms/',
        image: 'sobel-3.png'
      },
      {
        label: 'Sequence Alignment with Dynamic Programming',
        subtitle: 'The Smith-Waterman Algorithm',
        href: 'https://cse442-17f.github.io/Prims-and-A-Star/',
        image: 'smith-waterman.png'
      },
      {
        label: 'Conflict Driven Clause Learning',
        subtitle: 'The Boolean Satisfiability Problem',
        href: 'https://cse442-17f.github.io/Conflict-Driven-Clause-Learning/',
        image: 'conflict-driven.png'
      },
      {
        label: 'Efficient Collision Detection',
        subtitle: "The Gilbert-Johnson-Keerthi distance algorithm",
        href: 'https://cse442-17f.github.io/Gilbert-Johnson-Keerthi-Distance-Algorithm/',
        image: 'collision.png'
      },
    ],
  },
  {
    title : 'Articles and Blog Posts',
    examples: [
      {
        label: 'A Comic Introduction to Idyll',
        subtitle: 'See how Idyll can be used with CSS grid to create a comic-style layout.',
        href: 'https://mathisonian.github.io/idyll-comic/',
        image: 'https://mathisonian.github.io/idyll-comic/static/share.png',
        sourceUrl: "https://github.com/mathisonian/idyll-comic/"
      },
      {
        label: 'Autumn Colormaps',
        subtitle: 'A look at trees, colormaps, and chroma.js',
        href: 'https://mathisonian.github.io/idyll/fall-colors/',
        image: 'https://mathisonian.github.io/idyll/fall-colors/images/share.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/fall-colors"
      },
      {
        label: 'Who Shapes the Open Web?',
        subtitle: 'An interactive tool to explore membership in W3C working groups.',
        href: 'https://mathisonian.github.io/who-shapes-the-open-web/',
        image: 'https://mathisonian.github.io/who-shapes-the-open-web//images/share.png',
        sourceUrl: "https://github.com/mathisonian/who-shapes-the-open-web/"
      },
      {
        label: 'From Nothing to Something in WebGL Using regl',
        href: 'https://rreusser.github.io/from-nothing-to-something-in-webgl-with-regl/',
        image: 'hello-regl.png',
        sourceUrl: "https://github.com/rreusser/rreusser.github.io/tree/master/src/src/from-nothing-to-something-in-webgl-with-regl"
      },
      {
        label: 'Seattle PD’s Dashcam Problem',
        subtitle: 'Visualizing 27 million frames of video lost over four years',
        href: 'https://mathisonian.github.io/dashcam/',
        image: 'https://mathisonian.github.io/dashcam/images/share.png',
        sourceUrl: "https://github.com/mathisonian/dashcam"
      },
      {
        label: 'The United Complaints of America',
        subtitle: 'Analyzing over 700,000 complaints sent to the Consumer Financial Protection Bureau',
        href: 'https://mathisonian.github.io/consumer-complaints/',
        image: 'complaints-2.gif',
        sourceUrl: 'https://github.com/mathisonian/consumer-complaints'
      },
      {
        label: 'Lorenz Attractor',
        href: 'https://mathisonian.github.io/lorenz/',
        image: 'lorenz.png',
        sourceUrl: 'https://github.com/mathisonian/lorenz'
      },
      {
        label: 'Nonlinear Sliders',
        href: 'https://mathisonian.github.io/idyll/nonlinear-sliders/',
        image: 'nonlinear.png',
        sourceUrl: 'https://github.com/mathisonian/idyll/tree/master/nonlinear-sliders'
      },
    ]
  },
  {
    title: 'Tutorials',
    examples: [{
      label: 'Announcing idyll.pub',
      subtitle: "Publish interactive blog posts and explorable explanations with Idyll's free hosting service.",
      href: 'https://idyll.pub/post/announcing-idyll-pub-0a3eff0661df3446a915700d/',
      image: 'https://idyll.pub/post/announcing-idyll-pub-0a3eff0661df3446a915700d/static/images/share.png',
      sourceUrl: "https://github.com/mathisonian/announcing-idyll-pub"
      },{
      label: 'Scaffolding Interactives',
      subtitle: 'Rapidly create scroll- and step-based interactives with Idyll',
      href: 'https://mathisonian.github.io/idyll/scaffolding-interactives/',
      image: 'scaffolding-interactives.gif',
      sourceUrl: "https://github.com/mathisonian/scaffolding-interactives"
      },
      {
        label: 'Take a Walk on the Idyll Side',
        subtitle: 'Exploring new ways to create interactive documents',
        href: 'https://mathisonian.github.io/idyll/a-walk-on-the-idyll-side/',
        image: 'walk-on-the-idyll-side.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/introducing-idyll"
      }, {
        label: 'D3',
        href: 'https://idyll-lang.github.io/idyll-d3-component/',
        image: 'd3.png',
        sourceUrl: "https://github.com/idyll-lang/idyll-d3-component/tree/master/examples/basic"
      },
      {
        label: 'regl',
        href: 'https://idyll-lang.github.io/idyll-regl-component/',
        image: 'regl.png',
        sourceUrl: "https://github.com/idyll-lang/idyll-regl-component/tree/master/examples/basic"
      },
      {
        label: 'Vega Lite',
        href: 'https://idyll-lang.github.io/examples/csv/',
        image: 'vl.png',
        sourceUrl: "https://github.com/idyll-lang/examples/tree/master/csv"
      },
      {
        label: 'Firebase',
        href: 'https://mathisonian.github.io/idyll/firebase/',
        image: 'firebase.png',
        sourceUrl: "https://github.com/mathisonian/idyll/tree/master/firebase"
      },
      {
        label: 'Apparatus',
        href: 'https://mathisonian.com/writing/apparatus',
        image: 'apparatus.png',
        sourceUrl: 'https://github.com/mathisonian/mathisonian.github.io/blob/master/pages/writing/apparatus.js'
      }
    ],
  },
  // {
  //   title: 'Other examples',
  //   examples: [

  //     {
  //       label: 'Scrolly Idyll',
  //       href: 'https://idyll-lang.github.io/idyll/scroll/',
  //       image: 'scroll.gif',
  //     },
  //   ],
  // },
]

function slugify(text)
{
  return text.toString().split(/([A-Z][a-z]+)/).join('-').toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}

const indexedItems = {};
exampleGroups.forEach((group) => {
  group.examples.forEach((example) => {
    const slug = slugify(example.label);
    indexedItems[slug] = example;
  })
})

export { indexedItems };
export default exampleGroups;<|endoftext|>