From 7d475cae89cfbb1c55ca0f93e81b032501f3740a Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 16:43:18 -0400 Subject: [PATCH 01/22] start implementing sessions --- .gitignore | 4 +- app/client.js | 14 +- app/server.js | 94 ++++- assets/icons/download.svg | 4 + assets/icons/flip.svg | 16 +- assets/icons/fork.svg | 4 + assets/icons/link.svg | 4 + assets/icons/save.svg | 4 + client/store.js | 14 + package.json | 41 +- routes/4xx.html | 9 +- routes/5xx.html | 9 +- routes/_store.js | 15 - routes/api/gists/index.js | 3 - routes/blog/[slug].html | 3 - routes/blog/index.html | 3 - routes/guide/index.html | 1 - routes/index.html | 5 +- routes/repl/_AppControls.html | 181 +++++++++ routes/repl/_UserMenu.html | 58 +++ routes/repl/index.html | 207 +++++----- webpack/client.config.js | 2 +- yarn.lock | 702 ++++++++++++++++++++++++---------- 23 files changed, 998 insertions(+), 399 deletions(-) create mode 100644 assets/icons/download.svg create mode 100644 assets/icons/fork.svg create mode 100644 assets/icons/link.svg create mode 100644 assets/icons/save.svg create mode 100644 client/store.js delete mode 100644 routes/_store.js create mode 100644 routes/repl/_AppControls.html create mode 100644 routes/repl/_UserMenu.html diff --git a/.gitignore b/.gitignore index 770b0d67c..e93b5ce09 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ assets/svelte-app.zip credentials.json app/manifest build -yarn-error.log \ No newline at end of file +yarn-error.log +.env +.sessions \ No newline at end of file diff --git a/app/client.js b/app/client.js index af277e835..73c46c8b5 100644 --- a/app/client.js +++ b/app/client.js @@ -1,7 +1,19 @@ import { init } from 'sapper/runtime.js'; +import store from '../client/store.js'; import { routes } from './manifest/client.js'; -init(document.querySelector('#sapper'), routes); +init(document.querySelector('#sapper'), routes, { + store: data => { + store.set(data); + + fetch(`api/guide/contents`).then(r => r.json()).then(guide_contents => { + store.set({ guide_contents }); + }); + + window.store = store; + return store; + } +}); if (navigator.serviceWorker && navigator.serviceWorker.controller) { navigator.serviceWorker.controller.onstatechange = function(e) { diff --git a/app/server.js b/app/server.js index 3bd02d013..46e624a95 100644 --- a/app/server.js +++ b/app/server.js @@ -1,15 +1,107 @@ +import dotenv from 'dotenv'; import express from 'express'; import compression from 'compression'; +import session from 'express-session'; +import passport from 'passport'; +import { Strategy } from 'passport-github'; +import sessionFileStore from 'session-file-store'; import sapper from 'sapper'; import serve from 'serve-static'; +import devalue from 'devalue'; +import { Store } from 'svelte/store.js'; import { routes } from './manifest/server.js'; +dotenv.config(); + +const FileStore = sessionFileStore(session); + +passport.use(new Strategy({ + clientID: process.env.GITHUB_CLIENT_ID, + clientSecret: process.env.GITHUB_CLIENT_SECRET, + callbackURL: `http://${process.env.ORIGIN}/auth/callback` +}, (accessToken, refreshToken, profile, callback) => { + console.log(profile); + + return callback(null, { + id: profile.id, + username: profile.username, + displayName: profile.displayName, + photo: profile.photos && profile.photos[0] && profile.photos[0].value, + + accessToken + }); +})); + +passport.serializeUser((user, cb) => { + cb(null, user); +}); + +passport.deserializeUser((obj, cb) => { + cb(null, obj); +}); + express() + .use(compression({ threshold: 0 })) + + .use(session({ + secret: 'svelte', + resave: true, + saveUninitialized: true, + cookie: { + maxAge: 31536000 + }, + store: new FileStore({ + path: process.env.NOW ? `/tmp/sessions` : `.sessions` + }) + })) + + .use(passport.initialize()) + .use(passport.session()) + + .get('/auth/login', (req, res, next) => { + const { returnTo } = req.query; + req.session.returnTo = returnTo ? decodeURIComponent(returnTo) : '/'; + next(); + }, passport.authenticate('github', { scope: ['gist', 'read:user'] })) + + .post('/auth/logout', (req, res) => { + req.logout(); + res.end('ok'); + }) + + .get('/auth/callback', passport.authenticate('github', { failureRedirect: '/auth/error' }), (req, res) => { + const user = req.session.passport && req.session.passport.user; + if (user) delete user.accessToken; + + res.end(` + + `); + }) + .use( compression({ threshold: 0 }), serve('assets'), sapper({ - routes + routes, + store: req => { + const user = req.session.passport && req.session.passport.user; + + return new Store({ + user: user && { + // strip access token + id: user.id, + name: user.name, + displayName: user.displayName, + photo: user.photo + }, + guide_contents: [] + }); + } }) ) + .listen(process.env.PORT); \ No newline at end of file diff --git a/assets/icons/download.svg b/assets/icons/download.svg new file mode 100644 index 000000000..8d255ff74 --- /dev/null +++ b/assets/icons/download.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/flip.svg b/assets/icons/flip.svg index c001239ba..09326b1e6 100644 --- a/assets/icons/flip.svg +++ b/assets/icons/flip.svg @@ -1,14 +1,4 @@ - - - - - - - - + + + \ No newline at end of file diff --git a/assets/icons/fork.svg b/assets/icons/fork.svg new file mode 100644 index 000000000..57ad61bb2 --- /dev/null +++ b/assets/icons/fork.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/link.svg b/assets/icons/link.svg new file mode 100644 index 000000000..6772991bd --- /dev/null +++ b/assets/icons/link.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/icons/save.svg b/assets/icons/save.svg new file mode 100644 index 000000000..4bde5edde --- /dev/null +++ b/assets/icons/save.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/client/store.js b/client/store.js new file mode 100644 index 000000000..d694cb5b1 --- /dev/null +++ b/client/store.js @@ -0,0 +1,14 @@ +import { Store } from 'svelte/store.js'; + +class ClientStore extends Store { + logout() { + return fetch(`auth/logout`, { + method: 'POST', + credentials: 'include' + }).then(() => { + this.set({ user: null }); + }); + } +} + +export default new ClientStore(); \ No newline at end of file diff --git a/package.json b/package.json index 717e8351f..839ec7354 100644 --- a/package.json +++ b/package.json @@ -31,43 +31,50 @@ "devDependencies": { "chalk": "^2.0.1", "clean-css": "^4.0.12", - "css-loader": "^0.28.7", - "degit": "^2.0.1", - "eslint": "^4.0.0", + "css-loader": "^0.28.11", + "degit": "^2.1.3", + "eslint": "^4.19.1", "eslint-plugin-html": "^4.0.2", "eslint-plugin-import": "^2.2.0", "git-branch-is": "^0.1.0", "glob": "^7.1.2", "html-entities": "^1.2.1", - "now": "^10.1.5", + "now": "^10.2.1", "style-loader": "^0.20.3", - "svelte": "^1.57.1", - "svelte-loader": "^2.5.0", - "webpack": "^4.1.0" + "svelte": "^1.58.2", + "svelte-loader": "^2.5.1", + "webpack": "^4.2.0" }, "dependencies": { - "codemirror": "^5.25.2", + "codemirror": "^5.36.0", "compression": "^1.6.2", - "cross-env": "^5.1.1", - "express": "^4.15.2", - "file-saver": "^1.3.3", + "cross-env": "^5.1.4", + "devalue": "^1.0.1", + "dotenv": "^5.0.1", + "express": "^4.16.3", + "express-session": "^1.15.6", + "file-saver": "^1.3.8", "highlight.js": "^9.12.0", "jszip": "^3.1.3", "locate-character": "^2.0.0", - "lru-cache": "^4.1.1", - "marked": "^0.3.7", + "lru-cache": "^4.1.2", + "marked": "^0.3.18", "needle": "^2.0.0", "node-fetch": "^2.1.1", - "rollup": "^0.56.5", + "passport": "^0.4.0", + "passport-github": "^1.1.0", + "rollup": "^0.57.1", "sapper": "^0.10.1", "serve-static": "^1.13.1", - "sourcemap-codec": "^1.3.1" + "session-file-store": "^1.2.0", + "sourcemap-codec": "^1.4.1" }, "now": { "env": { "NODE_ENV": "production", - "client_id": "@svelte-gist-client-id", - "client_secret": "@svelte-gist-client-secret" + "ORIGIN": "svelte.technology", + "GITHUB_CLIENT_ID": "@svelte-gist-client-id", + "GITHUB_CLIENT_SECRET": "@svelte-gist-client-secret" }, "alias": "svelte.technology", "files": [ diff --git a/routes/4xx.html b/routes/4xx.html index e961e53b9..a500ee408 100644 --- a/routes/4xx.html +++ b/routes/4xx.html @@ -2,9 +2,9 @@ {{error.message}} • The magical disappearing UI framework - +

{{error.message}}

-
+ \ No newline at end of file diff --git a/routes/repl/_AppControls.html b/routes/repl/_AppControls.html new file mode 100644 index 000000000..4c20f93eb --- /dev/null +++ b/routes/repl/_AppControls.html @@ -0,0 +1,181 @@ +
+ + +
+ {{#if $user}} + + + + + + link to gist + + {{#if gist}} + gist + {{/if}} + {{else}} + + {{/if}} +
+
+ + + + \ No newline at end of file diff --git a/routes/repl/_UserMenu.html b/routes/repl/_UserMenu.html new file mode 100644 index 000000000..808697cbe --- /dev/null +++ b/routes/repl/_UserMenu.html @@ -0,0 +1,58 @@ +
+ {{$user.displayName}} + {{$user.displayName}} avatar + + {{#if showMenu}} + + {{/if}} +
+ + \ No newline at end of file diff --git a/routes/repl/index.html b/routes/repl/index.html index 31603f8a8..a72862d3e 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -3,100 +3,102 @@ -
-
-
-
- - -
- - - - {{#if gist}} - gist +
+ + +
+
+
+
+ {{#if selectedComponent}} + {{/if}}
-
-
- {{#if selectedComponent}} - + {{#if loadedCodemirror}} +
+ {{#if selectedComponent}} + {{#if showGenerated && selectedComponent.compiled}} + + {{else}} + + {{/if}} + {{/if}} + + +
+ {{else}} +

loading editor...

+ {{/if}} +
+
+ +
+

data.json

+
+ {{#if loadedCodemirror}} + + {{else}} +

loading editor...

{{/if}}
- {{#if loadedCodemirror}} -
- {{#if selectedComponent}} - {{#if showGenerated && selectedComponent.compiled}} - - {{else}} - - {{/if}} +

Rendered component

+
+ {{#if loadedSvelte}} + {{#if bundle}} + {{/if}} + {{else}} +

loading Svelte compiler...

+ {{/if}} - -
- {{else}} -

loading editor...

- {{/if}} - -
- -
-

data.json

-
- {{#if loadedCodemirror}} - - {{else}} -

loading editor...

- {{/if}} -
- -

Rendered component

-
- {{#if loadedSvelte}} - {{#if bundle}} - + {{#if dragging}} +
{{/if}} - {{else}} -

loading Svelte compiler...

- {{/if}} +
- {{#if dragging}} -
- {{/if}} +
-
+
- -
@@ -419,11 +401,12 @@

Rendered component

import Viewer from './_Viewer.html'; import ComponentSelector from './_ComponentSelector.html'; import ExampleSelector from './_ExampleSelector.html'; + import AppControls from './_AppControls.html'; + import UserMenu from './_UserMenu.html'; import { getComponentFromGist, saveComponentAsGist } from './_utils/gist.js'; import debounce from './_utils/debounce.js'; import * as load from './_utils/load.js'; import { get } from './_utils/get.js'; - import store from '../_store.js'; function loadCodemirror() { return import(/* webpackChunkName: "codemirror" */ './_codemirror.js').then(({ default: CodeMirror }) => { @@ -470,8 +453,6 @@

Rendered component

} export default { - store: () => store, - data() { const search = typeof window !== 'undefined' ? window.location.search : ''; const gistMatch = /gist=([^&]+)$/.exec(search); @@ -1137,7 +1118,9 @@

Rendered component

CodeMirror, Viewer, ComponentSelector, - ExampleSelector + ExampleSelector, + UserMenu, + AppControls } }; diff --git a/webpack/client.config.js b/webpack/client.config.js index 7c8502a44..db06c9d35 100644 --- a/webpack/client.config.js +++ b/webpack/client.config.js @@ -21,7 +21,7 @@ module.exports = { hydratable: true, cascade: false, store: true, - hotReload: false // TODO + hotReload: true } } }, diff --git a/yarn.lock b/yarn.lock index 1e4bd82f4..1aeebcc8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,25 @@ # yarn lockfile v1 +"@types/acorn@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.3.tgz#d1f3e738dde52536f9aad3d3380d14e448820afd" + dependencies: + "@types/estree" "*" + +"@types/estree@*", "@types/estree@0.0.38": + version "0.0.38" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.38.tgz#c1be40aa933723c608820a99a373a16d215a1ca2" + "@types/node@*": - version "9.4.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.0.tgz#d3480ee666df9784b1001a1872a2f6ccefb6c2d7" abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" -accepts@~1.3.4: +accepts@~1.3.4, accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" dependencies: @@ -33,9 +43,9 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.0.0, acorn@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.1.tgz#84e05a9ea0acbe131227da50301e62464dc9c1d8" +acorn@^5.0.0, acorn@^5.5.0, acorn@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" ajv-keywords@^2.1.0: version "2.1.1" @@ -62,8 +72,8 @@ ajv@^5.2.3, ajv@^5.3.0: json-schema-traverse "^0.3.0" ajv@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.1.tgz#28a6abc493a2abe0fb4c8507acaedb43fa550671" + version "6.3.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.3.0.tgz#1650a41114ef00574cac10b8032d8f4c14812da7" dependencies: fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" @@ -119,11 +129,17 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" -arr-flatten@^1.1.0: +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" @@ -145,6 +161,10 @@ array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -222,6 +242,10 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" +bagpipe@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/bagpipe/-/bagpipe-0.3.5.tgz#e341d164fcb24cdf04ea7e05b765ec10c8aea6a1" + balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" @@ -306,6 +330,14 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + braces@^2.3.0, braces@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" @@ -386,6 +418,10 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -410,7 +446,7 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" -cacache@^10.0.1: +cacache@^10.0.4: version "10.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" dependencies: @@ -469,8 +505,8 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000813" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000813.tgz#e0a1c603f8880ad787b2a35652b2733f32a5e29a" + version "1.0.30000819" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000819.tgz#c3b7dd559e5e6d63d5dcaa62bac6bd04c7619709" caseless@~0.12.0: version "0.12.0" @@ -486,7 +522,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" dependencies: @@ -510,8 +546,8 @@ cheerio@^1.0.0-rc.2: parse5 "^3.0.1" chokidar@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7" + version "2.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -525,7 +561,7 @@ chokidar@^2.0.2: readdirp "^2.0.0" upath "^1.0.0" optionalDependencies: - fsevents "^1.0.0" + fsevents "^1.1.2" chownr@^1.0.1: version "1.0.1" @@ -578,8 +614,8 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" clorox@^1.0.3: version "1.0.3" @@ -599,9 +635,9 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -codemirror@^5.25.2: - version "5.35.0" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.35.0.tgz#280653d495455bc66aa87e6284292b02775ba878" +codemirror@^5.36.0: + version "5.36.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.36.0.tgz#1172ad9dc298056c06e0b34e5ccd23825ca15b40" collection-visit@^1.0.0: version "1.0.0" @@ -652,14 +688,10 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.15.x: +commander@2.15.x, commander@^2.9.0, commander@~2.15.0: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" -commander@^2.9.0, commander@~2.14.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" - commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" @@ -680,7 +712,7 @@ compressible@~2.0.13: compression@^1.6.2: version "1.7.2" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" + resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" dependencies: accepts "~1.3.4" bytes "3.0.0" @@ -695,9 +727,10 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" concat-stream@^1.5.0, concat-stream@^1.6.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: + buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" @@ -759,6 +792,10 @@ core-util-is@1.0.2, 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" +crc@3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.4.4.tgz#9da1e980e3bd44fc5c93bf5ab3da3378d85e466b" + create-ecdh@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" @@ -786,9 +823,9 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-env@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.3.tgz#f8ae18faac87692b0a8b4d2f7000d4ec3a85dfd7" +cross-env@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.4.tgz#f61c14291f7cc653bb86457002ea80a04699d022" dependencies: cross-spawn "^5.1.0" is-windows "^1.0.0" @@ -827,9 +864,9 @@ css-color-names@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" -css-loader@^0.28.7: - version "0.28.10" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.10.tgz#40282e79230f7bcb4e483efa631d670b735ebf42" +css-loader@^0.28.11: + version "0.28.11" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.11.tgz#c3f9864a700be2711bb5a2462b2389b1a392dab7" dependencies: babel-code-frame "^6.26.0" css-selector-tokenizer "^0.7.0" @@ -929,6 +966,12 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" +date-time@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" + dependencies: + time-zone "^1.0.0" + debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -980,13 +1023,14 @@ defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" -degit@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/degit/-/degit-2.0.2.tgz#e4afe099394a64ddb16f2f4e20acb48a7c8ee7e3" +degit@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/degit/-/degit-2.1.3.tgz#b53c30ad18d9e30b9fd542fe81d5154e63d6261f" dependencies: chalk "^2.0.1" home-or-tmp "^3.0.0" mri "^1.1.0" + sander "^0.6.0" tar "^4.0.2" del@^2.0.2: @@ -1096,6 +1140,10 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dotenv@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" + duplexify@^3.4.2, duplexify@^3.5.3: version "3.5.4" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" @@ -1116,8 +1164,8 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" electron-to-chromium@^1.2.7: - version "1.3.36" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.36.tgz#0eabf71a9ebea9013fb1cc35a390e068624f27e8" + version "1.3.40" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.40.tgz#1fbd6d97befd72b8a6f921dc38d22413d2f6fddf" elliptic@^6.0.0: version "6.4.0" @@ -1135,7 +1183,7 @@ emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" -encodeurl@~1.0.1, encodeurl@~1.0.2: +encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -1227,9 +1275,9 @@ eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" -eslint@^4.0.0: - version "4.18.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.2.tgz#0f81267ad1012e7d2051e186a9004cc2267b8d45" +eslint@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -1240,7 +1288,7 @@ eslint@^4.0.0: doctrine "^2.1.0" eslint-scope "^3.7.1" eslint-visitor-keys "^1.0.0" - espree "^3.5.2" + espree "^3.5.4" esquery "^1.0.0" esutils "^2.0.2" file-entry-cache "^2.0.0" @@ -1262,6 +1310,7 @@ eslint@^4.0.0: path-is-inside "^1.0.2" pluralize "^7.0.0" progress "^2.0.0" + regexpp "^1.0.1" require-uncached "^1.0.3" semver "^5.3.0" strip-ansi "^4.0.0" @@ -1269,7 +1318,7 @@ eslint@^4.0.0: table "4.0.2" text-table "~0.2.0" -espree@^3.5.2: +espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: @@ -1300,6 +1349,10 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" +estree-walker@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -1319,6 +1372,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -1331,11 +1390,31 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -express@^4.15.2: - version "4.16.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" dependencies: - accepts "~1.3.4" + fill-range "^2.1.0" + +express-session@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.15.6.tgz#47b4160c88f42ab70fe8a508e31cbff76757ab0a" + dependencies: + cookie "0.3.1" + cookie-signature "1.0.6" + crc "3.4.4" + debug "2.6.9" + depd "~1.1.1" + on-headers "~1.0.1" + parseurl "~1.3.2" + uid-safe "~2.1.5" + utils-merge "1.0.1" + +express@^4.16.3: + version "4.16.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" + dependencies: + accepts "~1.3.5" array-flatten "1.1.1" body-parser "1.18.2" content-disposition "0.5.2" @@ -1343,26 +1422,26 @@ express@^4.15.2: cookie "0.3.1" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.1" - encodeurl "~1.0.1" + depd "~1.1.2" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.1.0" + finalhandler "1.1.1" fresh "0.5.2" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" parseurl "~1.3.2" path-to-regexp "0.1.7" - proxy-addr "~2.0.2" + proxy-addr "~2.0.3" qs "6.5.1" range-parser "~1.2.0" safe-buffer "5.1.1" - send "0.16.1" - serve-static "1.13.1" + send "0.16.2" + serve-static "1.13.2" setprototypeof "1.1.0" - statuses "~1.3.1" - type-is "~1.6.15" + statuses "~1.4.0" + type-is "~1.6.16" utils-merge "1.0.1" vary "~1.1.2" @@ -1391,6 +1470,12 @@ external-editor@^2.0.4: iconv-lite "^0.4.17" tmp "^0.0.33" +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1441,9 +1526,23 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -file-saver@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.3.tgz#cdd4c44d3aa264eac2f68ec165bc791c34af1232" +file-saver@^1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" fill-range@^4.0.0: version "4.0.0" @@ -1454,16 +1553,16 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" dependencies: debug "2.6.9" - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" on-finished "~2.3.0" parseurl "~1.3.2" - statuses "~1.3.1" + statuses "~1.4.0" unpipe "~1.0.0" find-cache-dir@^1.0.0: @@ -1501,16 +1600,22 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" flush-write-stream@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417" + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" dependencies: inherits "^2.0.1" readable-stream "^2.0.4" -for-in@^1.0.2: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -1544,7 +1649,15 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-minipass@^1.2.3: +fs-extra@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" dependencies: @@ -1563,7 +1676,7 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.0.0: +fsevents@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" dependencies: @@ -1624,6 +1737,19 @@ git-branch-is@^0.1.0: dependencies: commander "^2.9.0" +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -1643,8 +1769,8 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: path-is-absolute "^1.0.0" globals@^11.0.1: - version "11.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0" + version "11.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.4.0.tgz#b85c793349561c16076a3c13549238a27945f1bc" globby@^5.0.0: version "5.0.0" @@ -1657,7 +1783,7 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -1777,8 +1903,8 @@ home-or-tmp@^3.0.0: resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-3.0.0.tgz#57a8fe24cf33cdd524860a15821ddc25c86671fb" hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + version "2.6.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" html-comment-regex@^1.1.0: version "1.1.1" @@ -1848,8 +1974,8 @@ icss-utils@^2.1.0: postcss "^6.0.1" ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + version "1.1.11" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455" iferr@^0.1.5: version "0.1.5" @@ -1985,6 +2111,16 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -1995,6 +2131,10 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2009,6 +2149,12 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -2021,6 +2167,12 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -2042,8 +2194,8 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" dependencies: is-path-inside "^1.0.0" @@ -2063,10 +2215,24 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" +is-reference@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.1.0.tgz#50e6ef3f64c361e2c53c0416cdc9420037f2685b" + dependencies: + "@types/estree" "0.0.38" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -2163,6 +2329,12 @@ json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -2206,12 +2378,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" -lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - dependencies: - set-getter "^0.1.0" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -2246,7 +2412,7 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" -locate-character@^2.0.0: +locate-character@^2.0.0, locate-character@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-2.0.5.tgz#f2d2614d49820ecb3c92d80d193b8db755f74c0f" @@ -2277,9 +2443,9 @@ lower-case@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" -lru-cache@^4.0.1, lru-cache@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" +lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f" dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -2304,9 +2470,9 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^0.3.7: - version "0.3.17" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.17.tgz#607f06668b3c6b1246b28f13da76116ac1aa2d2b" +marked@^0.3.18: + version "0.3.18" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.18.tgz#3ef058cd926101849b92a7a7c15db18c7fc76b2f" math-expression-evaluator@^1.2.14: version "1.2.17" @@ -2338,9 +2504,27 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" +micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + micromatch@^3.1.4, micromatch@^3.1.8: - version "3.1.9" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89" + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -2354,7 +2538,7 @@ micromatch@^3.1.4, micromatch@^3.1.8: object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" - to-regex "^3.0.1" + to-regex "^3.0.2" miller-rabin@^4.0.0: version "4.0.1" @@ -2403,10 +2587,11 @@ minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -minipass@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.2.1.tgz#5ada97538b1027b4cf7213432428578cb564011f" +minipass@^2.2.1, minipass@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.2.4.tgz#03c824d84551ec38a8d1bb5bc350a5a30a354a40" dependencies: + safe-buffer "^5.1.1" yallist "^3.0.0" minizlib@^1.1.0: @@ -2467,8 +2652,8 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" nan@^2.3.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" nanomatch@^1.2.9: version "1.2.9" @@ -2583,7 +2768,7 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.1.1: +normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: @@ -2602,9 +2787,9 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" -now@^10.1.5: - version "10.1.5" - resolved "https://registry.yarnpkg.com/now/-/now-10.1.5.tgz#6d5ed80723aacf101103a200f56635cf870872fb" +now@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/now/-/now-10.2.1.tgz#239d1f86b613edca3902fad8588d719f5b62b611" npmlog@^4.0.2: version "4.1.2" @@ -2633,6 +2818,10 @@ oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2651,6 +2840,13 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -2759,6 +2955,15 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -2783,6 +2988,32 @@ pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" +passport-github@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/passport-github/-/passport-github-1.1.0.tgz#8ce1e3fcd61ad7578eb1df595839e4aea12355d4" + dependencies: + passport-oauth2 "1.x.x" + +passport-oauth2@1.x.x: + version "1.4.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.4.0.tgz#f62f81583cbe12609be7ce6f160b9395a27b86ad" + dependencies: + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + +passport@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.0.tgz#c5095691347bd5ad3b5e180238c3914d16f05811" + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -2823,6 +3054,10 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + pbkdf2@^3.0.3: version "3.0.14" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" @@ -2878,8 +3113,8 @@ pluralize@^7.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" port-authority@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/port-authority/-/port-authority-1.0.2.tgz#860d9988aa26b89f02e28e44dd3c1d08eb59b052" + version "1.0.3" + resolved "https://registry.yarnpkg.com/port-authority/-/port-authority-1.0.3.tgz#5e07be43abcbc0fad36d48a581b815b0484dca7a" posix-character-classes@^0.1.0: version "0.1.1" @@ -3124,12 +3359,12 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 supports-color "^3.2.3" postcss@^6.0.1: - version "6.0.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" + version "6.0.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.21.tgz#8265662694eddf9e9a5960db6da33c39e4cd069d" dependencies: - chalk "^2.3.1" + chalk "^2.3.2" source-map "^0.6.1" - supports-color "^5.2.0" + supports-color "^5.3.0" prelude-ls@~1.1.2: version "1.1.2" @@ -3139,6 +3374,10 @@ prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" @@ -3170,7 +3409,7 @@ promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" -proxy-addr@~2.0.2: +proxy-addr@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" dependencies: @@ -3249,6 +3488,17 @@ querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" @@ -3276,8 +3526,8 @@ raw-body@2.3.2: unpipe "1.0.0" rc@^1.1.7: - version "1.2.5" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd" + version "1.2.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" dependencies: deep-extend "~0.4.0" ini "~1.3.0" @@ -3349,6 +3599,12 @@ regenerate@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -3356,6 +3612,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexpp@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.0.1.tgz#d857c3a741dce075c2848dcb019a0a975b190d43" + regexpu-core@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" @@ -3441,8 +3701,8 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" resolve@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + version "1.6.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" dependencies: path-parse "^1.0.5" @@ -3457,6 +3717,10 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" @@ -3470,9 +3734,28 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" -rollup@^0.56.5: - version "0.56.5" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.5.tgz#40fe3cf0cd1659d469baad11f4d5b6336c14ce84" +rollup-pluginutils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" + dependencies: + estree-walker "^0.3.0" + micromatch "^2.3.11" + +rollup@^0.57.1: + version "0.57.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.57.1.tgz#0bb28be6151d253f67cf4a00fea48fb823c74027" + dependencies: + "@types/acorn" "^4.0.3" + acorn "^5.5.3" + acorn-dynamic-import "^3.0.0" + date-time "^2.1.0" + is-reference "^1.1.0" + locate-character "^2.0.5" + pretty-ms "^3.1.0" + require-relative "^0.8.7" + rollup-pluginutils "^2.0.1" + signal-exit "^3.0.2" + sourcemap-codec "^1.4.1" run-async@^2.2.0: version "2.3.0" @@ -3561,24 +3844,6 @@ schema-utils@^0.4.2, schema-utils@^0.4.5: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" - dependencies: - debug "2.6.9" - depd "~1.1.1" - destroy "~1.0.4" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.3.1" - send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -3601,16 +3866,7 @@ serialize-javascript@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005" -serve-static@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" - dependencies: - encodeurl "~1.0.1" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.1" - -serve-static@^1.13.1: +serve-static@1.13.2, serve-static@^1.13.1: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" dependencies: @@ -3619,16 +3875,20 @@ serve-static@^1.13.1: parseurl "~1.3.2" send "0.16.2" +session-file-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/session-file-store/-/session-file-store-1.2.0.tgz#35a994a7fb0cbf7f784067bf9059939c520b7c44" + dependencies: + bagpipe "^0.3.5" + fs-extra "^4.0.0" + object-assign "^4.1.1" + retry "^0.10.0" + write-file-atomic "1.3.1" + set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - dependencies: - to-object-path "^0.3.0" - set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -3664,8 +3924,8 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.10" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b" + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3690,6 +3950,10 @@ slice-ansi@1.0.0: dependencies: is-fullwidth-code-point "^2.0.0" +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -3705,8 +3969,8 @@ snapdragon-util@^3.0.1: kind-of "^3.2.0" snapdragon@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" dependencies: base "^0.11.1" debug "^2.2.0" @@ -3715,7 +3979,7 @@ snapdragon@^0.8.1: map-cache "^0.2.2" source-map "^0.5.6" source-map-resolve "^0.5.0" - use "^2.0.0" + use "^3.1.0" sntp@1.x.x: version "1.0.9" @@ -3761,11 +4025,9 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" -sourcemap-codec@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.0.tgz#905439c4c65a4db421a2f2d06065bd8b55846a8e" - dependencies: - vlq "^1.0.0" +sourcemap-codec@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.1.tgz#c8fd92d91889e902a07aee392bdd2c5863958ba2" spdx-correct@^3.0.0: version "3.0.0" @@ -3800,8 +4062,8 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.14.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -3814,8 +4076,8 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^5.2.4: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.2.4.tgz#9985e14041e65fc397af96542be35724ac11da52" + version "5.3.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" dependencies: safe-buffer "^5.1.1" @@ -3830,10 +4092,6 @@ static-extend@^0.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -3849,8 +4107,8 @@ stream-each@^1.1.0: stream-shift "^1.0.0" stream-http@^2.7.2: - version "2.8.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" + version "2.8.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.1.tgz#d0441be1a457a73a733a8a7b53570bebd9ef66a4" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -3938,27 +4196,27 @@ supports-color@^3.2.3: dependencies: has-flag "^1.0.0" -supports-color@^5.2.0, supports-color@^5.3.0: +supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" dependencies: has-flag "^3.0.0" svelte-dev-helper@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/svelte-dev-helper/-/svelte-dev-helper-1.1.4.tgz#d25091ae696dc24157f998060d676e95643b50f6" + version "1.1.7" + resolved "https://registry.yarnpkg.com/svelte-dev-helper/-/svelte-dev-helper-1.1.7.tgz#b7d887c7be5abf7e2436f9467560061b1e2a935f" -svelte-loader@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/svelte-loader/-/svelte-loader-2.5.0.tgz#ee46369fc0819cc512c6a396fb33acbed034f36c" +svelte-loader@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/svelte-loader/-/svelte-loader-2.5.1.tgz#1e4e861ca8917daec6ba5e62d37189e47f08df9b" dependencies: loader-utils "^1.1.0" svelte-dev-helper "^1.1.4" tmp "0.0.31" -svelte@^1.57.1: - version "1.57.1" - resolved "https://registry.yarnpkg.com/svelte/-/svelte-1.57.1.tgz#4235a55bb85a3268afffeded9bd629573f2ee869" +svelte@^1.58.2: + version "1.58.2" + resolved "https://registry.yarnpkg.com/svelte/-/svelte-1.58.2.tgz#d69096059254e6cfb30804df4cc07b9930558bbe" svgo@^0.7.0: version "0.7.2" @@ -4009,14 +4267,15 @@ tar@^2.2.1: inherits "2" tar@^4.0.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.0.tgz#3aaf8c29b6b800a8215f33efb4df1c95ce2ac2f5" + version "4.4.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.1.tgz#b25d5a8470c976fd7a9a8a350f42c59e9fa81749" dependencies: chownr "^1.0.1" - fs-minipass "^1.2.3" - minipass "^2.2.1" + fs-minipass "^1.2.5" + minipass "^2.2.4" minizlib "^1.1.0" mkdirp "^0.5.0" + safe-buffer "^5.1.1" yallist "^3.0.2" text-table@~0.2.0: @@ -4034,6 +4293,10 @@ through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + timers-browserify@^2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" @@ -4069,7 +4332,7 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" -to-regex@^3.0.1: +to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" dependencies: @@ -4108,7 +4371,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-is@~1.6.15: +type-is@~1.6.15, type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" dependencies: @@ -4127,19 +4390,19 @@ uglify-es@^3.3.4: source-map "~0.6.1" uglify-js@3.3.x: - version "3.3.14" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.14.tgz#d3d84d18722ff342fa96029cca71c67367700079" + version "3.3.16" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.16.tgz#23ba13efa27aa00885be7417819e8a9787f94028" dependencies: - commander "~2.14.1" + commander "~2.15.0" source-map "~0.6.1" uglifyjs-webpack-plugin@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.2.tgz#e7516d4367afdb715c3847841eb46f94c45ca2b9" + version "1.2.4" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.4.tgz#5eec941b2e9b8538be0a20fc6eda25b14c7c1043" dependencies: - cacache "^10.0.1" + cacache "^10.0.4" find-cache-dir "^1.0.0" - schema-utils "^0.4.2" + schema-utils "^0.4.5" serialize-javascript "^1.4.0" source-map "^0.6.1" uglify-es "^3.3.4" @@ -4150,6 +4413,16 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" +uid-safe@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + dependencies: + random-bytes "~1.0.0" + +uid2@0.0.x: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" @@ -4185,6 +4458,10 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" +universalify@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -4222,13 +4499,11 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -use@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" dependencies: - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" + kind-of "^6.0.2" util-deprecate@~1.0.1: version "1.0.2" @@ -4240,7 +4515,7 @@ util@0.10.3, util@^0.10.3: dependencies: inherits "2.0.1" -utils-merge@1.0.1: +utils-merge@1.0.1, utils-merge@1.x.x: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -4271,10 +4546,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vlq@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" - vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -4302,9 +4573,9 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.1.1.tgz#44e4d6a869dd36fdfc0b227f9bd865a4bccfd81c" +webpack@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.2.0.tgz#a4f80807651a0e611bb09609600dc266262efcc1" dependencies: acorn "^5.0.0" acorn-dynamic-import "^3.0.0" @@ -4347,16 +4618,23 @@ wordwrap@~1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" worker-farm@^1.5.2: - version "1.5.4" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.4.tgz#4debbe46b40edefcc717ebde74a90b1ae1e909a1" + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" dependencies: errno "~0.1.7" - xtend "~4.0.1" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write-file-atomic@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" From bc80320dbee2e96835c6464bdb2ce54db36de525 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 17:13:32 -0400 Subject: [PATCH 02/22] tidy up --- routes/repl/index.html | 141 ++++++++--------------------------------- 1 file changed, 25 insertions(+), 116 deletions(-) diff --git a/routes/repl/index.html b/routes/repl/index.html index a72862d3e..ed4286085 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -453,65 +453,49 @@

Rendered component

} export default { - data() { - const search = typeof window !== 'undefined' ? window.location.search : ''; - const gistMatch = /gist=([^&]+)$/.exec(search); - const dataMatch = /data=([^&]+)$/.exec(search); - + preload({ query }) { let gist = null; let components = []; - let selectedExample = null; + let selectedComponent; let data = {}; - if (dataMatch) { - dataQuery = dataMatch[1]; // so we don't lose it from the URL later - const parsed = tryParseData(dataMatch[1]); - - if (parsed.source && !parsed.components) { - // legacy - components = [ - { - name: 'App', - type: 'html', - entry: true, - source: parsed.source - } - ]; - } else { - components = parsed.components; - components.forEach(component => { - if (!component.type) component.type = 'html'; - }); - } + if (query.data) { + const parsed = tryParseData(query.data); + + components = parsed.components; + components.forEach(component => { + if (!component.type) component.type = 'html'; + }); data = parsed.data; } - let selectedComponent = null; - if (components && components.length > 0) { selectedComponent = components[0]; - } else if (gistMatch) { - gist = gistMatch[1]; + } else if (query.gist) { + gist = query.gist; } + return this.fetch(`api/examples`).then(r => r.json()).then(example_contents => { + return { + example_contents, + + gist, + components, + selectedComponent, + data, + json: JSON.stringify(data, null, ' ') + }; + }); + }, + + data() { return { horizontalDividerPos: 50, verticalDividerPos: 50, showGenerated: false, - // TODO remove this post-https://github.com/sveltejs/svelte/issues/424 - false: false, - true: true, - null: null, - selectedExample: null, - selectedComponent, - - gist, - components, - data, - json: JSON.stringify(data, null, ' '), loadedCodemirror: false, editorRotation: 0, @@ -829,75 +813,6 @@

Rendered component

}); }, - download() { - this.set({ - downloading: true - }); - - Promise.all([ - import(/* webpackChunkName: "jszip" */ 'jszip'), - import(/* webpackChunkName: "file-saver" */'file-saver') - ]).then(([{ default: JSZip }, { default: FileSaver }]) => { - const zip = new JSZip(); - - get('/svelte-app.zip', { responseType: 'arraybuffer' }) - .then(JSZip.loadAsync) - .then(zip => { - const { bundle, components, data } = this.get(); - - // remove any dotfiles that snuck in - Object.keys(zip.files).forEach(key => { - const file = key.split('/').pop(); - if (file[0] === '.') zip.remove(key); - }); - - // add component files - components.forEach(component => { - zip.file(`src/${component.name}.${component.type}`, component.source); - }); - - // add entry point - zip.file(`src/main.js`, `import App from './App.html'; - -var app = new App({ - target: document.body, - data: ${JSON.stringify(data, null, '\t').replace(/\n/g, '\n\t')} -}); - -export default app;` ); - - const go = () => { - zip.generateAsync({ type: 'blob' }) - .then(blob => { - this.set({ - downloading: false - }); - FileSaver.saveAs(blob, 'svelte-app.zip'); - }); - }; - - if (bundle.imports.length > 0) { - zip.file('package.json') - .async('string') - .then(JSON.parse) - .then(pkg => { - const deps = {}; - bundle.imports.forEach(mod => { - const match = /^[^@\/]+/.exec(mod); - deps[match[0]] = 'latest'; - }); - pkg.dependencies = deps; - - zip.file('package.json', JSON.stringify(pkg, null, ' ')); - }) - .then(go); - } else { - go(); - } - }); - }); - }, - findExample(id) { const { example_contents } = this.get(); @@ -913,12 +828,6 @@

Rendered component

} }, - preload() { - return this.fetch(`api/examples`).then(r => r.json()).then(example_contents => { - return { example_contents }; - }); - }, - oncreate() { this.uid = 0; this.flipping = false; From c1536aa14eb32ac2cd6102c91dc646f2967e26c8 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 17:51:19 -0400 Subject: [PATCH 03/22] factor out --- routes/repl/_SplitPane.html | 164 ++++++++++++++++++++++++++++++++++++ routes/repl/index.html | 163 ++++++++--------------------------- 2 files changed, 199 insertions(+), 128 deletions(-) create mode 100644 routes/repl/_SplitPane.html diff --git a/routes/repl/_SplitPane.html b/routes/repl/_SplitPane.html new file mode 100644 index 000000000..5b16ae0aa --- /dev/null +++ b/routes/repl/_SplitPane.html @@ -0,0 +1,164 @@ +
+
+ +
+ +
+ +
+ +
+
+ +{{#if dragging}} +
+{{/if}} + + + + \ No newline at end of file diff --git a/routes/repl/index.html b/routes/repl/index.html index ed4286085..d37e5b967 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -13,8 +13,8 @@ />
-
-
+ +
{{#if selectedComponent}} loading editor...

{{/if}}
-
-
-

data.json

-
- {{#if loadedCodemirror}} - - {{else}} -

loading editor...

- {{/if}} -
- -

Rendered component

-
- {{#if loadedSvelte}} - {{#if bundle}} - - {{/if}} - {{else}} -

loading Svelte compiler...

- {{/if}} +
+ +
+

Rendered component

- {{#if dragging}} -
- {{/if}} -
+ {{#if loadedSvelte}} + {{#if bundle}} + + {{/if}} + {{else}} +

loading Svelte compiler...

+ {{/if}} +
-
-
+
+

data.json

-
+ {{#if loadedCodemirror}} + + {{else}} +

loading editor...

+ {{/if}} +
+ +
+
@@ -135,10 +131,9 @@

Rendered component

} } - .divider { - position: absolute; - z-index: 10; - display: none; + .pane { + width: 100%; + height: 100%; } h2 { @@ -232,7 +227,7 @@

Rendered component

.top { top: 0; } .bottom { bottom: 0; } - .left .editor-wrapper { + .editor-wrapper { /* make it easier to interact with scrollbar */ padding-right: 8px; height: auto; @@ -244,40 +239,6 @@

Rendered component

} } - .divider::after { - content: ''; - position: absolute; - background-color: #eee; - } - - .vertical-divider { - padding: 0 8px; - width: 0; - height: 100%; - cursor: ew-resize; - } - - .vertical-divider::after { - left: 8px; - top: 0; - width: 1px; - height: 100%; - } - - .horizontal-divider { - padding: 8px 0; - width: 100%; - height: 0; - cursor: ns-resize; - } - - .horizontal-divider::after { - top: 8px; - left: 0; - width: 100%; - height: 1px; - } - .loading { text-align: center; color: #999; @@ -343,15 +304,6 @@

Rendered component

} } - .mousecatcher { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - background: rgba(255,255,255,0.01); - } - .repl-inner :global(.message) { position: relative; border-radius: 0.2em; @@ -400,9 +352,8 @@

Rendered component

import CodeMirror from './_CodeMirror.html'; import Viewer from './_Viewer.html'; import ComponentSelector from './_ComponentSelector.html'; - import ExampleSelector from './_ExampleSelector.html'; import AppControls from './_AppControls.html'; - import UserMenu from './_UserMenu.html'; + import SplitPane from './_SplitPane.html'; import { getComponentFromGist, saveComponentAsGist } from './_utils/gist.js'; import debounce from './_utils/debounce.js'; import * as load from './_utils/load.js'; @@ -628,23 +579,10 @@

Rendered component

window.scrollTo(0, window.scrollY + d); }, - setHorizontal(event) { - const { top, bottom } = this.refs.right.getBoundingClientRect(); - - this.set({ - horizontalDividerPos: 100 * (event.clientY - top) / (bottom - top) + resizePanes(panes) { + panes.forEach(pane => { + this.refs[pane].resize(); }); - - this.refs.data.resize(); - }, - - setVertical(event) { - this.set({ - verticalDividerPos: 100 * event.clientX / window.innerWidth - }); - - this.refs.editor.resize(); - this.refs.data.resize(); }, updateData({ key, value }) { @@ -992,44 +930,13 @@

Rendered component

}); }, - events: { - drag(node, callback) { - const mousedown = event => { - if (event.which !== 1) return; - - event.preventDefault(); - - this.set({ dragging: true }); - - const onmouseup = () => { - this.set({ dragging: false }); - - window.removeEventListener('mousemove', callback, false); - window.removeEventListener('mouseup', onmouseup, false); - }; - - window.addEventListener('mousemove', callback, false); - window.addEventListener('mouseup', onmouseup, false); - } - - node.addEventListener('mousedown', mousedown, false); - - return { - teardown() { - node.removeEventListener('mousedown', onmousedown, false); - } - }; - } - }, - components: { Layout, CodeMirror, Viewer, ComponentSelector, - ExampleSelector, - UserMenu, - AppControls + AppControls, + SplitPane } }; From 99f6214574eb230968b8b4c8973506834d1c08f1 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 18:18:46 -0400 Subject: [PATCH 04/22] load codemirror inside the codemirror component --- routes/repl/_CodeMirror.html | 148 +++++++++++++++++----------- routes/repl/_ComponentSelector.html | 67 +++++++------ routes/repl/index.html | 86 +++++----------- 3 files changed, 155 insertions(+), 146 deletions(-) diff --git a/routes/repl/_CodeMirror.html b/routes/repl/_CodeMirror.html index f682a398a..21f4995cf 100644 --- a/routes/repl/_CodeMirror.html +++ b/routes/repl/_CodeMirror.html @@ -1,26 +1,32 @@ -
- - - {{#if error}} -

- {{#if error.loc}} - - {{#if error.filename}} - {{error.filename}} - {{/if}} - - ({{error.loc.line}}:{{error.loc.column}}) - - {{/if}} - - {{error.message}} -

- {{elseif warningCount > 0}} -

- Compiled, but with {{warningCount}} {{warningCount === 1 ? 'warning' : 'warnings'}} — check the console for details -

- {{/if}} -
+{{#await codemirrorPromise}} +

loading editor...

+{{then _}} +
+ + + {{#if error}} +

+ {{#if error.loc}} + + {{#if error.filename}} + {{error.filename}} + {{/if}} + + ({{error.loc.line}}:{{error.loc.column}}) + + {{/if}} + + {{error.message}} +

+ {{elseif warningCount > 0}} +

+ Compiled, but with {{warningCount}} {{warningCount === 1 ? 'warning' : 'warnings'}} — check the console for details +

+ {{/if}} +
+{{catch err}} +

error loading CodeMirror

+{{/await}} \ No newline at end of file diff --git a/routes/repl/index.html b/routes/repl/index.html index 947c54f04..e70b4e08a 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -23,27 +23,14 @@ on:remove='removeComponent(selectedComponent)' /> -
- {{#if selectedComponent}} - {{#if showGenerated && selectedComponent.compiled}} - - {{else}} - - {{/if}} - {{/if}} - - -
+
@@ -105,20 +92,6 @@

data.json

100% { opacity: 1; } } - .left, .right { - position: relative; - } - - @media (max-width: 767px) { - .left, .right { - width: 100% !important; /* override divider-set width */ - } - - .top, .bottom { - height: auto !important; - } - } - .pane { width: 100%; height: 100%; @@ -131,56 +104,6 @@

data.json

font-size: 1.2em; } - .editor-wrapper { - z-index: 5; - transform-style: preserve-3d; - animation-fill-mode: forwards; - } - - .repl-inner .editor-toggle { - position: absolute; - bottom: 1em; - right: 1em; - z-index: 10; - background: white url(/icons/flip.svg) no-repeat calc(100% - 0.7em) 50%; - background-size: 1.4em 1em; - padding-right: 2.5em; - } - - .flip-text { - /*display: none;*/ - } - - .editor-toggle:hover .flip-text { - /*display: inline-block;*/ - } - - .flip-out { - animation-name: flip-out; - animation-duration: 0.2s; - animation-timing-function: ease-in; - } - - .flip-pause { - opacity: 0; - } - - .flip-in { - animation-name: flip-in; - animation-duration: 0.2s; - animation-timing-function: ease-out; - } - - @keyframes flip-out { - from { transform: rotateY(0deg); } - to { transform: rotateY(90deg); } - } - - @keyframes flip-in { - from { transform: rotateY(-90deg); } - to { transform: rotateY(0deg); } - } - @media (min-width: 768px) { .show-if-mobile { display: none; @@ -193,35 +116,6 @@

data.json

overflow: hidden; } - .screen-too-small { - display: none; - } - - .left, .right, .divider { - display: block; - - } - - .left, .right { - height: 100%; - float: left; - } - - .top, .bottom { - position: absolute; - width: 100%; - } - - .top { top: 0; } - .bottom { bottom: 0; } - - .editor-wrapper { - /* make it easier to interact with scrollbar */ - padding-right: 8px; - height: auto; - height: 100%; - } - section { height: 100%; } @@ -268,21 +162,6 @@

data.json

box-sizing: border-box; } - .gist-link { - float: right; - line-height: 2; - font-family: Rajdhani; - font-weight: 400; - padding: 0 0.1em; - display: none; - } - - @media (min-width: 768px) { - .gist-link { - display: block; - } - } - .repl-inner :global(.message) { position: relative; border-radius: 0.2em; @@ -329,6 +208,7 @@

data.json

import { locate } from 'locate-character'; import Layout from '../_components/Layout.html'; import CodeMirror from './_CodeMirror.html'; + import ModuleEditor from './_ModuleEditor.html'; import Viewer from './_Viewer.html'; import ComponentSelector from './_ComponentSelector.html'; import AppControls from './_AppControls.html'; @@ -421,8 +301,7 @@

data.json

selectedExample: null, - editorRotation: 0, - flip: '' + editorRotation: 0 }; }, @@ -493,64 +372,6 @@

data.json

}); }, - flip() { - if (window.innerWidth < 768) { - this.flipMobile(); - return; - } - - if (this.flipping) return; - this.flipping = true; - - const wrapper = this.refs.editorWrapper; - const showGenerated = this.get('showGenerated'); - - const handleFlipOutEnd = () => { - wrapper.removeEventListener('animationend', handleFlipOutEnd); - wrapper.removeEventListener('webkitAnimationEnd', handleFlipOutEnd); - - this.set({ - showGenerated: !showGenerated, - flip: 'flip-pause' - }); - - const handleFlipInEnd = () => { - wrapper.removeEventListener('animationend', handleFlipInEnd); - wrapper.removeEventListener('webkitAnimationEnd', handleFlipInEnd); - - this.flipping = false; - - this.set({ flip: '' }); - } - - wrapper.addEventListener('animationend', handleFlipInEnd); - wrapper.addEventListener('webkitAnimationEnd', handleFlipInEnd); - - setTimeout(() => { - this.set({ flip: 'flip-in' }); - }); - } - - wrapper.addEventListener('animationend', handleFlipOutEnd); - wrapper.addEventListener('webkitAnimationEnd', handleFlipOutEnd); - - this.set({ flip: 'flip-out' }); - }, - - flipMobile() { - const bcr1 = this.refs.editorWrapper.getBoundingClientRect(); - this.set({ - showGenerated: !this.get('showGenerated') - }); - - // if top is visible, keep it that way - if (bcr1.top > 0) return; - - const bcr2 = this.refs.editorWrapper.getBoundingClientRect(); - const d = bcr2.bottom - bcr1.bottom; - window.scrollTo(0, window.scrollY + d); - }, - resizePanes(panes) { panes.forEach(pane => { this.refs[pane].resize(); @@ -740,7 +561,6 @@

data.json

oncreate() { this.uid = 0; - this.flipping = false; this.bundlePromise = null; let exampleComponents; @@ -900,6 +720,7 @@

data.json

components: { Layout, + ModuleEditor, CodeMirror, Viewer, ComponentSelector, From 91ab11c529e4ab90827457fd1fa2db9db9cb91f4 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 18:36:49 -0400 Subject: [PATCH 06/22] remove unused CSS --- routes/repl/index.html | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/routes/repl/index.html b/routes/repl/index.html index e70b4e08a..25d5deac3 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -70,28 +70,6 @@

data.json

height: 100%; } - @keyframes pulse { - 0% { opacity: 1; transform: scale(1.5); } - 50% { opacity: 0; transform: scale(1); } - 100% { opacity: 1; transform: scale(1.5); } - } - - @-webkit-keyframes pulse { - 0% { opacity: 1; transform: scale(1.5); } - 50% { opacity: 0; transform: scale(1); } - 100% { opacity: 1; transform: scale(1.5); } - } - - @keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } - } - - @-webkit-keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } - } - .pane { width: 100%; height: 100%; From f7d507cb11d6912bed82e7c1d137c238a9770454 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 18:53:01 -0400 Subject: [PATCH 07/22] minor tidy up --- routes/repl/index.html | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/routes/repl/index.html b/routes/repl/index.html index 25d5deac3..d834f3da2 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -199,8 +199,7 @@

data.json

const versionMatch = typeof window !== 'undefined' && /version=([^&]+)/.exec(window.location.search); let dataQuery; - function loadSvelte() { - const version = versionMatch ? versionMatch[1] : 'latest'; + function loadSvelte(version) { if (version === 'local') return import(/* webpackChunkName: "svelte" */ 'svelte'); return load.script(`https://unpkg.com/svelte@${version}/compiler/svelte.js`).then(() => window.svelte); } @@ -236,6 +235,8 @@

data.json

export default { preload({ query }) { + if (!process.browser) return null; + let gist = null; let components = []; let selectedComponent; @@ -262,6 +263,8 @@

data.json

return { example_contents, + version: query.version || 'latest', + gist, components, selectedComponent, @@ -273,6 +276,9 @@

data.json

data() { return { + example_contents: [], + components: [], + horizontalDividerPos: 50, verticalDividerPos: 50, showGenerated: false, @@ -487,22 +493,21 @@

data.json

updateUrl() { if (typeof history === 'undefined') return; - const gist = this.get('gist'); - const selectedExample = this.get('selectedExample'); + const { gist, selectedExample, version, query } = this.get(); const params = {}; if (typeof svelte !== 'undefined') { - params.version = versionMatch && versionMatch[1] === 'local' ? 'local' : svelte.VERSION; - } else if (versionMatch) { - params.version = versionMatch[1]; + params.version = version === 'local' ? 'local' : svelte.VERSION; + } else { + params.version = version } if (gist) { params.gist = gist; } else if (selectedExample) { params.example = selectedExample.id; - } else if (dataQuery) { - params.data = dataQuery; + } else if (query.data) { + params.data = query.data; } const queryString = Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); @@ -544,7 +549,7 @@

data.json

let exampleComponents; let lastSelectedExample; - const { gist, components } = this.get(); + const { gist, components, version } = this.get(); if (!gist && components.length === 0) { const exampleMatch = /example=([^&]+)$/.exec(window.location.search); const selectedExample = this.findExample(exampleMatch ? exampleMatch[1] : 'hello-world'); @@ -616,7 +621,7 @@

data.json

this.updateUrl(); }); - loadSvelte().then(svelte => { + loadSvelte(version).then(svelte => { window.svelte = svelte; this.set({ loadedSvelte: true }); From 3f1d53c2fcc5f873dc995f3b6aac84a44783a2c7 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 18:59:26 -0400 Subject: [PATCH 08/22] remove unused vars --- routes/repl/index.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/routes/repl/index.html b/routes/repl/index.html index d834f3da2..be5efad15 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -196,9 +196,6 @@

data.json

import * as load from './_utils/load.js'; import { get } from './_utils/get.js'; - const versionMatch = typeof window !== 'undefined' && /version=([^&]+)/.exec(window.location.search); - let dataQuery; - function loadSvelte(version) { if (version === 'local') return import(/* webpackChunkName: "svelte" */ 'svelte'); return load.script(`https://unpkg.com/svelte@${version}/compiler/svelte.js`).then(() => window.svelte); From 1d074c89a4c1594c426602c085832936429c5fc6 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 22:09:21 -0400 Subject: [PATCH 09/22] do compilation in a worker --- package.json | 3 +- routes/repl/_utils/get.js | 17 --- routes/repl/_worker.js | 114 +++++++++++++++ routes/repl/index.html | 286 +++++++++++++------------------------- webpack/client.config.js | 8 +- yarn.lock | 6 + 6 files changed, 221 insertions(+), 213 deletions(-) delete mode 100644 routes/repl/_utils/get.js create mode 100644 routes/repl/_worker.js diff --git a/package.json b/package.json index 839ec7354..202870b2e 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "style-loader": "^0.20.3", "svelte": "^1.58.2", "svelte-loader": "^2.5.1", - "webpack": "^4.2.0" + "webpack": "^4.2.0", + "workerize-loader": "^1.0.2" }, "dependencies": { "codemirror": "^5.36.0", diff --git a/routes/repl/_utils/get.js b/routes/repl/_utils/get.js deleted file mode 100644 index 902ac83c6..000000000 --- a/routes/repl/_utils/get.js +++ /dev/null @@ -1,17 +0,0 @@ -// TODO do we need this? -export function get(url, options = {}) { - return new Promise((fulfil, reject) => { - const xhr = new XMLHttpRequest(); - xhr.open('GET', url); - - xhr.responseType = options.responseType || 'text'; - - xhr.onload = () => { - fulfil(xhr.response); - }; - - xhr.onerror = reject; - - xhr.send(); - }); -} diff --git a/routes/repl/_worker.js b/routes/repl/_worker.js new file mode 100644 index 000000000..cf35336b4 --- /dev/null +++ b/routes/repl/_worker.js @@ -0,0 +1,114 @@ +global.window = self; // egregious hack to get magic-string to work in a worker + +function loadSvelte(version) { + if (version === 'local') { + return import(/* webpackChunkName: "svelte" */ 'svelte').then(s => { + global.svelte = s; + }); + } + + importScripts(`https://unpkg.com/svelte@${version}/compiler/svelte.js`); +} + +export async function init(version) { + await Promise.all([ + import(/* webpackChunkName: "rollup" */ 'rollup/dist/rollup.browser.js').then(r => { + global.rollup = r; + }), + loadSvelte(version) + ]); + + return svelte.VERSION; +} + +let bundle; +let currentToken; + +export async function compile(components) { + const token = currentToken = {}; + + console.clear(); + console.log(`running Svelte compiler version %c${svelte.VERSION}`, 'font-weight: bold'); + + const lookup = {}; + components.forEach(component => { + const path = `./${component.name}.${component.type}`; + lookup[path] = component; + }); + + let warningCount = 0; + + try { + bundle = await rollup.rollup({ + input: './App.html', + external: id => { + return id[0] !== '.'; + }, + plugins: [{ + resolveId(importee, importer) { + if (importee in lookup) return importee; + }, + load(id) { + if (id in lookup) { + const component = lookup[id]; + + if (component.type === 'js') return component.source; + + const { code, map } = svelte.compile(component.source, { + cascade: false, + name: component.name, + filename: component.name + '.html', + dev: true, + onwarn: warning => { + console.warn(warning.message); + console.log(warning.frame); + warningCount += 1; + } + }); + + return { code, map }; + } + } + }], + onwarn(warning) { + console.warn(warning); + warnings.push(warning); + warningCount += 1; + }, + cache: bundle + }); + + if (token !== currentToken) return; + + let uid = 1; + const importMap = new Map(); + + const { code, map } = await bundle.generate({ + format: 'iife', + name: 'SvelteComponent', + globals: id => { + const name = `import_${uid++}`; + importMap.set(id, name); + return name; + }, + sourcemap: true + }); + + return { + bundle: { + code, + map, + imports: bundle.imports, + importMap + }, + warningCount, + error: null + }; + } catch (err) { + return { + bundle: null, + warningCount, + error: err.message + }; + } +} \ No newline at end of file diff --git a/routes/repl/index.html b/routes/repl/index.html index be5efad15..ba4c0da0e 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -38,10 +38,8 @@

Rendered component

- {{#if loadedSvelte}} - {{#if bundle}} - - {{/if}} + {{#if bundle}} + {{else}}

loading Svelte compiler...

{{/if}} @@ -194,12 +192,6 @@

data.json

import { getComponentFromGist, saveComponentAsGist } from './_utils/gist.js'; import debounce from './_utils/debounce.js'; import * as load from './_utils/load.js'; - import { get } from './_utils/get.js'; - - function loadSvelte(version) { - if (version === 'local') return import(/* webpackChunkName: "svelte" */ 'svelte'); - return load.script(`https://unpkg.com/svelte@${version}/compiler/svelte.js`).then(() => window.svelte); - } function tryParseData(encoded) { try { @@ -212,24 +204,6 @@

data.json

} } - function compile(component) { - const warnings = []; - - if (component.type === 'js') return { code: component.source, map: null, warnings }; - - const { code, map } = svelte.compile(component.source || '', { - cascade: false, - name: component.name, - filename: component.name + '.html', - dev: true, - onwarn: warning => { - warnings.push(warning); - } - }); - - return { code, map, warnings }; - } - export default { preload({ query }) { if (!process.browser) return null; @@ -378,115 +352,6 @@

data.json

}); }, - updateBundle() { - // TODO do this in a worker - const components = this.get('components'); - - if (!components || !components.length) return; - if (components.some(c => !c.compiled)) return; - - console.clear(); - console.log(`running Svelte compiler version %c${svelte.VERSION}`, 'font-weight: bold'); - - if (this.bundlePromise) this.bundlePromise.cancel(); - - const lookup = {}; - let warningCount = 0; - for (let i = 0; i < components.length; i += 1) { - const component = components[i]; - const w = component.compiled.warnings.length; - warningCount += w; - - if (w > 0) { - console.group(`${component.name}.${component.type}: ${w} ${w === 1 ? 'warning' : 'warnings'}`); - component.compiled.warnings.forEach(warning => { - console.warn(warning.message); - console.log(warning.frame); - }); - console.groupEnd(); - } - - const path = `./${component.name}.${component.type}`; - - if (path in lookup) { - this.set({ - bundleError: new Error(`Multiple ${component.name}.${component.type} components`) - }); - return; - } - - lookup[path] = { - code: component.compiled.code, - map: component.compiled.map - }; - } - - this.set({ warningCount }); - - let cancelled = false; - - let uid = 1; - const importMap = new Map(); - const input = './App.html'; - - this.bundlePromise = rollup.rollup({ - input, - external: id => { - return id[0] !== '.'; - }, - plugins: [{ - resolveId(importee, importer) { - if (importee[0] === '.') return importee; - }, - load(id) { - if (id in lookup) return lookup[id]; - if (id[0] === '.') { - throw new Error(`file does not exist`); - } - - return null; - } - }], - onwarn(warning) { - if (warning.code === 'MISSING_GLOBAL_NAME') return; - console.warn(warning.message); - } - }).then(bundle => { - if (cancelled) return; - - return bundle.generate({ - format: 'iife', - name: 'SvelteComponent', - globals: id => { - const name = `import_${uid++}`; - importMap.set(id, name); - return name; - }, - sourcemap: true - }).then(({ code, map }) => { - this.set({ - bundle: { - code, - map, - imports: bundle.imports, - importMap - }, - bundleError: null, - runtimeError: null - }); - }); - }).catch(err => { - console.error(err.stack); - this.set({ - bundleError: err - }); - }); - - this.bundlePromise.cancel = () => { - cancelled = true; - }; - }, - updateUrl() { if (typeof history === 'undefined') return; @@ -540,8 +405,45 @@

data.json

}, oncreate() { + import('workerize-loader!./_worker.js').then(async ({ default: worker }) => { + const instance = worker(); + let { version } = this.get(); + + version = await instance.init(version); + // TODO update URL bar + + const updateBundle = async () => { + const { components } = this.get(); + + const { bundle, warningCount, error } = await instance.compile(components); + + if (error) { + this.set({ + bundle: null, + bundleError: new Error(error), + runtimeError: null, + warningCount + }); + } else { + this.set({ + bundle, + bundleError: null, + runtimeError: null, + warningCount + }); + } + }; + + this.observe('components', updateBundle); + this.observe('selectedComponent', (n, o) => { + // slightly counterintuitively, we only want to recompile if + // this is the *same* component — not if we've just selected + // a different one + if (n === o) updateBundle(); + }); + }); + this.uid = 0; - this.bundlePromise = null; let exampleComponents; let lastSelectedExample; @@ -573,7 +475,7 @@

data.json

json: JSON.stringify(example.data, null, ' ') }); - this.updateBundle(); + // this.updateBundle(); }); this.set({ gist: null }); @@ -618,59 +520,59 @@

data.json

this.updateUrl(); }); - loadSvelte(version).then(svelte => { - window.svelte = svelte; - - this.set({ loadedSvelte: true }); - - this.get('components').forEach(component => { - try { - component.compiled = compile(component); - } catch (err) { - console.error(err.stack); - - this.set({ - sourceError: err, - sourceErrorLoc: err.loc - }); - } - }); - - this.observe('selectedComponent', (selectedComponent, previousComponent) => { - if (!selectedComponent) return; - if (previousComponent && selectedComponent !== previousComponent) return; - - // if component has been edited, unset selectedExample - if (stringifyComponents(this.get('components')) !== exampleComponents) { - this.set({ selectedExample: null }); - } - - try { - selectedComponent.compiled = compile(selectedComponent); - this.set({ selectedComponent, sourceError: null, sourceErrorLoc: null }); - - if (this.get('loadedRollup')) { - this.updateBundle(); - } - } catch (err) { - console.error(err.stack); - - this.set({ - sourceError: err, - sourceErrorLoc: err.loc - }); - } - }); - - this.updateUrl(); - }); - - import(/* webpackChunkName: "rollup" */ 'rollup/dist/rollup.browser.js').then(rollup => { - this.set({ loadedRollup: true }); - window.rollup = rollup; - - this.updateBundle(); - }); + // loadSvelte(version).then(svelte => { + // window.svelte = svelte; + + // this.set({ loadedSvelte: true }); + + // this.get('components').forEach(component => { + // try { + // component.compiled = compile(component); + // } catch (err) { + // console.error(err.stack); + + // this.set({ + // sourceError: err, + // sourceErrorLoc: err.loc + // }); + // } + // }); + + // this.observe('selectedComponent', (selectedComponent, previousComponent) => { + // if (!selectedComponent) return; + // if (previousComponent && selectedComponent !== previousComponent) return; + + // // if component has been edited, unset selectedExample + // if (stringifyComponents(this.get('components')) !== exampleComponents) { + // this.set({ selectedExample: null }); + // } + + // try { + // selectedComponent.compiled = compile(selectedComponent); + // this.set({ selectedComponent, sourceError: null, sourceErrorLoc: null }); + + // if (this.get('loadedRollup')) { + // this.updateBundle(); + // } + // } catch (err) { + // console.error(err.stack); + + // this.set({ + // sourceError: err, + // sourceErrorLoc: err.loc + // }); + // } + // }); + + // this.updateUrl(); + // }); + + // import(/* webpackChunkName: "rollup" */ 'rollup/dist/rollup.browser.js').then(rollup => { + // this.set({ loadedRollup: true }); + // window.rollup = rollup; + + // this.updateBundle(); + // }); this.observe('json', json => { try { diff --git a/webpack/client.config.js b/webpack/client.config.js index db06c9d35..3bd612ac5 100644 --- a/webpack/client.config.js +++ b/webpack/client.config.js @@ -6,7 +6,9 @@ const dev = mode === 'development'; module.exports = { entry: config.client.entry(), - output: config.client.output(), + output: Object.assign(config.client.output(), { + globalObject: 'this' + }), resolve: { extensions: ['.js', '.json', '.html'] }, @@ -21,7 +23,7 @@ module.exports = { hydratable: true, cascade: false, store: true, - hotReload: true + hotReload: false } } }, @@ -36,7 +38,7 @@ module.exports = { }, mode, plugins: [ - dev && new webpack.HotModuleReplacementPlugin(), + // dev && new webpack.HotModuleReplacementPlugin(), new webpack.DefinePlugin({ 'process.browser': true, 'process.env.NODE_ENV': JSON.stringify(mode) diff --git a/yarn.lock b/yarn.lock index 1aeebcc8b..06000fc6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4623,6 +4623,12 @@ worker-farm@^1.5.2: dependencies: errno "~0.1.7" +workerize-loader@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/workerize-loader/-/workerize-loader-1.0.2.tgz#ec87bfd2f97a589907172c5ebbcc5c9abbeb7686" + dependencies: + loader-utils "^1.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 19eb66572b58c9c0271e19b381259eb38562a06f Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 22:49:54 -0400 Subject: [PATCH 10/22] fix error locations --- package.json | 2 +- routes/repl/_worker.js | 55 ++++++++++++++++++++++++++++++------------ routes/repl/index.html | 10 +++++--- yarn.lock | 2 +- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 202870b2e..2f9acdb5b 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "file-saver": "^1.3.8", "highlight.js": "^9.12.0", "jszip": "^3.1.3", - "locate-character": "^2.0.0", + "locate-character": "^2.0.5", "lru-cache": "^4.1.2", "marked": "^0.3.18", "needle": "^2.0.0", diff --git a/routes/repl/_worker.js b/routes/repl/_worker.js index cf35336b4..33beb8283 100644 --- a/routes/repl/_worker.js +++ b/routes/repl/_worker.js @@ -25,11 +25,11 @@ let bundle; let currentToken; export async function compile(components) { - const token = currentToken = {}; - console.clear(); console.log(`running Svelte compiler version %c${svelte.VERSION}`, 'font-weight: bold'); + const token = currentToken = {}; + const lookup = {}; components.forEach(component => { const path = `./${component.name}.${component.type}`; @@ -37,6 +37,8 @@ export async function compile(components) { }); let warningCount = 0; + let error; + let erroredComponent; try { bundle = await rollup.rollup({ @@ -54,19 +56,25 @@ export async function compile(components) { if (component.type === 'js') return component.source; - const { code, map } = svelte.compile(component.source, { - cascade: false, - name: component.name, - filename: component.name + '.html', - dev: true, - onwarn: warning => { - console.warn(warning.message); - console.log(warning.frame); - warningCount += 1; - } - }); - - return { code, map }; + try { + const { code, map } = svelte.compile(component.source, { + cascade: false, + name: component.name, + filename: component.name + '.html', + dev: true, + onwarn: warning => { + console.warn(warning.message); + console.log(warning.frame); + warningCount += 1; + } + }); + + return { code, map }; + } catch (err) { + error = err; + erroredComponent = component; + throw err; + } } } }], @@ -105,10 +113,25 @@ export async function compile(components) { error: null }; } catch (err) { + const e = error || err; + + if (erroredComponent && e.loc) { + const { line, column } = e.loc; + // for some reason error.loc gets borked up, maybe by Rollup? + // TODO investigation. In the meantime, fix it here + const { locate } = await import(/* webpackChunkName: "locate-character" */ 'locate-character'); + e.loc = locate(erroredComponent.source, e.pos, { offsetLine: 1 }); + e.loc.file = erroredComponent.name; + e.message = e.message.replace(` (${line}:${column})`, ''); + } + return { bundle: null, warningCount, - error: err.message + error: Object.assign({}, e, { + message: e.message, + stack: e.stack + }) }; } } \ No newline at end of file diff --git a/routes/repl/index.html b/routes/repl/index.html index ba4c0da0e..ff13be4a2 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -38,7 +38,7 @@

Rendered component

- {{#if bundle}} + {{#if compilerReady}} {{else}}

loading Svelte compiler...

@@ -420,16 +420,18 @@

data.json

if (error) { this.set({ bundle: null, - bundleError: new Error(error), + bundleError: error, runtimeError: null, - warningCount + warningCount, + compilerReady: true }); } else { this.set({ bundle, bundleError: null, runtimeError: null, - warningCount + warningCount, + compilerReady: true }); } }; diff --git a/yarn.lock b/yarn.lock index 06000fc6b..e5efae7a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2412,7 +2412,7 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" -locate-character@^2.0.0, locate-character@^2.0.5: +locate-character@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-2.0.5.tgz#f2d2614d49820ecb3c92d80d193b8db755f74c0f" From 665b67cf87151accf57bcdc6a26650395af9f89e Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sat, 24 Mar 2018 22:52:20 -0400 Subject: [PATCH 11/22] remove some unused stuff --- routes/repl/index.html | 64 ++---------------------------------------- 1 file changed, 2 insertions(+), 62 deletions(-) diff --git a/routes/repl/index.html b/routes/repl/index.html index ff13be4a2..54c3d6110 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -249,14 +249,7 @@

data.json

return { example_contents: [], components: [], - - horizontalDividerPos: 50, - verticalDividerPos: 50, - showGenerated: false, - - selectedExample: null, - - editorRotation: 0 + selectedExample: null }; }, @@ -418,6 +411,7 @@

data.json

const { bundle, warningCount, error } = await instance.compile(components); if (error) { + // TODO differentiate between bundleError and sourceError this.set({ bundle: null, bundleError: error, @@ -522,60 +516,6 @@

data.json

this.updateUrl(); }); - // loadSvelte(version).then(svelte => { - // window.svelte = svelte; - - // this.set({ loadedSvelte: true }); - - // this.get('components').forEach(component => { - // try { - // component.compiled = compile(component); - // } catch (err) { - // console.error(err.stack); - - // this.set({ - // sourceError: err, - // sourceErrorLoc: err.loc - // }); - // } - // }); - - // this.observe('selectedComponent', (selectedComponent, previousComponent) => { - // if (!selectedComponent) return; - // if (previousComponent && selectedComponent !== previousComponent) return; - - // // if component has been edited, unset selectedExample - // if (stringifyComponents(this.get('components')) !== exampleComponents) { - // this.set({ selectedExample: null }); - // } - - // try { - // selectedComponent.compiled = compile(selectedComponent); - // this.set({ selectedComponent, sourceError: null, sourceErrorLoc: null }); - - // if (this.get('loadedRollup')) { - // this.updateBundle(); - // } - // } catch (err) { - // console.error(err.stack); - - // this.set({ - // sourceError: err, - // sourceErrorLoc: err.loc - // }); - // } - // }); - - // this.updateUrl(); - // }); - - // import(/* webpackChunkName: "rollup" */ 'rollup/dist/rollup.browser.js').then(rollup => { - // this.set({ loadedRollup: true }); - // window.rollup = rollup; - - // this.updateBundle(); - // }); - this.observe('json', json => { try { this.set({ From 24518e43803c739fdf8cb6e2f87b682fb4a6c26d Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 10:20:01 -0400 Subject: [PATCH 12/22] move examples into gists, for unified approach to loading --- app/server.js | 9 +- content/examples/7guis-circles/App.html | 130 ------------ content/examples/7guis-circles/example.json | 3 - content/examples/7guis-counter/App.html | 3 - content/examples/7guis-counter/example.json | 6 - content/examples/7guis-crud/App.html | 112 ---------- content/examples/7guis-crud/example.json | 10 - content/examples/7guis-flight-booker/App.html | 71 ------- .../examples/7guis-flight-booker/example.json | 3 - content/examples/7guis-temperature/App.html | 27 --- .../examples/7guis-temperature/example.json | 6 - content/examples/7guis-timer/App.html | 53 ----- content/examples/7guis-timer/example.json | 3 - content/examples/_gists.json | 30 +++ content/examples/await-block/App.html | 26 --- content/examples/await-block/example.json | 3 - content/examples/bar-chart/App.html | 132 ------------ content/examples/bar-chart/example.json | 31 --- .../examples/binding-input-checkbox/App.html | 17 -- .../binding-input-checkbox/example.json | 19 -- .../examples/binding-input-numeric/App.html | 12 -- .../binding-input-numeric/example.json | 7 - content/examples/binding-input-radio/App.html | 16 -- .../examples/binding-input-radio/example.json | 6 - content/examples/binding-input-text/App.html | 2 - .../examples/binding-input-text/example.json | 6 - .../examples/binding-media-elements/App.html | 100 --------- .../binding-media-elements/example.json | 4 - content/examples/binding-textarea/App.html | 19 -- .../examples/binding-textarea/example.json | 6 - content/examples/each-blocks/App.html | 7 - content/examples/each-blocks/example.json | 19 -- content/examples/hacker-news/App.html | 66 ------ content/examples/hacker-news/Comment.html | 28 --- content/examples/hacker-news/Item.html | 47 ----- content/examples/hacker-news/List.html | 51 ----- content/examples/hacker-news/Summary.html | 38 ---- content/examples/hacker-news/example.json | 4 - content/examples/hello-world/App.html | 14 -- content/examples/hello-world/example.json | 6 - content/examples/if-blocks/App.html | 5 - content/examples/if-blocks/example.json | 6 - content/examples/line-chart/App.html | 153 -------------- content/examples/line-chart/example.json | 45 ---- content/examples/modal-with-slot/App.html | 33 --- content/examples/modal-with-slot/Modal.html | 39 ---- content/examples/modal-with-slot/example.json | 6 - content/examples/munge.js | 36 ++++ content/examples/nested-components/App.html | 12 -- .../examples/nested-components/Nested.html | 1 - .../examples/nested-components/example.json | 3 - content/examples/parallax/App.html | 72 ------- content/examples/parallax/example.json | 3 - content/examples/scatterplot/App.html | 29 --- content/examples/scatterplot/Scatterplot.html | 116 ----------- content/examples/scatterplot/example.json | 57 ----- content/examples/scoped-styles/App.html | 11 - content/examples/scoped-styles/example.json | 4 - content/examples/self-references/App.html | 9 - content/examples/self-references/example.json | 25 --- content/examples/svg-clock/App.html | 81 ------- content/examples/svg-clock/example.json | 4 - content/examples/transitions-custom/App.html | 50 ----- .../examples/transitions-custom/example.json | 3 - content/examples/transitions-fade/App.html | 13 -- .../examples/transitions-fade/example.json | 3 - content/examples/transitions-fly/App.html | 13 -- content/examples/transitions-fly/example.json | 3 - content/examples/transitions-in-out/App.html | 13 -- .../examples/transitions-in-out/example.json | 3 - routes/api/examples/[slug].js | 16 -- routes/api/examples/_examples.js | 64 ------ routes/api/examples/index.js | 11 - routes/gist/[id].js | 25 +++ routes/gist/create.js | 68 ++++++ routes/repl/_AppControls.html | 47 +++-- routes/repl/_ExampleSelector.html | 18 +- routes/repl/_examples.json | 197 ++++++++++++++++++ routes/repl/_worker.js | 5 +- routes/repl/index.html | 178 +++++++--------- 80 files changed, 484 insertions(+), 2148 deletions(-) delete mode 100644 content/examples/7guis-circles/App.html delete mode 100644 content/examples/7guis-circles/example.json delete mode 100644 content/examples/7guis-counter/App.html delete mode 100644 content/examples/7guis-counter/example.json delete mode 100644 content/examples/7guis-crud/App.html delete mode 100644 content/examples/7guis-crud/example.json delete mode 100644 content/examples/7guis-flight-booker/App.html delete mode 100644 content/examples/7guis-flight-booker/example.json delete mode 100644 content/examples/7guis-temperature/App.html delete mode 100644 content/examples/7guis-temperature/example.json delete mode 100644 content/examples/7guis-timer/App.html delete mode 100644 content/examples/7guis-timer/example.json create mode 100644 content/examples/_gists.json delete mode 100644 content/examples/await-block/App.html delete mode 100644 content/examples/await-block/example.json delete mode 100644 content/examples/bar-chart/App.html delete mode 100644 content/examples/bar-chart/example.json delete mode 100644 content/examples/binding-input-checkbox/App.html delete mode 100644 content/examples/binding-input-checkbox/example.json delete mode 100644 content/examples/binding-input-numeric/App.html delete mode 100644 content/examples/binding-input-numeric/example.json delete mode 100644 content/examples/binding-input-radio/App.html delete mode 100644 content/examples/binding-input-radio/example.json delete mode 100644 content/examples/binding-input-text/App.html delete mode 100644 content/examples/binding-input-text/example.json delete mode 100644 content/examples/binding-media-elements/App.html delete mode 100644 content/examples/binding-media-elements/example.json delete mode 100644 content/examples/binding-textarea/App.html delete mode 100644 content/examples/binding-textarea/example.json delete mode 100644 content/examples/each-blocks/App.html delete mode 100644 content/examples/each-blocks/example.json delete mode 100644 content/examples/hacker-news/App.html delete mode 100644 content/examples/hacker-news/Comment.html delete mode 100644 content/examples/hacker-news/Item.html delete mode 100644 content/examples/hacker-news/List.html delete mode 100644 content/examples/hacker-news/Summary.html delete mode 100644 content/examples/hacker-news/example.json delete mode 100644 content/examples/hello-world/App.html delete mode 100644 content/examples/hello-world/example.json delete mode 100644 content/examples/if-blocks/App.html delete mode 100644 content/examples/if-blocks/example.json delete mode 100644 content/examples/line-chart/App.html delete mode 100644 content/examples/line-chart/example.json delete mode 100644 content/examples/modal-with-slot/App.html delete mode 100644 content/examples/modal-with-slot/Modal.html delete mode 100644 content/examples/modal-with-slot/example.json create mode 100644 content/examples/munge.js delete mode 100644 content/examples/nested-components/App.html delete mode 100644 content/examples/nested-components/Nested.html delete mode 100644 content/examples/nested-components/example.json delete mode 100644 content/examples/parallax/App.html delete mode 100644 content/examples/parallax/example.json delete mode 100644 content/examples/scatterplot/App.html delete mode 100644 content/examples/scatterplot/Scatterplot.html delete mode 100644 content/examples/scatterplot/example.json delete mode 100644 content/examples/scoped-styles/App.html delete mode 100644 content/examples/scoped-styles/example.json delete mode 100644 content/examples/self-references/App.html delete mode 100644 content/examples/self-references/example.json delete mode 100644 content/examples/svg-clock/App.html delete mode 100644 content/examples/svg-clock/example.json delete mode 100644 content/examples/transitions-custom/App.html delete mode 100644 content/examples/transitions-custom/example.json delete mode 100644 content/examples/transitions-fade/App.html delete mode 100644 content/examples/transitions-fade/example.json delete mode 100644 content/examples/transitions-fly/App.html delete mode 100644 content/examples/transitions-fly/example.json delete mode 100644 content/examples/transitions-in-out/App.html delete mode 100644 content/examples/transitions-in-out/example.json delete mode 100644 routes/api/examples/[slug].js delete mode 100644 routes/api/examples/_examples.js delete mode 100644 routes/api/examples/index.js create mode 100644 routes/gist/[id].js create mode 100644 routes/gist/create.js create mode 100644 routes/repl/_examples.json diff --git a/app/server.js b/app/server.js index 46e624a95..cc07cc0db 100644 --- a/app/server.js +++ b/app/server.js @@ -20,15 +20,12 @@ passport.use(new Strategy({ clientSecret: process.env.GITHUB_CLIENT_SECRET, callbackURL: `http://${process.env.ORIGIN}/auth/callback` }, (accessToken, refreshToken, profile, callback) => { - console.log(profile); - return callback(null, { + token: accessToken, id: profile.id, username: profile.username, displayName: profile.displayName, - photo: profile.photos && profile.photos[0] && profile.photos[0].value, - - accessToken + photo: profile.photos && profile.photos[0] && profile.photos[0].value }); })); @@ -71,7 +68,7 @@ express() .get('/auth/callback', passport.authenticate('github', { failureRedirect: '/auth/error' }), (req, res) => { const user = req.session.passport && req.session.passport.user; - if (user) delete user.accessToken; + if (user) delete user.token; res.end(` \ No newline at end of file diff --git a/content/examples/7guis-circles/example.json b/content/examples/7guis-circles/example.json deleted file mode 100644 index 0901c2998..000000000 --- a/content/examples/7guis-circles/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Circles" -} \ No newline at end of file diff --git a/content/examples/7guis-counter/App.html b/content/examples/7guis-counter/App.html deleted file mode 100644 index 90cd49056..000000000 --- a/content/examples/7guis-counter/App.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/content/examples/7guis-counter/example.json b/content/examples/7guis-counter/example.json deleted file mode 100644 index a44879156..000000000 --- a/content/examples/7guis-counter/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Counter", - "data": { - "count": 0 - } -} \ No newline at end of file diff --git a/content/examples/7guis-crud/App.html b/content/examples/7guis-crud/App.html deleted file mode 100644 index ceb704ba6..000000000 --- a/content/examples/7guis-crud/App.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - -
- - - -
- - - - \ No newline at end of file diff --git a/content/examples/7guis-crud/example.json b/content/examples/7guis-crud/example.json deleted file mode 100644 index 5cc86a213..000000000 --- a/content/examples/7guis-crud/example.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "CRUD", - "data": { - "people": [ - { "first": "Hans", "last": "Emil" }, - { "first": "Max", "last": "Mustermann" }, - { "first": "Roman", "last": "Tisch" } - ] - } -} \ No newline at end of file diff --git a/content/examples/7guis-flight-booker/App.html b/content/examples/7guis-flight-booker/App.html deleted file mode 100644 index e04dc1f2d..000000000 --- a/content/examples/7guis-flight-booker/App.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/content/examples/7guis-flight-booker/example.json b/content/examples/7guis-flight-booker/example.json deleted file mode 100644 index 8f546a740..000000000 --- a/content/examples/7guis-flight-booker/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Flight booker" -} \ No newline at end of file diff --git a/content/examples/7guis-temperature/App.html b/content/examples/7guis-temperature/App.html deleted file mode 100644 index add1ecfd1..000000000 --- a/content/examples/7guis-temperature/App.html +++ /dev/null @@ -1,27 +0,0 @@ - - °c = - °f - - - - diff --git a/content/examples/7guis-temperature/example.json b/content/examples/7guis-temperature/example.json deleted file mode 100644 index 34b8df6c6..000000000 --- a/content/examples/7guis-temperature/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Temperature converter", - "data": { - "celsius": 0 - } -} \ No newline at end of file diff --git a/content/examples/7guis-timer/App.html b/content/examples/7guis-timer/App.html deleted file mode 100644 index 0bdc58c0c..000000000 --- a/content/examples/7guis-timer/App.html +++ /dev/null @@ -1,53 +0,0 @@ - - - -
{{ ( elapsed / 1000 ).toFixed( 1 ) }}s
- - - - - - \ No newline at end of file diff --git a/content/examples/7guis-timer/example.json b/content/examples/7guis-timer/example.json deleted file mode 100644 index 516b8bc3c..000000000 --- a/content/examples/7guis-timer/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Timer" -} \ No newline at end of file diff --git a/content/examples/_gists.json b/content/examples/_gists.json new file mode 100644 index 000000000..cba425d77 --- /dev/null +++ b/content/examples/_gists.json @@ -0,0 +1,30 @@ +[{"slug":"hello-world","link":"http://localhost:3000/repl?example=hello-world","gist":"f47d948ad2f93a968ccf41f41a4c4fef"}, + {"slug":"if-blocks","link":"http://localhost:3000/repl?example=if-blocks","gist":"555e1ee20a6cf8a5efdd80f3d733d775"}, + {"slug":"each-blocks","link":"http://localhost:3000/repl?example=each-blocks","gist":"03b53eb9ae6611a37a87b2c64cc736a6"}, + {"slug":"scoped-styles","link":"http://localhost:3000/repl?example=scoped-styles","gist":"ee8b6071bb027ab772f959c161f10829"}, + {"slug":"binding-input-text","link":"http://localhost:3000/repl?example=binding-input-text","gist":"c02997e6d74b4ff35b5167fcf08f39a7"}, + {"slug":"binding-input-numeric","link":"http://localhost:3000/repl?example=binding-input-numeric","gist":"55f8d6e34c22c5661d4606fdf634ad39"}, + {"slug":"binding-textarea","link":"http://localhost:3000/repl?example=binding-textarea","gist":"4b629960f4b2f9bdeb631fa782d8fc69"}, + {"slug":"binding-input-checkbox","link":"http://localhost:3000/repl?example=binding-input-checkbox","gist":"e2a4b664a2c6438c8a7c210b7b0d1928"}, + {"slug":"binding-input-radio","link":"http://localhost:3000/repl?example=binding-input-radio","gist":"9281789758a6ddcc8a96f577b116b91d"}, + {"slug":"binding-media-elements","link":"http://localhost:3000/repl?example=binding-media-elements","gist":"572a49986a7aa010a9ce9aca86c478a6"}, + {"slug":"nested-components","link":"http://localhost:3000/repl?example=nested-components","gist":"6d6e54f5e05e055834c37b62eca8199d"}, + {"slug":"modal-with-slot","link":"http://localhost:3000/repl?example=modal-with-slot","gist":"123192280e5e09bc8023ac906af974e9"}, + {"slug":"self-references","link":"http://localhost:3000/repl?example=self-references","gist":"2e0f3c90282cfcde01459ba66318f76e"}, + {"slug":"svg-clock","link":"http://localhost:3000/repl?example=svg-clock","gist":"42525a77c5c46c1ef177484b3b26a5de"}, + {"slug":"line-chart","link":"http://localhost:3000/repl?example=line-chart","gist":"1e8265ba2b7978844ac28b8e62c7abf0"}, + {"slug":"bar-chart","link":"http://localhost:3000/repl?example=bar-chart","gist":"349720ee7893e0d37cae8a4dee3fc5bb"}, + {"slug":"scatterplot","link":"http://localhost:3000/repl?example=scatterplot","gist":"ddc6efaf45b49589d3bdd9820a0fb5ef"}, + {"slug":"transitions-fade","link":"http://localhost:3000/repl?example=transitions-fade","gist":"7eab8577ba46f7dfc211cca467fff04c"}, + {"slug":"transitions-fly","link":"http://localhost:3000/repl?example=transitions-fly","gist":"fd0ea4288d2b646b9d9feab1b37aa2b5"}, + {"slug":"transitions-in-out","link":"http://localhost:3000/repl?example=transitions-in-out","gist":"224527cf23d8db36d3f06fb1c0fe5d1e"}, + {"slug":"transitions-custom","link":"http://localhost:3000/repl?example=transitions-custom","gist":"3272be2d51c354b7f3767246a23002f7"}, + {"slug":"await-block","link":"http://localhost:3000/repl?example=await-block","gist":"3f180bd04deccd3eb50f2b2ae98f645c"}, + {"slug":"7guis-counter","link":"http://localhost:3000/repl?example=7guis-counter","gist":"297ab99ee2157455ed97251da90656f9"}, + {"slug":"7guis-temperature","link":"http://localhost:3000/repl?example=7guis-temperature","gist":"2471795061f5fae36b6e4a9208dddb11"}, + {"slug":"7guis-flight-booker","link":"http://localhost:3000/repl?example=7guis-flight-booker","gist":"b70db83daff25ef4b29291518cc4677f"}, + {"slug":"7guis-timer","link":"http://localhost:3000/repl?example=7guis-timer","gist":"7f7f8370679a988bdba5bdad3d9c7189"}, + {"slug":"7guis-crud","link":"http://localhost:3000/repl?example=7guis-crud","gist":"20af605a966f523327c6840e040eb4a8"}, + {"slug":"7guis-circles","link":"http://localhost:3000/repl?example=7guis-circles","gist":"4ca275a30ca241c86ec2eb185e582287"}, + {"slug":"parallax","link":"http://localhost:3000/repl?example=parallax","gist":"c69eb13257e6e3ea2254330cefe7a954"}, + {"slug":"hacker-news","link":"http://localhost:3000/repl?example=hacker-news","gist":"b9e1e6399eec7823a1b3e81c1962281e"}] diff --git a/content/examples/await-block/App.html b/content/examples/await-block/App.html deleted file mode 100644 index 1e71ee99f..000000000 --- a/content/examples/await-block/App.html +++ /dev/null @@ -1,26 +0,0 @@ - - -{{#if promise}} - {{#await promise}} -

wait for it...

- {{then answer}} -

the answer is {{answer}}!

- {{catch error}} -

well that's odd

- {{/await}} -{{/if}} - - \ No newline at end of file diff --git a/content/examples/await-block/example.json b/content/examples/await-block/example.json deleted file mode 100644 index 1a9cab791..000000000 --- a/content/examples/await-block/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Await block" -} \ No newline at end of file diff --git a/content/examples/bar-chart/App.html b/content/examples/bar-chart/App.html deleted file mode 100644 index 43bdc9ba9..000000000 --- a/content/examples/bar-chart/App.html +++ /dev/null @@ -1,132 +0,0 @@ -<:Window on:resize='resize()'/> - -
-

US birthrate by year

- - - - {{#each yTicks as tick}} - - - {{tick}} {{tick === 20 ? ' per 1,000 population' : ''}} - - {{/each}} - - - - - {{#each points as point, i}} - - {{width > 380 ? point.year : formatMobile(point.year)}} - - {{/each}} - - - - {{#each points as point, i}} - - {{/each}} - - -
- - - - \ No newline at end of file diff --git a/content/examples/bar-chart/example.json b/content/examples/bar-chart/example.json deleted file mode 100644 index 05de31928..000000000 --- a/content/examples/bar-chart/example.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "title": "Bar chart", - "data": { - "points": [ - { - "year": 1990, - "birthrate": 16.7 - }, - { - "year": 1995, - "birthrate": 14.6 - }, - { - "year": 2000, - "birthrate": 14.4 - }, - { - "year": 2005, - "birthrate": 14 - }, - { - "year": 2010, - "birthrate": 13 - }, - { - "year": 2015, - "birthrate": 12.4 - } - ] - } -} \ No newline at end of file diff --git a/content/examples/binding-input-checkbox/App.html b/content/examples/binding-input-checkbox/App.html deleted file mode 100644 index 1a5d0c8b8..000000000 --- a/content/examples/binding-input-checkbox/App.html +++ /dev/null @@ -1,17 +0,0 @@ -{{#each todos as todo}} -
- - -
-{{/each}} - - \ No newline at end of file diff --git a/content/examples/binding-input-checkbox/example.json b/content/examples/binding-input-checkbox/example.json deleted file mode 100644 index ff613eadb..000000000 --- a/content/examples/binding-input-checkbox/example.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "title": "Checkbox input", - "data": { - "todos": [ - { - "description": "Buy some milk", - "done": true - }, - { - "description": "Do the laundry", - "done": true - }, - { - "description": "Find life's true purpose", - "done": false - } - ] - } -} \ No newline at end of file diff --git a/content/examples/binding-input-numeric/App.html b/content/examples/binding-input-numeric/App.html deleted file mode 100644 index f58788f85..000000000 --- a/content/examples/binding-input-numeric/App.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - -

{{a}} * {{b}} = {{a * b}}

- - \ No newline at end of file diff --git a/content/examples/binding-input-numeric/example.json b/content/examples/binding-input-numeric/example.json deleted file mode 100644 index 20ce0064f..000000000 --- a/content/examples/binding-input-numeric/example.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Numeric input", - "data": { - "a": 5, - "b": 5 - } -} \ No newline at end of file diff --git a/content/examples/binding-input-radio/App.html b/content/examples/binding-input-radio/App.html deleted file mode 100644 index 7a551f675..000000000 --- a/content/examples/binding-input-radio/App.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - -

selected {{selected}}

\ No newline at end of file diff --git a/content/examples/binding-input-radio/example.json b/content/examples/binding-input-radio/example.json deleted file mode 100644 index 94af043f9..000000000 --- a/content/examples/binding-input-radio/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Radio input", - "data": { - "selected": "blue" - } -} \ No newline at end of file diff --git a/content/examples/binding-input-text/App.html b/content/examples/binding-input-text/App.html deleted file mode 100644 index 19c72e3e8..000000000 --- a/content/examples/binding-input-text/App.html +++ /dev/null @@ -1,2 +0,0 @@ - -

Hello {{name || 'stranger'}}!

\ No newline at end of file diff --git a/content/examples/binding-input-text/example.json b/content/examples/binding-input-text/example.json deleted file mode 100644 index 83256280e..000000000 --- a/content/examples/binding-input-text/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Text input", - "data": { - "name": "" - } -} \ No newline at end of file diff --git a/content/examples/binding-media-elements/App.html b/content/examples/binding-media-elements/App.html deleted file mode 100644 index e11b94ff7..000000000 --- a/content/examples/binding-media-elements/App.html +++ /dev/null @@ -1,100 +0,0 @@ -<:Window on:click='seek(event)' on:mousemove='seek(event)'/> - - - -

THX Deep Note

-
- play/pause button - {{format(t)}} - {{format(d)}} -
- -
-

THX Deep Note

-
- play/pause button - {{format(t)}} - {{format(d)}} -
-
- - - - \ No newline at end of file diff --git a/content/examples/binding-media-elements/example.json b/content/examples/binding-media-elements/example.json deleted file mode 100644 index 98a940607..000000000 --- a/content/examples/binding-media-elements/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Media elements", - "data": {} -} \ No newline at end of file diff --git a/content/examples/binding-textarea/App.html b/content/examples/binding-textarea/App.html deleted file mode 100644 index 5862c6516..000000000 --- a/content/examples/binding-textarea/App.html +++ /dev/null @@ -1,19 +0,0 @@ - -
{{{marked(markdown)}}}
- - - - \ No newline at end of file diff --git a/content/examples/binding-textarea/example.json b/content/examples/binding-textarea/example.json deleted file mode 100644 index 4222cec63..000000000 --- a/content/examples/binding-textarea/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Textarea", - "data": { - "markdown": "# Markdown editor\n\nTODOs:\n\n* make a Svelte app\n* think of a third item for this list" - } -} \ No newline at end of file diff --git a/content/examples/each-blocks/App.html b/content/examples/each-blocks/App.html deleted file mode 100644 index 6dac67a25..000000000 --- a/content/examples/each-blocks/App.html +++ /dev/null @@ -1,7 +0,0 @@ -

Cats of YouTube

- - \ No newline at end of file diff --git a/content/examples/each-blocks/example.json b/content/examples/each-blocks/example.json deleted file mode 100644 index e96376280..000000000 --- a/content/examples/each-blocks/example.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "title": "Each blocks", - "data": { - "cats": [ - { - "name": "Keyboard Cat", - "video": "https://www.youtube.com/watch?v=J---aiyznGQ" - }, - { - "name": "Maru", - "video": "https://www.youtube.com/watch?v=z_AbfPXTKms" - }, - { - "name": "Henri The Existential Cat", - "video": "https://www.youtube.com/watch?v=OUtn3pvWmpg" - } - ] - } -} \ No newline at end of file diff --git a/content/examples/hacker-news/App.html b/content/examples/hacker-news/App.html deleted file mode 100644 index a81f76962..000000000 --- a/content/examples/hacker-news/App.html +++ /dev/null @@ -1,66 +0,0 @@ -<:Window on:hashchange='hashchange()'/> - -
- {{#if item}} - - {{elseif page}} - - {{/if}} -
- - - - \ No newline at end of file diff --git a/content/examples/hacker-news/Comment.html b/content/examples/hacker-news/Comment.html deleted file mode 100644 index 97433a0dc..000000000 --- a/content/examples/hacker-news/Comment.html +++ /dev/null @@ -1,28 +0,0 @@ -
-

{{comment.user}} {{comment.time_ago}}

- - {{{comment.content}}} - -
- {{#each comment.comments as child}} - <:Self comment='{{child}}'/> - {{/each}} -
-
- - \ No newline at end of file diff --git a/content/examples/hacker-news/Item.html b/content/examples/hacker-news/Item.html deleted file mode 100644 index 95ff9fef0..000000000 --- a/content/examples/hacker-news/Item.html +++ /dev/null @@ -1,47 +0,0 @@ -« back - - - -
- {{#each item.comments as comment}} - - {{/each}} -
- - - - \ No newline at end of file diff --git a/content/examples/hacker-news/List.html b/content/examples/hacker-news/List.html deleted file mode 100644 index 910c5e426..000000000 --- a/content/examples/hacker-news/List.html +++ /dev/null @@ -1,51 +0,0 @@ -{{#if items}} - {{#each items as item, i}} - - {{/each}} - - page {{page + 1}} -{{else}} -

loading...

-{{/if}} - - - - \ No newline at end of file diff --git a/content/examples/hacker-news/Summary.html b/content/examples/hacker-news/Summary.html deleted file mode 100644 index 944c90b34..000000000 --- a/content/examples/hacker-news/Summary.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - \ No newline at end of file diff --git a/content/examples/hacker-news/example.json b/content/examples/hacker-news/example.json deleted file mode 100644 index 9999db378..000000000 --- a/content/examples/hacker-news/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Hacker News", - "data": {} -} \ No newline at end of file diff --git a/content/examples/hello-world/App.html b/content/examples/hello-world/App.html deleted file mode 100644 index d25b2adba..000000000 --- a/content/examples/hello-world/App.html +++ /dev/null @@ -1,14 +0,0 @@ -

Hello {{name}}!

- - \ No newline at end of file diff --git a/content/examples/hello-world/example.json b/content/examples/hello-world/example.json deleted file mode 100644 index b7dd0957e..000000000 --- a/content/examples/hello-world/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Hello World!", - "data": { - "name": "world" - } -} \ No newline at end of file diff --git a/content/examples/if-blocks/App.html b/content/examples/if-blocks/App.html deleted file mode 100644 index c73bfc624..000000000 --- a/content/examples/if-blocks/App.html +++ /dev/null @@ -1,5 +0,0 @@ -{{#if foo}} -

foo!

-{{else}} -

not foo!

-{{/if}} \ No newline at end of file diff --git a/content/examples/if-blocks/example.json b/content/examples/if-blocks/example.json deleted file mode 100644 index 32f09cf35..000000000 --- a/content/examples/if-blocks/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "If blocks", - "data": { - "foo": true - } -} \ No newline at end of file diff --git a/content/examples/line-chart/App.html b/content/examples/line-chart/App.html deleted file mode 100644 index 12408c7e5..000000000 --- a/content/examples/line-chart/App.html +++ /dev/null @@ -1,153 +0,0 @@ -<:Window on:resize='resize()'/> - -
-

Arctic sea ice minimum

- - - - - {{#each yTicks as tick}} - - - {{tick}} {{tick === 8 ? ' million sq km' : ''}} - - {{/each}} - - - - - {{#each xTicks as tick}} - - - {{width > 380 ? tick : formatMobile(tick)}} - - {{/each}} - - - - - - - -

Average September extent. Source: NSIDC/NASA -

- - - - \ No newline at end of file diff --git a/content/examples/line-chart/example.json b/content/examples/line-chart/example.json deleted file mode 100644 index c077cfb72..000000000 --- a/content/examples/line-chart/example.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "title": "Line/area chart", - "data": { - "points": [ - {"x":1979,"y":7.19}, - {"x":1980,"y":7.83}, - {"x":1981,"y":7.24}, - {"x":1982,"y":7.44}, - {"x":1983,"y":7.51}, - {"x":1984,"y":7.1}, - {"x":1985,"y":6.91}, - {"x":1986,"y":7.53}, - {"x":1987,"y":7.47}, - {"x":1988,"y":7.48}, - {"x":1989,"y":7.03}, - {"x":1990,"y":6.23}, - {"x":1991,"y":6.54}, - {"x":1992,"y":7.54}, - {"x":1993,"y":6.5}, - {"x":1994,"y":7.18}, - {"x":1995,"y":6.12}, - {"x":1996,"y":7.87}, - {"x":1997,"y":6.73}, - {"x":1998,"y":6.55}, - {"x":1999,"y":6.23}, - {"x":2000,"y":6.31}, - {"x":2001,"y":6.74}, - {"x":2002,"y":5.95}, - {"x":2003,"y":6.13}, - {"x":2004,"y":6.04}, - {"x":2005,"y":5.56}, - {"x":2006,"y":5.91}, - {"x":2007,"y":4.29}, - {"x":2008,"y":4.72}, - {"x":2009,"y":5.38}, - {"x":2010,"y":4.92}, - {"x":2011,"y":4.61}, - {"x":2012,"y":3.62}, - {"x":2013,"y":5.35}, - {"x":2014,"y":5.28}, - {"x":2015,"y":4.63}, - {"x":2016,"y":4.72} - ] - } -} \ No newline at end of file diff --git a/content/examples/modal-with-slot/App.html b/content/examples/modal-with-slot/App.html deleted file mode 100644 index c2d22cb78..000000000 --- a/content/examples/modal-with-slot/App.html +++ /dev/null @@ -1,33 +0,0 @@ -{{#if showModal}} - -

- modal - adjective mod·al \ˈmō-dəl\ -

- -
    -
  1. of or relating to modality in logic
  2. -
  3. containing provisions as to the mode of procedure or the manner of taking effect —used of a contract or legacy
  4. -
  5. of or relating to a musical mode
  6. -
  7. of or relating to structure as opposed to substance
  8. -
  9. of, relating to, or constituting a grammatical form or category characteristically indicating predication
  10. -
  11. of or relating to a statistical mode
  12. -
- - merriam-webster.com -
-{{else}} - -{{/if}} - - \ No newline at end of file diff --git a/content/examples/modal-with-slot/Modal.html b/content/examples/modal-with-slot/Modal.html deleted file mode 100644 index 2bd61df89..000000000 --- a/content/examples/modal-with-slot/Modal.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - diff --git a/content/examples/modal-with-slot/example.json b/content/examples/modal-with-slot/example.json deleted file mode 100644 index 7d626a83d..000000000 --- a/content/examples/modal-with-slot/example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Modal with ", - "data": { - "showModal": true - } -} \ No newline at end of file diff --git a/content/examples/munge.js b/content/examples/munge.js new file mode 100644 index 000000000..6c49a3db2 --- /dev/null +++ b/content/examples/munge.js @@ -0,0 +1,36 @@ +const fs = require('fs'); +const path = require('path'); + +const manifest = require('./manifest.json'); +const gists = require('./_gists.json'); + +const titleBySlug = {}; + +fs.readdirSync(__dirname).forEach(file => { + const stats = fs.statSync(path.join(__dirname, file)); + if (!stats.isDirectory()) return; + + const meta = require(`./${file}/example.json`); + + titleBySlug[file] = meta.title; +}); + +console.log(titleBySlug); + +const gistBySlug = {}; + +gists.forEach(gist => { + gistBySlug[gist.slug] = gist.gist; +}); + +manifest.forEach(group => { + group.examples = group.examples.map(slug => { + return { + slug, + title: titleBySlug[slug], + gist: gistBySlug[slug] + }; + }); +}); + +fs.writeFileSync(path.join(__dirname, 'manifest2.json'), JSON.stringify(manifest, null, '\t')); \ No newline at end of file diff --git a/content/examples/nested-components/App.html b/content/examples/nested-components/App.html deleted file mode 100644 index b6ed6060b..000000000 --- a/content/examples/nested-components/App.html +++ /dev/null @@ -1,12 +0,0 @@ -

This is a top-level element.

- - - \ No newline at end of file diff --git a/content/examples/nested-components/Nested.html b/content/examples/nested-components/Nested.html deleted file mode 100644 index 74ee56a5e..000000000 --- a/content/examples/nested-components/Nested.html +++ /dev/null @@ -1 +0,0 @@ -

And this is a nested component.

\ No newline at end of file diff --git a/content/examples/nested-components/example.json b/content/examples/nested-components/example.json deleted file mode 100644 index 5848360a4..000000000 --- a/content/examples/nested-components/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Nested components" -} \ No newline at end of file diff --git a/content/examples/parallax/App.html b/content/examples/parallax/App.html deleted file mode 100644 index f7557b90b..000000000 --- a/content/examples/parallax/App.html +++ /dev/null @@ -1,72 +0,0 @@ - -<:Window bind:scrollY='sy'/> - - -
- - - - - -
- -
- (scroll down) - parallax has never been this easy -
- - \ No newline at end of file diff --git a/content/examples/parallax/example.json b/content/examples/parallax/example.json deleted file mode 100644 index b0ccc0209..000000000 --- a/content/examples/parallax/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Parallax" -} \ No newline at end of file diff --git a/content/examples/scatterplot/App.html b/content/examples/scatterplot/App.html deleted file mode 100644 index 00a4fd5e7..000000000 --- a/content/examples/scatterplot/App.html +++ /dev/null @@ -1,29 +0,0 @@ -
-

Anscombe's quartet

- - - - - -
- - - - \ No newline at end of file diff --git a/content/examples/scatterplot/Scatterplot.html b/content/examples/scatterplot/Scatterplot.html deleted file mode 100644 index b2615f51e..000000000 --- a/content/examples/scatterplot/Scatterplot.html +++ /dev/null @@ -1,116 +0,0 @@ -<:Window on:resize='resize()'/> - - - - - {{#each yTicks as tick}} - - - {{tick}} - - {{/each}} - - - - - {{#each xTicks as tick}} - - - {{tick}} - - {{/each}} - - - - {{#each points as point}} - - {{/each}} - - - - - \ No newline at end of file diff --git a/content/examples/scatterplot/example.json b/content/examples/scatterplot/example.json deleted file mode 100644 index b02b149e1..000000000 --- a/content/examples/scatterplot/example.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "title": "Scatterplot", - "data": { - "a": [ - {"x":10,"y":8.04}, - {"x":8,"y":6.95}, - {"x":13,"y":7.58}, - {"x":9,"y":8.81}, - {"x":11,"y":8.33}, - {"x":14,"y":9.96}, - {"x":6,"y":7.24}, - {"x":4,"y":4.26}, - {"x":12,"y":10.84}, - {"x":7,"y":4.82}, - {"x":5,"y":5.68} - ], - "b": [ - {"x":10,"y":9.14}, - {"x":8,"y":8.14}, - {"x":13,"y":8.74}, - {"x":9,"y":8.77}, - {"x":11,"y":9.26}, - {"x":14,"y":8.1}, - {"x":6,"y":6.13}, - {"x":4,"y":3.1}, - {"x":12,"y":9.13}, - {"x":7,"y":7.26}, - {"x":5,"y":4.74} - ], - "c": [ - {"x":10,"y":7.46}, - {"x":8,"y":6.77}, - {"x":13,"y":12.74}, - {"x":9,"y":7.11}, - {"x":11,"y":7.81}, - {"x":14,"y":8.84}, - {"x":6,"y":6.08}, - {"x":4,"y":5.39}, - {"x":12,"y":8.15}, - {"x":7,"y":6.42}, - {"x":5,"y":5.73} - ], - "d": [ - {"x":8,"y":6.58}, - {"x":8,"y":5.76}, - {"x":8,"y":7.71}, - {"x":8,"y":8.84}, - {"x":8,"y":8.47}, - {"x":8,"y":7.04}, - {"x":8,"y":5.25}, - {"x":19,"y":12.5}, - {"x":8,"y":5.56}, - {"x":8,"y":7.91}, - {"x":8,"y":6.89} - ] - } -} \ No newline at end of file diff --git a/content/examples/scoped-styles/App.html b/content/examples/scoped-styles/App.html deleted file mode 100644 index e058f2b6d..000000000 --- a/content/examples/scoped-styles/App.html +++ /dev/null @@ -1,11 +0,0 @@ -
- Big red Comic Sans -
- - \ No newline at end of file diff --git a/content/examples/scoped-styles/example.json b/content/examples/scoped-styles/example.json deleted file mode 100644 index 8c797148c..000000000 --- a/content/examples/scoped-styles/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Scoped styles", - "data": {} -} \ No newline at end of file diff --git a/content/examples/self-references/App.html b/content/examples/self-references/App.html deleted file mode 100644 index 51de6c2ea..000000000 --- a/content/examples/self-references/App.html +++ /dev/null @@ -1,9 +0,0 @@ -
    -
  • {{node.name}} - {{#if node.children}} - {{#each node.children as child}} - <:Self node='{{child}}'/> - {{/each}} - {{/if}} -
  • -
\ No newline at end of file diff --git a/content/examples/self-references/example.json b/content/examples/self-references/example.json deleted file mode 100644 index f2c2d42e7..000000000 --- a/content/examples/self-references/example.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "title": "Self-references", - "data": { - "node": { - "name": "Fruit", - "children": [ - { - "name": "Red", - "children": [ - { "name": "Cherry" }, - { "name": "Strawberry" } - ] - }, - { - "name": "Green", - "children": [ - { "name": "Apple" }, - { "name": "Pear" }, - { "name": "Lime" } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/content/examples/svg-clock/App.html b/content/examples/svg-clock/App.html deleted file mode 100644 index 96397a58a..000000000 --- a/content/examples/svg-clock/App.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - {{#each [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 ] as minute}} - - - {{#each [ 1, 2, 3, 4 ] as offset}} - - {{/each}} - {{/each}} - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/content/examples/svg-clock/example.json b/content/examples/svg-clock/example.json deleted file mode 100644 index 6855b0984..000000000 --- a/content/examples/svg-clock/example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "SVG Clock", - "data": {} -} \ No newline at end of file diff --git a/content/examples/transitions-custom/App.html b/content/examples/transitions-custom/App.html deleted file mode 100644 index 1415db929..000000000 --- a/content/examples/transitions-custom/App.html +++ /dev/null @@ -1,50 +0,0 @@ - visible - -{{#if visible}} -
- wheeee!!!!! -
-{{/if}} - - - - diff --git a/content/examples/transitions-custom/example.json b/content/examples/transitions-custom/example.json deleted file mode 100644 index cf47e4280..000000000 --- a/content/examples/transitions-custom/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Custom CSS" -} \ No newline at end of file diff --git a/content/examples/transitions-fade/App.html b/content/examples/transitions-fade/App.html deleted file mode 100644 index e0ab9970f..000000000 --- a/content/examples/transitions-fade/App.html +++ /dev/null @@ -1,13 +0,0 @@ - visible - -{{#if visible}} -

fades in and out

-{{/if}} - - \ No newline at end of file diff --git a/content/examples/transitions-fade/example.json b/content/examples/transitions-fade/example.json deleted file mode 100644 index 87e1ab0be..000000000 --- a/content/examples/transitions-fade/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Simple fade" -} \ No newline at end of file diff --git a/content/examples/transitions-fly/App.html b/content/examples/transitions-fly/App.html deleted file mode 100644 index 2c3c50e29..000000000 --- a/content/examples/transitions-fly/App.html +++ /dev/null @@ -1,13 +0,0 @@ - visible - -{{#if visible}} -

flies 200 pixels up, slowly

-{{/if}} - - \ No newline at end of file diff --git a/content/examples/transitions-fly/example.json b/content/examples/transitions-fly/example.json deleted file mode 100644 index eb24d63ba..000000000 --- a/content/examples/transitions-fly/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "Parameterised" -} \ No newline at end of file diff --git a/content/examples/transitions-in-out/App.html b/content/examples/transitions-in-out/App.html deleted file mode 100644 index 7d9239cea..000000000 --- a/content/examples/transitions-in-out/App.html +++ /dev/null @@ -1,13 +0,0 @@ - visible - -{{#if visible}} -

flies up, fades out

-{{/if}} - - \ No newline at end of file diff --git a/content/examples/transitions-in-out/example.json b/content/examples/transitions-in-out/example.json deleted file mode 100644 index 627f409fa..000000000 --- a/content/examples/transitions-in-out/example.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "In and out" -} \ No newline at end of file diff --git a/routes/api/examples/[slug].js b/routes/api/examples/[slug].js deleted file mode 100644 index 0ffa08a88..000000000 --- a/routes/api/examples/[slug].js +++ /dev/null @@ -1,16 +0,0 @@ -import { examples } from './_examples.js'; - -const lookup = new Map(); -examples.forEach(example => { - lookup.set(example.slug, JSON.stringify(example)); -}); - -export function get(req, res) { - if (lookup.has(req.params.slug)) { - res.set({ - 'Content-Type': 'application/json', - 'Cache-Control': `max-age=${30 * 60 * 1e3}` // 30 minutes - }); - res.end(lookup.get(req.params.slug)); - } -} \ No newline at end of file diff --git a/routes/api/examples/_examples.js b/routes/api/examples/_examples.js deleted file mode 100644 index d2224fb41..000000000 --- a/routes/api/examples/_examples.js +++ /dev/null @@ -1,64 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import glob from 'glob'; - -function read_json (file) { - const json = fs.readFileSync(path.resolve('content/examples', file), 'utf-8'); - return JSON.parse(json); -} - -const contents = []; -const examples = []; - -read_json('manifest.json').forEach(group => { - const group_contents = []; - - group.examples.forEach(id => { - const example = read_json(`${id}/example.json`); - - example.slug = id; - - example.data = example.data || {}; - - example.components = glob - .sync('**/*.+(html|js)', { cwd: `content/examples/${id}` }) - .map(file => { - const ext = path.extname(file); - const type = ext.slice(1); - - return { - name: file.replace(ext, ''), - type, - entry: file === 'App.html' ? true : undefined, - source: fs.readFileSync( - `content/examples/${id}/${file}`, - 'utf-8' - ) - }; - }) - .sort((a, b) => { - if (a.name === 'App') return -1; - if (b.name === 'App') return 1; - - if (a.type !== b.type) { - return a.type === 'js' ? 1 : -1; - } - - return a.name < b.name ? -1 : 1; - }); - - group_contents.push({ - id, - title: example.title - }); - - examples.push(example); - }); - - contents.push({ - name: group.name, - examples: group_contents - }); -}); - -export { examples, contents }; \ No newline at end of file diff --git a/routes/api/examples/index.js b/routes/api/examples/index.js deleted file mode 100644 index 1e2435574..000000000 --- a/routes/api/examples/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import { contents } from './_examples.js'; - -const summary = JSON.stringify(contents); - -export function get(req, res) { - res.set({ - 'Content-Type': 'application/json', - 'Cache-Control': `max-age=${30 * 60 * 1e3}` // 30 minutes - }); - res.end(summary); -} \ No newline at end of file diff --git a/routes/gist/[id].js b/routes/gist/[id].js new file mode 100644 index 000000000..d8b82b40d --- /dev/null +++ b/routes/gist/[id].js @@ -0,0 +1,25 @@ +import fetch from 'node-fetch'; + +export async function get(req, res) { + const { id } = req.params; + + const r = await fetch(`https://api.github.com/gists/${id}`); + + res.writeHead(r.status, { + 'Content-Type': 'application/json' + }); + + const result = await r.json(); + + if (r.status === 200) { + res.end(JSON.stringify({ + id: result.id, + description: result.description, + owner: result.owner, + html_url: result.html_url, + files: result.files + })); + } else { + res.end(JSON.stringify(result)); + } +} \ No newline at end of file diff --git a/routes/gist/create.js b/routes/gist/create.js new file mode 100644 index 000000000..58c7763c4 --- /dev/null +++ b/routes/gist/create.js @@ -0,0 +1,68 @@ +import fetch from 'node-fetch'; + +export function post(req, res) { + const user = req.session.passport && req.session.passport.user; + + if (!user) { + res.writeHead(403, { + 'Content-Type': 'application/json' + }); + res.end(JSON.stringify({ error: 'unauthorized' })); + return; + } + + let body = ''; + + req.on('data', chunk => { + body += chunk; + }); + + req.on('end', async () => { + const { name, components, json } = JSON.parse(body); + + const files = { + 'meta.json': { + content: JSON.stringify({ + svelte: true + }, null, ' ') + }, + 'README.md': { + content: `Created with [svelte.technology/repl](https://svelte.technology/repl)` + } + }; + components.forEach(component => { + const file = `${component.name}.${component.type}`; + files[file] = { content: component.source }; + }); + + if (json) { + files['data.json'] = { content: json }; + } + + const r = await fetch(`https://api.github.com/gists`, { + method: 'POST', + headers: { + Authorization: `token ${user.token}` + }, + body: JSON.stringify({ + description: name, + files, + public: false + }) + }); + + res.writeHead(r.status, { + 'Content-Type': 'application/json' + }); + + const gist = await r.json(); + + res.end(JSON.stringify({ + id: gist.id, + description: gist.description, + owner: gist.owner, + html_url: gist.html_url, + files: gist.files + })); + }); +} \ No newline at end of file diff --git a/routes/repl/_AppControls.html b/routes/repl/_AppControls.html index 4c20f93eb..255ffc01c 100644 --- a/routes/repl/_AppControls.html +++ b/routes/repl/_AppControls.html @@ -1,21 +1,20 @@
- +
{{#if $user}} - - - - - link to gist - - {{#if gist}} - gist - {{/if}} {{else}} {{/if}} + + + + + + {{#if gist}} + link to gist + {{/if}}
@@ -78,16 +77,21 @@ UserMenu }, + computed: { + canSave: ($user, gist) => { + if (!$user) return false; + if (!gist) return false; + return $user.id === gist.owner.id; + } + }, + methods: { login(event) { event.preventDefault(); const loginWindow = window.open(`${window.location.origin}/auth/login`, 'login', 'width=600,height=400'); const handleLogin = event => { - console.log(event); loginWindow.close(); - window.user = event.data.user; - console.log('user', window.user); this.store.set({ user: event.data.user }); window.removeEventListener('message', handleLogin); }; @@ -95,10 +99,23 @@ loginWindow.addEventListener('message', handleLogin); }, - fork() { + async fork() { + const { components, json, selectedExample } = this.get(); + this.set({ forking: true }); - // TODO actually save + const r = await fetch(`gist/create`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify({ + name: selectedExample ? selectedExample.title : 'Svelte REPL', // TODO make name editable + components, + json + }) + }); + + const gist = await r.json(); + this.fire('forked', { gist }); }, save() { diff --git a/routes/repl/_ExampleSelector.html b/routes/repl/_ExampleSelector.html index 87531894d..d847db7cd 100644 --- a/routes/repl/_ExampleSelector.html +++ b/routes/repl/_ExampleSelector.html @@ -1,18 +1,18 @@
- - {{#each example_contents as group}} + {{#each examples as group}} {{#each group.examples as example}} - + {{/each}} {{/each}}
- {{selectedExample ? selectedExample.title : 'Select an example'}} + {{name}}
@@ -59,4 +59,12 @@ .visible span { top: 0.05em; } - \ No newline at end of file + + + \ No newline at end of file diff --git a/routes/repl/_examples.json b/routes/repl/_examples.json new file mode 100644 index 000000000..662d5c931 --- /dev/null +++ b/routes/repl/_examples.json @@ -0,0 +1,197 @@ +[ + { + "name": "Basics", + "examples": [ + { + "slug": "hello-world", + "title": "Hello World!", + "gist": "f47d948ad2f93a968ccf41f41a4c4fef" + }, + { + "slug": "if-blocks", + "title": "If blocks", + "gist": "555e1ee20a6cf8a5efdd80f3d733d775" + }, + { + "slug": "each-blocks", + "title": "Each blocks", + "gist": "03b53eb9ae6611a37a87b2c64cc736a6" + }, + { + "slug": "scoped-styles", + "title": "Scoped styles", + "gist": "ee8b6071bb027ab772f959c161f10829" + } + ] + }, + { + "name": "Two-way bindings", + "examples": [ + { + "slug": "binding-input-text", + "title": "Text input", + "gist": "c02997e6d74b4ff35b5167fcf08f39a7" + }, + { + "slug": "binding-input-numeric", + "title": "Numeric input", + "gist": "55f8d6e34c22c5661d4606fdf634ad39" + }, + { + "slug": "binding-textarea", + "title": "Textarea", + "gist": "4b629960f4b2f9bdeb631fa782d8fc69" + }, + { + "slug": "binding-input-checkbox", + "title": "Checkbox input", + "gist": "e2a4b664a2c6438c8a7c210b7b0d1928" + }, + { + "slug": "binding-input-radio", + "title": "Radio input", + "gist": "9281789758a6ddcc8a96f577b116b91d" + }, + { + "slug": "binding-media-elements", + "title": "Media elements", + "gist": "572a49986a7aa010a9ce9aca86c478a6" + } + ] + }, + { + "name": "Nested components", + "examples": [ + { + "slug": "nested-components", + "title": "Nested components", + "gist": "6d6e54f5e05e055834c37b62eca8199d" + }, + { + "slug": "modal-with-slot", + "title": "Modal with ", + "gist": "123192280e5e09bc8023ac906af974e9" + }, + { + "slug": "self-references", + "title": "Self-references", + "gist": "2e0f3c90282cfcde01459ba66318f76e" + } + ] + }, + { + "name": "SVG and dataviz", + "examples": [ + { + "slug": "svg-clock", + "title": "SVG Clock", + "gist": "42525a77c5c46c1ef177484b3b26a5de" + }, + { + "slug": "line-chart", + "title": "Line/area chart", + "gist": "1e8265ba2b7978844ac28b8e62c7abf0" + }, + { + "slug": "bar-chart", + "title": "Bar chart", + "gist": "349720ee7893e0d37cae8a4dee3fc5bb" + }, + { + "slug": "scatterplot", + "title": "Scatterplot", + "gist": "ddc6efaf45b49589d3bdd9820a0fb5ef" + } + ] + }, + { + "name": "Transitions", + "examples": [ + { + "slug": "transitions-fade", + "title": "Simple fade", + "gist": "7eab8577ba46f7dfc211cca467fff04c" + }, + { + "slug": "transitions-fly", + "title": "Parameterised", + "gist": "fd0ea4288d2b646b9d9feab1b37aa2b5" + }, + { + "slug": "transitions-in-out", + "title": "In and out", + "gist": "224527cf23d8db36d3f06fb1c0fe5d1e" + }, + { + "slug": "transitions-custom", + "title": "Custom CSS", + "gist": "3272be2d51c354b7f3767246a23002f7" + } + ] + }, + { + "name": "Async data", + "examples": [ + { + "slug": "await-block", + "title": "Await block", + "gist": "3f180bd04deccd3eb50f2b2ae98f645c" + } + ] + }, + { + "name": "7guis", + "examples": [ + { + "slug": "7guis-counter", + "title": "Counter", + "gist": "297ab99ee2157455ed97251da90656f9" + }, + { + "slug": "7guis-temperature", + "title": "Temperature converter", + "gist": "2471795061f5fae36b6e4a9208dddb11" + }, + { + "slug": "7guis-flight-booker", + "title": "Flight booker", + "gist": "b70db83daff25ef4b29291518cc4677f" + }, + { + "slug": "7guis-timer", + "title": "Timer", + "gist": "7f7f8370679a988bdba5bdad3d9c7189" + }, + { + "slug": "7guis-crud", + "title": "CRUD", + "gist": "20af605a966f523327c6840e040eb4a8" + }, + { + "slug": "7guis-circles", + "title": "Circles", + "gist": "4ca275a30ca241c86ec2eb185e582287" + } + ] + }, + { + "name": "<:Window>", + "examples": [ + { + "slug": "parallax", + "title": "Parallax", + "gist": "c69eb13257e6e3ea2254330cefe7a954" + } + ] + }, + { + "name": "Miscellaneous", + "examples": [ + { + "slug": "hacker-news", + "title": "Hacker News", + "gist": "b9e1e6399eec7823a1b3e81c1962281e" + } + ] + } +] \ No newline at end of file diff --git a/routes/repl/_worker.js b/routes/repl/_worker.js index 33beb8283..eda385c1b 100644 --- a/routes/repl/_worker.js +++ b/routes/repl/_worker.js @@ -25,7 +25,7 @@ let bundle; let currentToken; export async function compile(components) { - console.clear(); + // console.clear(); console.log(`running Svelte compiler version %c${svelte.VERSION}`, 'font-weight: bold'); const token = currentToken = {}; @@ -36,6 +36,9 @@ export async function compile(components) { lookup[path] = component; }); + console.log(components); + console.log(lookup); + let warningCount = 0; let error; let erroredComponent; diff --git a/routes/repl/index.html b/routes/repl/index.html index 54c3d6110..0e5e45a2b 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -5,11 +5,15 @@
@@ -190,6 +194,7 @@

data.json

import AppControls from './_AppControls.html'; import SplitPane from './_SplitPane.html'; import { getComponentFromGist, saveComponentAsGist } from './_utils/gist.js'; + import examples from './_examples.json'; import debounce from './_utils/debounce.js'; import * as load from './_utils/load.js'; @@ -205,7 +210,7 @@

data.json

} export default { - preload({ query }) { + async preload({ query }) { if (!process.browser) return null; let gist = null; @@ -226,30 +231,27 @@

data.json

if (components && components.length > 0) { selectedComponent = components[0]; - } else if (query.gist) { - gist = query.gist; } - return this.fetch(`api/examples`).then(r => r.json()).then(example_contents => { - return { - example_contents, + return { + examples, - version: query.version || 'latest', + version: query.version || 'latest', - gist, - components, - selectedComponent, - data, - json: JSON.stringify(data, null, ' ') - }; - }); + components, + selectedComponent, + data, + json: JSON.stringify(data, null, ' ') + }; }, data() { return { - example_contents: [], + name: 'loading...', + examples, components: [], - selectedExample: null + selectedExample: null, + gist: null }; }, @@ -259,9 +261,6 @@

data.json

if (runtimeError.filename !== `${selectedComponent.name}.${selectedComponent.type}`) return; return runtimeError.loc; - }, - githubGist(gist) { - return 'https://gist.github.com/anonymous/' + gist; } }, @@ -332,23 +331,12 @@

data.json

this.set({ json: JSON.stringify(data, null, ' ') }); }, - save() { - this.set({ saving: true }); - - saveComponentAsGist(this.get('components'), this.get('json')).then(id => { - this.set({ - saving: false, - gist: id, - selectedExample: null - }); - this.updateUrl(); - }); - }, - updateUrl() { + return; // TODO + if (typeof history === 'undefined') return; - const { gist, selectedExample, version, query } = this.get(); + const { selectedExample, version, query } = this.get(); const params = {}; if (typeof svelte !== 'undefined') { @@ -383,17 +371,28 @@

data.json

}, findExample(id) { - const { example_contents } = this.get(); + const { examples } = this.get(); id = decodeURIComponent(id); - for (let i = 0; i < example_contents.length; i += 1) { - const group = example_contents[i]; + for (let i = 0; i < examples.length; i += 1) { + const group = examples[i]; for (let j = 0; j < group.examples.length; j += 1) { - const example = group.examples[j]; - if (example.id === id) return example; + const info = group.examples[j]; + if (info.slug === id) return info; } } + }, + + selectExample(slug) { + const example = this.findExample(slug); + fetch(`gist/${example.gist}`).then(r => r.json()).then(gist => { + this.set({ gist }); + }); + }, + + setGist(gist) { + } }, @@ -441,79 +440,54 @@

data.json

this.uid = 0; - let exampleComponents; - let lastSelectedExample; + const { query, components, version } = this.get(); - const { gist, components, version } = this.get(); - if (!gist && components.length === 0) { - const exampleMatch = /example=([^&]+)$/.exec(window.location.search); - const selectedExample = this.findExample(exampleMatch ? exampleMatch[1] : 'hello-world'); - this.set({ selectedExample }); + if (query.gist) { + fetch(`gist/${query.gist}`).then(r => r.json()).then(gist => { + this.set({ gist }); + }); + } else if (components.length === 0) { + this.selectExample(query.example || 'hello-world'); } - this.observe('selectedExample', example => { - if (!example) return; - const id = example.id; - - lastSelectedExample = id; - fetch(`api/examples/${id}`).then(r => r.json()).then(example => { - exampleComponents = stringifyComponents(example.components); - - if (window.svelte) { - example.components.forEach(component => { - component.compiled = compile(component); - }); - } + this.observe('gist', gist => { + if (!gist) return; - this.set({ - components: example.components, - selectedComponent: example.components[0], - json: JSON.stringify(example.data, null, ' ') - }); + let json; + const components = Object.keys(gist.files) + .map(file => { + const dot = file.lastIndexOf('.'); + if (!~dot) return; - // this.updateBundle(); - }); + const source = gist.files[file].content; - this.set({ gist: null }); - this.updateUrl(); - }); + // while we're here... + if (file === 'data.json') json = source; - if (!this.get('gist')) { - this.set({ json: JSON.stringify(this.get('data'), null, ' ') }); - } + return { + name: file.slice(0, dot), + type: file.slice(dot + 1), + source + }; + }) + .filter(x => x.type === 'html' || x.type === 'js') + .sort((a, b) => { + if (a.name === 'App' && a.type === 'html') return -1; + if (b.name === 'App' && b.type === 'html') return -1; - this.observe('gist', gist => { - if (!gist) return; + if (a.type !== b.type) return a.type === 'html' ? -1 : 1; - if (this.promise) this.promise.cancel(); - this.promise = getComponentFromGist(gist); - - this.promise - .then(({ components, json }) => { - if (window.svelte) { - components.forEach(component => { - try { - component.compiled = compile(component); - } catch (err) { - console.error(err.stack); - - this.set({ - sourceError: err, - sourceErrorLoc: err.loc - }); - } - }); - } - - this.set({ components, json, selectedComponent: components[0] }); - }) - .catch(err => { - alert('Error loading from gist.github.com – please try again later!'); - console.error(err.stack); + return a.name < b.name ? -1 : 1 }); - this.set({ selectedExample: null }); - this.updateUrl(); + this.set({ + name: gist.description, + selectedComponent: components[0], + components, + json + }); + + history.replaceState({}, 'x', `repl?gist=${gist.id}`); }); this.observe('json', json => { From 7123bb82d4c0d2abb98c817950ea00f5588be178 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 11:32:40 -0400 Subject: [PATCH 13/22] better dropdown --- assets/icons/dropdown.svg | 4 +++ routes/gist/[id].js | 50 +++++++++++++++++++++++++++++ routes/gist/_utils.js | 19 +++++++++++ routes/gist/create.js | 23 ++++++++------ routes/repl/_AppControls.html | 52 ++++++++++++++++++++++++++++--- routes/repl/_ExampleSelector.html | 33 +++++++++++++++----- routes/repl/index.html | 5 +-- 7 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 assets/icons/dropdown.svg create mode 100644 routes/gist/_utils.js diff --git a/assets/icons/dropdown.svg b/assets/icons/dropdown.svg new file mode 100644 index 000000000..b3fcdbe79 --- /dev/null +++ b/assets/icons/dropdown.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/routes/gist/[id].js b/routes/gist/[id].js index d8b82b40d..4de4eba89 100644 --- a/routes/gist/[id].js +++ b/routes/gist/[id].js @@ -1,4 +1,5 @@ import fetch from 'node-fetch'; +import { body } from './_utils.js'; export async function get(req, res) { const { id } = req.params; @@ -22,4 +23,53 @@ export async function get(req, res) { } else { res.end(JSON.stringify(result)); } +} + +export async function patch(req, res) { + const user = req.session.passport && req.session.passport.user; + + if (!user) { + res.writeHead(403, { + 'Content-Type': 'application/json' + }); + res.end(JSON.stringify({ error: 'unauthorized' })); + return; + } + + console.log(user); + + try { + const { description, files } = await body(req); + + const r = await fetch(`https://api.github.com/gists/${req.params.id}`, { + method: 'PATCH', + headers: { + Authorization: `token ${user.token}` + }, + body: JSON.stringify({ + description, + files + }) + }); + + res.writeHead(r.status, { + 'Content-Type': 'application/json' + }); + + if (r.status === 200) { + res.end(JSON.stringify({ + ok: true + })); + } else { + res.end(await r.text()); + } + } catch (err) { + res.writeHead(500, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ + error: err.message + })); + } } \ No newline at end of file diff --git a/routes/gist/_utils.js b/routes/gist/_utils.js new file mode 100644 index 000000000..841703100 --- /dev/null +++ b/routes/gist/_utils.js @@ -0,0 +1,19 @@ +export function body(req) { + return new Promise((fulfil, reject) => { + let str = ''; + + req.on('error', reject); + + req.on('data', chunk => { + str += chunk; + }); + + req.on('end', () => { + try { + fulfil(JSON.parse(str)); + } catch (err) { + reject(err); + } + }); + }); +} \ No newline at end of file diff --git a/routes/gist/create.js b/routes/gist/create.js index 58c7763c4..a49ffd6ab 100644 --- a/routes/gist/create.js +++ b/routes/gist/create.js @@ -1,6 +1,7 @@ import fetch from 'node-fetch'; +import { body } from './_utils.js'; -export function post(req, res) { +export async function post(req, res) { const user = req.session.passport && req.session.passport.user; if (!user) { @@ -11,14 +12,8 @@ export function post(req, res) { return; } - let body = ''; - - req.on('data', chunk => { - body += chunk; - }); - - req.on('end', async () => { - const { name, components, json } = JSON.parse(body); + try { + const { name, components, json } = await body(req); const files = { 'meta.json': { @@ -64,5 +59,13 @@ export function post(req, res) { html_url: gist.html_url, files: gist.files })); - }); + } catch (err) { + res.writeHead(500, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ + error: err.message + })); + } } \ No newline at end of file diff --git a/routes/repl/_AppControls.html b/routes/repl/_AppControls.html index 255ffc01c..54a7f36ed 100644 --- a/routes/repl/_AppControls.html +++ b/routes/repl/_AppControls.html @@ -81,7 +81,7 @@ canSave: ($user, gist) => { if (!$user) return false; if (!gist) return false; - return $user.id === gist.owner.id; + return $user.id == gist.owner.id; // comparing number and string } }, @@ -100,15 +100,17 @@ }, async fork() { - const { components, json, selectedExample } = this.get(); + const { name, components, json } = this.get(); this.set({ forking: true }); + // TODO handle errors + const r = await fetch(`gist/create`, { method: 'POST', credentials: 'include', body: JSON.stringify({ - name: selectedExample ? selectedExample.title : 'Svelte REPL', // TODO make name editable + name, components, json }) @@ -116,12 +118,52 @@ const gist = await r.json(); this.fire('forked', { gist }); + + this.set({ forking: false }); }, - save() { + async save() { + const { name, components, json, gist } = this.get(); + this.set({ saving: true }); - // TODO actually save + try { + const files = {}; + + // null out any deleted files + const set = new Set(components.map(m => `${m.name}.${m.type}`)); + Object.keys(gist.files).forEach(file => { + if (!set.has(file)) files[file] = null; + }); + + components.forEach(module => { + const file = `${module.name}.${module.type}`; + + if (!gist.files[files] || module.source !== gist.files[file].content) { + files[file] = { content: module.source }; + } + }); + + if (!gist.files['data.json'] || json !== gist.files['data.json'].content) { + files['data.json'] = json; + } + + const r = await fetch(`gist/${gist.id}`, { + method: 'PATCH', + credentials: 'include', + body: JSON.stringify({ + description: name, + files + }) + }); + + const result = await r.json(); + + console.log(r.status, result); + } catch (err) { + console.error(err); + // TODO show in UI + } }, download() { diff --git a/routes/repl/_ExampleSelector.html b/routes/repl/_ExampleSelector.html index d847db7cd..5f1080c05 100644 --- a/routes/repl/_ExampleSelector.html +++ b/routes/repl/_ExampleSelector.html @@ -12,7 +12,8 @@
- {{name}} + {{name}} +
@@ -21,7 +22,7 @@ position: relative; display: block; float: left; - padding: 0 1.5em 0 0; + padding: 0 0 0 2em; /* background-color: white; border: 1px solid #333; border-radius: 2px; */ @@ -29,9 +30,11 @@ font-weight: 300; font-size: 1em; line-height: 1.2; + background: url(icons/dropdown.svg) 0.5em 50% no-repeat; + background-size: 18px 18px; } - .select-wrapper::after { + /* .select-wrapper::after { content: '▼'; position: absolute; right: 0.8rem; @@ -39,7 +42,7 @@ font-size: 0.7em; color: rgba(0,0,0,0.4); pointer-events: none; - } + } */ select { position: absolute; @@ -51,13 +54,27 @@ } .visible { - pointer-events: none; - padding: 5px 0.4em; + position: relative; + padding: 6px 0 4px 0.4em; font-size: 20px; } - .visible span { - top: 0.05em; + span { + color: transparent; + } + + input { + position: absolute; + paddding: 0; + width: 100%; + height: 100%; + top: 0; + left: 0.4em; + font-family: inherit; + font-size: inherit; + font-weight: 300; + border: none; + background: none; } diff --git a/routes/repl/index.html b/routes/repl/index.html index 0e5e45a2b..1231eb864 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -250,7 +250,6 @@

data.json

name: 'loading...', examples, components: [], - selectedExample: null, gist: null }; }, @@ -336,7 +335,7 @@

data.json

if (typeof history === 'undefined') return; - const { selectedExample, version, query } = this.get(); + const { version, query } = this.get(); const params = {}; if (typeof svelte !== 'undefined') { @@ -347,8 +346,6 @@

data.json

if (gist) { params.gist = gist; - } else if (selectedExample) { - params.example = selectedExample.id; } else if (query.data) { params.data = query.data; } From 73c6942ac1977cad9ef962bf8d7b4c19e647b379 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 13:08:23 -0400 Subject: [PATCH 14/22] doh --- app/server.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/server.js b/app/server.js index cc07cc0db..3928e69c6 100644 --- a/app/server.js +++ b/app/server.js @@ -67,13 +67,12 @@ express() }) .get('/auth/callback', passport.authenticate('github', { failureRedirect: '/auth/error' }), (req, res) => { - const user = req.session.passport && req.session.passport.user; - if (user) delete user.token; + const { id, username, displayName, photo } = req.session.passport && req.session.passport.user; res.end(` `); From a84c0ade87b547db012b28bc1ed3971877d156de Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 14:27:27 -0400 Subject: [PATCH 15/22] tidy up --- routes/repl/_AppControls.html | 11 +++++++---- routes/repl/_CodeMirror.html | 6 ++---- routes/repl/_worker.js | 5 +---- routes/repl/index.html | 3 +++ 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/routes/repl/_AppControls.html b/routes/repl/_AppControls.html index 54a7f36ed..ceb0261ad 100644 --- a/routes/repl/_AppControls.html +++ b/routes/repl/_AppControls.html @@ -9,8 +9,11 @@ {{/if}} - - + + {{#if $user}} + + + {{/if}} {{#if gist}} link to gist @@ -59,7 +62,8 @@ /* position: relative; padding: 0 2em 0 0; */ line-height: 1.2; - display: block; + display: inline-block; + float: right; padding: 0.5em; font-family: Rajdhani; font-weight: 400; @@ -158,7 +162,6 @@ }); const result = await r.json(); - console.log(r.status, result); } catch (err) { console.error(err); diff --git a/routes/repl/_CodeMirror.html b/routes/repl/_CodeMirror.html index 21f4995cf..0f9c8569c 100644 --- a/routes/repl/_CodeMirror.html +++ b/routes/repl/_CodeMirror.html @@ -95,10 +95,8 @@ let codemirrorPromise; function loadCodemirror() { - console.log('loading CodeMirror') - return import(/* webpackChunkName: "codemirror" */ './_codemirror.js').then(({ default: CodeMirror }) => { - return CodeMirror; - }); + return import(/* webpackChunkName: "codemirror" */ './_codemirror.js') + .then(m => m.default); } export default { diff --git a/routes/repl/_worker.js b/routes/repl/_worker.js index eda385c1b..33beb8283 100644 --- a/routes/repl/_worker.js +++ b/routes/repl/_worker.js @@ -25,7 +25,7 @@ let bundle; let currentToken; export async function compile(components) { - // console.clear(); + console.clear(); console.log(`running Svelte compiler version %c${svelte.VERSION}`, 'font-weight: bold'); const token = currentToken = {}; @@ -36,9 +36,6 @@ export async function compile(components) { lookup[path] = component; }); - console.log(components); - console.log(lookup); - let warningCount = 0; let error; let erroredComponent; diff --git a/routes/repl/index.html b/routes/repl/index.html index 1231eb864..bd5a17b60 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -217,6 +217,7 @@

data.json

let components = []; let selectedComponent; let data = {}; + let name = 'loading...'; if (query.data) { const parsed = tryParseData(query.data); @@ -227,6 +228,7 @@

data.json

}); data = parsed.data; + name = 'Example from guide'; } if (components && components.length > 0) { @@ -241,6 +243,7 @@

data.json

components, selectedComponent, data, + name, json: JSON.stringify(data, null, ' ') }; }, From 004a37246c249bebe65a88f92a41d7db35373635 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 14:35:42 -0400 Subject: [PATCH 16/22] move some things around, remove some unused stuff --- routes/api/gists/[id].js | 23 ----- routes/api/gists/_cache.js | 6 -- routes/api/gists/index.js | 45 --------- .../AppControls.html} | 4 +- .../CodeMirror.html} | 0 .../ComponentSelector.html} | 0 .../ExampleSelector.html} | 10 +- .../ModuleEditor.html} | 2 +- .../SplitPane.html} | 0 .../UserMenu.html} | 0 .../{_Viewer.html => _components/Viewer.html} | 2 +- routes/repl/{ => _components}/_codemirror.js | 0 routes/repl/_utils/debounce.js | 11 --- routes/repl/_utils/gist.js | 91 ------------------- routes/repl/_utils/load.js | 44 --------- routes/repl/index.html | 15 ++- 16 files changed, 11 insertions(+), 242 deletions(-) delete mode 100644 routes/api/gists/[id].js delete mode 100644 routes/api/gists/_cache.js delete mode 100644 routes/api/gists/index.js rename routes/repl/{_AppControls.html => _components/AppControls.html} (98%) rename routes/repl/{_CodeMirror.html => _components/CodeMirror.html} (100%) rename routes/repl/{_ComponentSelector.html => _components/ComponentSelector.html} (100%) rename routes/repl/{_ExampleSelector.html => _components/ExampleSelector.html} (95%) rename routes/repl/{_ModuleEditor.html => _components/ModuleEditor.html} (98%) rename routes/repl/{_SplitPane.html => _components/SplitPane.html} (100%) rename routes/repl/{_UserMenu.html => _components/UserMenu.html} (100%) rename routes/repl/{_Viewer.html => _components/Viewer.html} (99%) rename routes/repl/{ => _components}/_codemirror.js (100%) delete mode 100644 routes/repl/_utils/debounce.js delete mode 100644 routes/repl/_utils/gist.js delete mode 100644 routes/repl/_utils/load.js diff --git a/routes/api/gists/[id].js b/routes/api/gists/[id].js deleted file mode 100644 index 38dc90d7b..000000000 --- a/routes/api/gists/[id].js +++ /dev/null @@ -1,23 +0,0 @@ -import cache from './_cache.js'; -import needle from 'needle'; - -export function get(req, res) { - const { id } = req.params; - - Promise.resolve( - cache.get(id) || - needle('get', - `https://api.github.com/gists/${id}?client_id=${credentials.id}&client_secret=${credentials.secret}`, - { decode: false, parse: false } - ).then(response => { - cache.set(id, response.body); - return response.body; - }) - ).then(json => { - res.set({ - 'Content-Type': 'application/json', - 'Cache-Control': `max-age=31536000` - }); - res.end(json); - }); -} \ No newline at end of file diff --git a/routes/api/gists/_cache.js b/routes/api/gists/_cache.js deleted file mode 100644 index 1713088e1..000000000 --- a/routes/api/gists/_cache.js +++ /dev/null @@ -1,6 +0,0 @@ -import LRU from 'lru-cache'; - -export default new LRU({ - max: 50 * 1024 * 1024, // basically a random number [shrug] - length: str => str.length -}); \ No newline at end of file diff --git a/routes/api/gists/index.js b/routes/api/gists/index.js deleted file mode 100644 index b1b18e8bc..000000000 --- a/routes/api/gists/index.js +++ /dev/null @@ -1,45 +0,0 @@ -import fs from 'fs'; -import needle from 'needle'; -import cache from './_cache.js'; - -let credentials = { - id: process.env.client_id, - secret: process.env.client_secret -}; - -try { - const json = fs.readFileSync('credentials.json', 'utf-8'); - credentials = JSON.parse(json); -} catch(err) { - // noop -} - -export function post(req, res) { - let body = ''; - - req.on('data', chunk => { - body += chunk; - }); - - req.on('end', () => { - needle.post( - `https://api.github.com/gists?client_id=${credentials.id}&client_secret=${credentials.secret}`, - body, - (err, response) => { - if (err) { - console.error(err.message); - res.status(500).end(err.message); - } else { - const json = JSON.stringify(response.body); - cache.set(response.body.id, json); - - res.set({ - 'Content-Type': 'application/json', - 'Cache-Control': `max-age=31536000` - }); - res.end(json); - } - } - ); - }); -} diff --git a/routes/repl/_AppControls.html b/routes/repl/_components/AppControls.html similarity index 98% rename from routes/repl/_AppControls.html rename to routes/repl/_components/AppControls.html index ceb0261ad..9f75a5180 100644 --- a/routes/repl/_AppControls.html +++ b/routes/repl/_components/AppControls.html @@ -72,8 +72,8 @@ \ No newline at end of file + \ No newline at end of file diff --git a/routes/repl/_ModuleEditor.html b/routes/repl/_components/ModuleEditor.html similarity index 98% rename from routes/repl/_ModuleEditor.html rename to routes/repl/_components/ModuleEditor.html index 226c13017..90249cd7a 100644 --- a/routes/repl/_ModuleEditor.html +++ b/routes/repl/_components/ModuleEditor.html @@ -74,7 +74,7 @@ \ No newline at end of file From 1a0f034f4c49da4d70910fd74a8d1e99f0cf84f1 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 14:40:10 -0400 Subject: [PATCH 18/22] remove obsolete reference to store --- routes/guide/index.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/routes/guide/index.html b/routes/guide/index.html index 7108338e2..4135818e7 100644 --- a/routes/guide/index.html +++ b/routes/guide/index.html @@ -230,10 +230,6 @@

{{section.metadata.title}}

} export default { - store() { - return store; - }, - preload() { return this.fetch(`api/guide`).then(r => r.json()).then(sections => { return { sections }; From 89ca47b02b956a30b9347881bd3ca1a49b971e6f Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 14:42:26 -0400 Subject: [PATCH 19/22] only null out deleted components, preserve README etc --- routes/repl/_components/AppControls.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routes/repl/_components/AppControls.html b/routes/repl/_components/AppControls.html index 9f75a5180..fb9a33a6d 100644 --- a/routes/repl/_components/AppControls.html +++ b/routes/repl/_components/AppControls.html @@ -137,7 +137,9 @@ // null out any deleted files const set = new Set(components.map(m => `${m.name}.${m.type}`)); Object.keys(gist.files).forEach(file => { - if (!set.has(file)) files[file] = null; + if (/.(html|js)$/.test(file)) { + if (!set.has(file)) files[file] = null; + } }); components.forEach(module => { From 7b0442b9a3c2e7f0fe591e493240198a35131029 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 14:48:32 -0400 Subject: [PATCH 20/22] typo --- routes/repl/_components/AppControls.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/repl/_components/AppControls.html b/routes/repl/_components/AppControls.html index fb9a33a6d..75b70c555 100644 --- a/routes/repl/_components/AppControls.html +++ b/routes/repl/_components/AppControls.html @@ -137,7 +137,7 @@ // null out any deleted files const set = new Set(components.map(m => `${m.name}.${m.type}`)); Object.keys(gist.files).forEach(file => { - if (/.(html|js)$/.test(file)) { + if (/\.(html|js)$/.test(file)) { if (!set.has(file)) files[file] = null; } }); From d8d80e62145dc662f63c6b222960b4e88080a607 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 15:36:31 -0400 Subject: [PATCH 21/22] maybe this works? --- app/server.js | 3 ++- package.json | 4 ++-- yarn.lock | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/server.js b/app/server.js index 3928e69c6..33ac97292 100644 --- a/app/server.js +++ b/app/server.js @@ -18,7 +18,8 @@ const FileStore = sessionFileStore(session); passport.use(new Strategy({ clientID: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, - callbackURL: `http://${process.env.ORIGIN}/auth/callback` + callbackURL: `${process.env.BASEURL}/auth/callback`, + userAgent: 'svelte.technology' }, (accessToken, refreshToken, profile, callback) => { return callback(null, { token: accessToken, diff --git a/package.json b/package.json index 2f9acdb5b..03c4038ab 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "passport": "^0.4.0", "passport-github": "^1.1.0", "rollup": "^0.57.1", - "sapper": "^0.10.1", + "sapper": "^0.10.2", "serve-static": "^1.13.1", "session-file-store": "^1.2.0", "sourcemap-codec": "^1.4.1" @@ -73,7 +73,7 @@ "now": { "env": { "NODE_ENV": "production", - "ORIGIN": "svelte.technology", + "BASEURL": "https://svelte.technology", "GITHUB_CLIENT_ID": "@svelte-gist-client-id", "GITHUB_CLIENT_SECRET": "@svelte-gist-client-secret" }, diff --git a/yarn.lock b/yarn.lock index e5efae7a6..0084220a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3804,9 +3804,9 @@ sander@^0.6.0: mkdirp "^0.5.1" rimraf "^2.5.2" -sapper@^0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/sapper/-/sapper-0.10.1.tgz#174f27e840a0acf2dbc7bb27cd379e84e50907b4" +sapper@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/sapper/-/sapper-0.10.2.tgz#da493c6564446ceee3f050f17019e486fd7f41de" dependencies: cheerio "^1.0.0-rc.2" chokidar "^2.0.2" From 78a56a90108f4c2d5b8130bf1e1288cc7ad8cdb0 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Sun, 25 Mar 2018 15:59:56 -0400 Subject: [PATCH 22/22] update URL when necessary --- routes/repl/_worker.js | 2 +- routes/repl/index.html | 46 ++++++++++++++++-------------------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/routes/repl/_worker.js b/routes/repl/_worker.js index 33beb8283..3e858858a 100644 --- a/routes/repl/_worker.js +++ b/routes/repl/_worker.js @@ -18,7 +18,7 @@ export async function init(version) { loadSvelte(version) ]); - return svelte.VERSION; + return version === 'local' ? version : svelte.VERSION; } let bundle; diff --git a/routes/repl/index.html b/routes/repl/index.html index aafb94d09..107b00f3f 100644 --- a/routes/repl/index.html +++ b/routes/repl/index.html @@ -260,6 +260,18 @@

data.json

if (runtimeError.filename !== `${selectedComponent.name}.${selectedComponent.type}`) return; return runtimeError.loc; + }, + + url: (version, gist, query) => { + const params = []; + if (version !== 'latest') params.push(`version=${version}`); + if (gist) params.push(`gist=${gist.id}`); + else if (query.gist) params.push(`gist=${query.gist}`); + else if (query.data) params.push(`data=${query.data}`); + + return params.length > 0 + ? `repl?${params.join('&')}` + : 'repl'; } }, @@ -330,32 +342,6 @@

data.json

this.set({ json: JSON.stringify(data, null, ' ') }); }, - updateUrl() { - return; // TODO - - if (typeof history === 'undefined') return; - - const { version, query } = this.get(); - - const params = {}; - if (typeof svelte !== 'undefined') { - params.version = version === 'local' ? 'local' : svelte.VERSION; - } else { - params.version = version - } - - if (gist) { - params.gist = gist; - } else if (query.data) { - params.data = query.data; - } - - const queryString = Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); - const url = queryString ? `/repl?${queryString}` : '/repl'; - - history.replaceState({}, 'x', url); - }, - navigate(filename) { const name = filename.replace(/\.html$/, ''); const { components, selectedComponent } = this.get(); @@ -399,7 +385,7 @@

data.json

let { version } = this.get(); version = await instance.init(version); - // TODO update URL bar + this.set({ version }); const updateBundle = async () => { const { components } = this.get(); @@ -483,8 +469,6 @@

data.json

components, json }); - - history.replaceState({}, 'x', `repl?gist=${gist.id}`); }); this.observe('json', json => { @@ -511,6 +495,10 @@

data.json

} } }); + + this.observe('url', url => { + history.replaceState({}, 'x', url); + }); }, components: {