diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..40b878d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules/
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..87dafd2
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,14 @@
+{
+ // Use IntelliSense to learn about possible Node.js debug attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Launch Program",
+ "program": "${file}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/dist/ticketStatus.json b/dist/ticketStatus.json
new file mode 100644
index 0000000..817f58e
--- /dev/null
+++ b/dist/ticketStatus.json
@@ -0,0 +1 @@
+[{"date":"2017/08/23(三)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2340"},{"date":"2017/08/24(四)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2416"},{"date":"2017/08/25(五)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2417"},{"date":"2017/08/26(六)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2418"},{"date":"2017/08/27(日)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2419"},{"date":"2017/08/28(一)","sport":"田徑","place":"臺北田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_02/2420"},{"date":"2017/08/23(三)","sport":"棒球","place":"新北市新莊棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2431"},{"date":"2017/08/25(五)","sport":"棒球","place":"臺北市天母棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2432"},{"date":"2017/08/25(五)","sport":"棒球","place":"新北市新莊棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2433"},{"date":"2017/08/26(六)","sport":"棒球","place":"新北市新莊棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2435"},{"date":"2017/08/27(日)","sport":"棒球","place":"新北市新莊棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2436"},{"date":"2017/08/28(一)","sport":"棒球","place":"新北市新莊棒球場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_04/2438"},{"date":"2017/08/23(三)","sport":"籃球","place":"新竹市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2451"},{"date":"2017/08/23(三)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2452"},{"date":"2017/08/23(三)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2453"},{"date":"2017/08/24(四)","sport":"籃球","place":"新竹市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2455"},{"date":"2017/08/24(四)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2456"},{"date":"2017/08/24(四)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2457"},{"date":"2017/08/25(五)","sport":"籃球","place":"臺北小巨蛋","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2458"},{"date":"2017/08/25(五)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2460"},{"date":"2017/08/25(五)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2461"},{"date":"2017/08/26(六)","sport":"籃球","place":"臺北小巨蛋","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2462"},{"date":"2017/08/26(六)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2463"},{"date":"2017/08/27(日)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2466"},{"date":"2017/08/28(一)","sport":"籃球","place":"臺北小巨蛋","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2468"},{"date":"2017/08/28(一)","sport":"籃球","place":"新竹市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2469"},{"date":"2017/08/28(一)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2470"},{"date":"2017/08/28(一)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2471"},{"date":"2017/08/29(二)","sport":"籃球","place":"新竹市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2473"},{"date":"2017/08/29(二)","sport":"籃球","place":"臺北市立大學天母校區體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2474"},{"date":"2017/08/29(二)","sport":"籃球","place":"臺北和平籃球館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_05/2923"},{"date":"2017/08/23(三)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2507"},{"date":"2017/08/23(三)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2508"},{"date":"2017/08/24(四)","sport":"足球","place":"輔仁大學體育場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2510"},{"date":"2017/08/24(四)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2511"},{"date":"2017/08/24(四)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2512"},{"date":"2017/08/24(四)","sport":"足球","place":"新竹縣第二運動場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2513"},{"date":"2017/08/25(五)","sport":"足球","place":"輔仁大學體育場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2514"},{"date":"2017/08/25(五)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2515"},{"date":"2017/08/25(五)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2516"},{"date":"2017/08/26(六)","sport":"足球","place":"輔仁大學體育場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2518"},{"date":"2017/08/26(六)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2519"},{"date":"2017/08/26(六)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2520"},{"date":"2017/08/27(日)","sport":"足球","place":"輔仁大學體育場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2522"},{"date":"2017/08/27(日)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2523"},{"date":"2017/08/27(日)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2524"},{"date":"2017/08/28(一)","sport":"足球","place":"輔仁大學體育場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2526"},{"date":"2017/08/28(一)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2527"},{"date":"2017/08/28(一)","sport":"足球","place":"新竹縣第二運動場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2528"},{"date":"2017/08/28(一)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2529"},{"date":"2017/08/29(二)","sport":"足球","place":"新北市新莊田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2531"},{"date":"2017/08/29(二)","sport":"足球","place":"新竹縣第二運動場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2924"},{"date":"2017/08/29(二)","sport":"足球","place":"長庚大學田徑場","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_08/2925"},{"date":"2017/08/24(四)","sport":"高爾夫","place":"揚昇高爾夫鄉村俱樂部","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_09/2347"},{"date":"2017/08/25(五)","sport":"高爾夫","place":"揚昇高爾夫鄉村俱樂部","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_09/2532"},{"date":"2017/08/26(六)","sport":"高爾夫","place":"揚昇高爾夫鄉村俱樂部","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_09/2533"},{"date":"2017/08/27(日)","sport":"高爾夫","place":"揚昇高爾夫鄉村俱樂部","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_09/2534"},{"date":"2017/08/23(三)","sport":"柔道","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_12/2543"},{"date":"2017/08/24(四)","sport":"柔道","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_12/2544"},{"date":"2017/08/23(三)","sport":"游泳","place":"國立體育大學綜合體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_14/2552"},{"date":"2017/08/24(四)","sport":"游泳","place":"國立體育大學綜合體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_14/2553"},{"date":"2017/08/23(三)","sport":"桌球","place":"新北市新莊體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_15/2647"},{"date":"2017/08/24(四)","sport":"桌球","place":"新北市新莊體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_15/2648"},{"date":"2017/08/23(三)","sport":"跆拳道","place":"桃園市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_16/2566"},{"date":"2017/08/24(四)","sport":"跆拳道","place":"桃園市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_16/2567"},{"date":"2017/08/25(五)","sport":"跆拳道","place":"桃園市立體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_16/2568"},{"date":"2017/08/23(三)","sport":"網球","place":"臺北市網球中心","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_17/2571"},{"date":"2017/08/24(四)","sport":"網球","place":"臺北市網球中心","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_17/2572"},{"date":"2017/08/25(五)","sport":"網球","place":"臺北市網球中心","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_17/2573"},{"date":"2017/08/24(四)","sport":"排球","place":"中國文化大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2953"},{"date":"2017/08/24(四)","sport":"排球","place":"國立清華大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2955"},{"date":"2017/08/25(五)","sport":"排球","place":"中國文化大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2957"},{"date":"2017/08/28(一)","sport":"排球","place":"中國文化大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2969"},{"date":"2017/08/28(一)","sport":"排球","place":"國立清華大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2971"},{"date":"2017/08/29(二)","sport":"排球","place":"國立清華大學體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_18/2975"},{"date":"2017/08/26(六)","sport":"武術","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_21/2359"},{"date":"2017/08/27(日)","sport":"武術","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_21/2639"},{"date":"2017/08/28(一)","sport":"武術","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_21/2640"},{"date":"2017/08/29(二)","sport":"武術","place":"新竹縣體育館","hasTicket":true,"url":"https://tickets.2017.taipei//ticket/area/17_TPE_21/2641"}]
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7ef3b17
--- /dev/null
+++ b/package.json
@@ -0,0 +1,11 @@
+{
+ "dependencies": {
+ "cheerio": "^1.0.0-rc.2",
+ "express": "^4.15.4",
+ "fs-extra": "^4.0.1",
+ "isomorphic-fetch": "^2.2.1"
+ },
+ "scripts": {
+ "start": "node server.js"
+ }
+}
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..b497a6f
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+ Universiade Ticket
+
+
+
+
+
+
+
+
+
+
+
+
{{key}}
+
+
+
+
{{status.date}}
{{status.place}}
+
購票
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/main.js b/public/main.js
new file mode 100644
index 0000000..d1586a3
--- /dev/null
+++ b/public/main.js
@@ -0,0 +1,29 @@
+var app = new Vue({
+ el: '#app',
+ data: {
+ ticketStatus: {},
+ filteredTicketStatus: {},
+ sports: {},
+ places: {},
+ dates: {},
+ selectedPlace: '',
+ selectedSport: '',
+ selectedDate: ''
+ },
+ created: function () {
+ var self = this;
+ $.get('/api/ticketStatus').then(function (json) {
+ self.ticketStatus = _.groupBy(json, 'sport');
+ json.forEach(function (status) {
+ self.sports[status.sport] = true;
+ self.places[status.place] = true;
+ self.dates[status.date] = true;
+ })
+ })
+ },
+ method: {
+ filterData: function () {
+ // this.
+ }
+ }
+})
\ No newline at end of file
diff --git a/schedule.js b/schedule.js
new file mode 100644
index 0000000..e69de29
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..15e60d1
--- /dev/null
+++ b/server.js
@@ -0,0 +1,23 @@
+const express = require('express')
+const serveStatic = require('serve-static')
+const path = require('path')
+const {getAllTicketStatus } = require('./ticket');
+const app = express()
+
+app.get('/api/ticketstatus', (req, res, next) => {
+ res.sendFile(path.join(__dirname, 'dist', 'ticketStatus.json'))
+})
+
+app.use(express.static(path.join(__dirname, 'public')));
+
+const port = process.env.PORT || 8080;
+app.listen(port, function () {
+ console.log('app running on port', port);
+})
+console.log(`app listen on ${port}`)
+
+setInterval(async () => {
+ console.time('[Scheduler] getAllTicketStatus');
+ await getAllTicketStatus()
+ console.timeEnd('[Scheduler] getAllTicketStatus');
+}, 3600000)
\ No newline at end of file
diff --git a/ticket.js b/ticket.js
new file mode 100644
index 0000000..a737ef9
--- /dev/null
+++ b/ticket.js
@@ -0,0 +1,45 @@
+const { getCheerio$ } = require('./util');
+const fetch = require("isomorphic-fetch");
+const { outputJson } = require('fs-extra');
+
+const rootUrl = 'https://tickets.2017.taipei'
+const distFolder = 'dist/';
+const getAllTicketStatus = async () => {
+ let allStatus = [];
+ for (var i = 1; i <= 22; i++) {
+ const ticketStatus = await getTicketStatus(('0' + i).slice(-2));
+ console.log(`Get ticket status for ${ticketStatus[0].sport}`)
+ allStatus = allStatus.concat(ticketStatus)
+ outputJson(`${distFolder}${ticketStatus[0].sport}.json`, ticketStatus, { spaces: 2 })
+ await outputJson(`${distFolder}ticketStatus.json`, allStatus.filter(status => status.hasTicket))
+ }
+}
+
+const getTicketStatus = (sportsId) => {
+ return new Promise(async (resolve, reject) => {
+ try {
+ const $ = await getCheerio$(`${rootUrl}/schedule/17_TPE_${sportsId}`)
+ const promises = Array.from($('#schedule-info tr:has(button)').map(async (index, tr) => {
+ const $tr = $(tr);
+ const $tds = $tr.find('td')
+ const ticketUrl = rootUrl + $tr.find('button').attr('onclick').split('\'')[1];
+ const ticketResponse = await fetch(ticketUrl)
+ const ticketStatus = await ticketResponse.text();
+ return {
+ date: $tds.eq(0).text(),
+ sport: $tds.eq(1).text(),
+ place: $tds.eq(2).text(),
+ hasTicket: ticketStatus.indexOf('本活動已售完') === -1,
+ url: ticketUrl
+ }
+ }));
+ const results = await Promise.all(promises);
+ resolve(results);
+ }
+ catch (err) {
+ console.error(err)
+ }
+ })
+}
+
+module.exports = { getAllTicketStatus }
diff --git a/util.js b/util.js
new file mode 100644
index 0000000..146aefa
--- /dev/null
+++ b/util.js
@@ -0,0 +1,9 @@
+const cheerio = require('cheerio');
+
+async function getCheerio$(request) {
+ const response = await fetch(request);
+ const html = await response.text();
+ return cheerio.load(html, { decodeEntities: false });
+}
+
+module.exports = { getCheerio$ }
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..af2d788
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,430 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@types/node@^6.0.46":
+ version "6.0.87"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.87.tgz#5ab5774f8351a33a935099fa6be850aa0b0ad564"
+
+accepts@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
+ dependencies:
+ mime-types "~2.1.11"
+ negotiator "0.6.1"
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
+cheerio@^1.0.0-rc.2:
+ version "1.0.0-rc.2"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
+ dependencies:
+ css-select "~1.2.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "^3.9.1"
+ lodash "^4.15.0"
+ parse5 "^3.0.1"
+
+content-disposition@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+css-select@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-what@2.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
+debug@2.6.8:
+ version "2.6.8"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
+ dependencies:
+ ms "2.0.0"
+
+depd@1.1.1, depd@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+dom-serializer@0, dom-serializer@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ dependencies:
+ domelementtype "~1.1.1"
+ entities "~1.1.1"
+
+domelementtype@1, domelementtype@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@^2.3.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.5.1, domutils@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+encodeurl@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
+
+encoding@^0.1.11:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ dependencies:
+ iconv-lite "~0.4.13"
+
+entities@^1.1.1, entities@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+etag@~1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
+
+express@^4.15.4:
+ version "4.15.4"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
+ dependencies:
+ accepts "~1.3.3"
+ array-flatten "1.1.1"
+ content-disposition "0.5.2"
+ content-type "~1.0.2"
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ debug "2.6.8"
+ depd "~1.1.1"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ finalhandler "~1.0.4"
+ fresh "0.5.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ path-to-regexp "0.1.7"
+ proxy-addr "~1.1.5"
+ qs "6.5.0"
+ range-parser "~1.2.0"
+ send "0.15.4"
+ serve-static "1.12.4"
+ setprototypeof "1.0.3"
+ statuses "~1.3.1"
+ type-is "~1.6.15"
+ utils-merge "1.0.0"
+ vary "~1.1.1"
+
+finalhandler@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
+ dependencies:
+ debug "2.6.8"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ statuses "~1.3.1"
+ unpipe "~1.0.0"
+
+forwarded@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.0.tgz#19ef9874c4ae1c297bcf078fde63a09b66a84363"
+
+fresh@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
+
+fs-extra@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880"
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^3.0.0"
+ universalify "^0.1.0"
+
+graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+htmlparser2@^3.9.1:
+ version "3.9.2"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ dependencies:
+ domelementtype "^1.3.0"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
+http-errors@~1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+ dependencies:
+ depd "1.1.1"
+ inherits "2.0.3"
+ setprototypeof "1.0.3"
+ statuses ">= 1.3.1 < 2"
+
+iconv-lite@~0.4.13:
+ version "0.4.18"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
+
+inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+ipaddr.js@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
+
+is-stream@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isomorphic-fetch@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+ dependencies:
+ node-fetch "^1.0.1"
+ whatwg-fetch ">=0.10.0"
+
+jsonfile@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+lodash@^4.15.0:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+mime-db@~1.29.0:
+ version "1.29.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
+
+mime-types@~2.1.11, mime-types@~2.1.15:
+ version "2.1.16"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23"
+ dependencies:
+ mime-db "~1.29.0"
+
+mime@1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+negotiator@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+node-fetch@^1.0.1:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.2.tgz#c54e9aac57e432875233525f3c891c4159ffefd7"
+ dependencies:
+ encoding "^0.1.11"
+ is-stream "^1.0.1"
+
+nth-check@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+ dependencies:
+ boolbase "~1.0.0"
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ dependencies:
+ ee-first "1.1.1"
+
+parse5@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.2.tgz#05eff57f0ef4577fb144a79f8b9a967a6cc44510"
+ dependencies:
+ "@types/node" "^6.0.46"
+
+parseurl@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+process-nextick-args@~1.0.6:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+proxy-addr@~1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
+ dependencies:
+ forwarded "~0.1.0"
+ ipaddr.js "1.4.0"
+
+qs@6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
+
+range-parser@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+readable-stream@^2.0.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.0.3"
+ util-deprecate "~1.0.1"
+
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+send@0.15.4:
+ version "0.15.4"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
+ dependencies:
+ debug "2.6.8"
+ depd "~1.1.1"
+ destroy "~1.0.4"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ fresh "0.5.0"
+ http-errors "~1.6.2"
+ mime "1.3.4"
+ ms "2.0.0"
+ on-finished "~2.3.0"
+ range-parser "~1.2.0"
+ statuses "~1.3.1"
+
+serve-static@1.12.4:
+ version "1.12.4"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
+ dependencies:
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ parseurl "~1.3.1"
+ send "0.15.4"
+
+setprototypeof@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
+
+string_decoder@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+ dependencies:
+ safe-buffer "~5.1.0"
+
+type-is@~1.6.15:
+ version "1.6.15"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.15"
+
+universalify@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
+
+unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+utils-merge@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
+
+vary@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
+
+whatwg-fetch@>=0.10.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"