diff --git a/.gitignore b/.gitignore index 3669f86f..479c5590 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.sublime-workspace node_modules bundle.js +target diff --git a/doc/TODO.md b/doc/TODO.md index f3e41d42..b667c51b 100644 --- a/doc/TODO.md +++ b/doc/TODO.md @@ -11,7 +11,7 @@ - DONE: store state - DONE: make summary work better (name and joined/inviteCount doesn't seem to work well) - DONE: timeline doesn't seem to recover it's key well upon loading, the query in load seems to never yield an event in the persister - - map DOMException to something better + - DONE: map DOMException to something better - it's pretty opaque now when something idb related fails. DOMException has these fields: code: 0 message: "Key already exists in the object store." @@ -26,21 +26,44 @@ - DONE: clicking on a room list, you see messages (userId -> body) - DONE: style minimal UI - DONE: implement gap filling and fragments (see FRAGMENTS.md) - - allow collection items (especially tiles) to self-update + - DONE: allow collection items (especially tiles) to self-update - improve fragmentidcomparer::add - - send messages - - better UI + - DONE: better UI - fix MappedMap update mechanism - see if in BaseObservableMap we need to change ...params - - put sync button and status label inside SessionView + - DONE: put sync button and status label inside SessionView - fix some errors: - find out if `(this._emitCollectionUpdate)(this)` is different than `this._emitCollectionUpdate(this)` - got "database tried to mutate when not allowed" or something error as well - find out why when RoomPersister.(\_createGapEntry/\_createEventEntry) we remove .buffer the transaction fails (good), but upon fixing and refreshing is missing a message! syncToken should not be saved, so why isn't this again in the sync response and now the txn does succeed? - DONE: take access token out of IDB? this way it can be stored in a more secure thing for non-web clients, together wit encryption key for olm sessions ... ? like macos keychain, gnome keyring, ... maybe using https://www.npmjs.com/package/keytar - - experiment with using just a normal array with 2 numbers for sortkeys, to work in Edge as well. - - send messages - - fill gaps with call to /messages + - DONE: experiment with using just a normal array with 2 numbers for sortkeys, to work in Edge as well. + - DONE: send messages + - DONE: fill gaps with call to /messages + + - build script + - DONE: take dev index.html, run some dom modifications to change script tag with `parse5`. + - DONE: create js bundle, rollup + - DONE: create css bundle, postcss, probably just need postcss-import for now, but good to have more options + - DONE: put all in /target + - have option to run it locally to test + + - deploy script + - upload /target to github pages + + - offline available + - both offline mechanisms have (filelist, version) as input for their template: + - create appcache manifest with (index.html, brawl.js, brawl.css) and print version number in it + - create service worker wit file list to cache (at top const files = "%%FILES_ARRAY%%", version = "%%VERSION%%") + - write web manifest + - delete sessions from picker & option to close current session and go back to picker + + - create room + - join room + - accept invite + - leave room + - unread rooms, badge count, sort rooms by activity + - create sync filter - lazy loading members - decide denormalized data in summary vs reading from multiple stores PER room on load diff --git a/index.html b/index.html index 8ae1e5cf..ef553722 100644 --- a/index.html +++ b/index.html @@ -2,6 +2,8 @@ + + diff --git a/package.json b/package.json index d6ecacbc..85e65434 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "brawl-chat", - "version": "1.0.0", + "version": "0.0.1", "description": "A javascript matrix client prototype, trying to minize RAM usage by offloading as much as possible to IndexedDB", "main": "index.js", "directories": { @@ -9,22 +9,26 @@ "scripts": { "test": "node_modules/.bin/impunity --entryPoint src/main.js --force-esm", "start": "node scripts/serve-local.js", - "build": "node_modules/rollup/bin/rollup -c" + "build": "node --experimental-modules scripts/build.mjs" }, "repository": { "type": "git", "url": "git+https://github.com/bwindels/brawl-chat.git" }, - "author": "", + "author": "Bruno Windels", "license": "ISC", "bugs": { "url": "https://github.com/bwindels/brawl-chat/issues" }, "homepage": "https://github.com/bwindels/brawl-chat#readme", "devDependencies": { + "cheerio": "^1.0.0-rc.3", "finalhandler": "^1.1.1", "impunity": "^0.0.7", + "postcss": "^7.0.18", + "postcss-import": "^12.0.1", "rollup": "^1.15.6", "serve-static": "^1.13.2" - } + }, + "type": "module" } diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index ebaa9ff0..00000000 --- a/rollup.config.js +++ /dev/null @@ -1,8 +0,0 @@ -export default { - input: 'src/main.js', - output: { - file: 'bundle.js', - format: 'iife', - name: 'main' - } -}; diff --git a/scripts/build.mjs b/scripts/build.mjs new file mode 100644 index 00000000..90d13b07 --- /dev/null +++ b/scripts/build.mjs @@ -0,0 +1,99 @@ +import cheerio from "cheerio"; +import fsRoot from "fs"; +const fs = fsRoot.promises; +import path from "path"; +import rollup from 'rollup'; +import postcss from "postcss"; +import postcssImport from "postcss-import"; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; + + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectDir = path.join(__dirname, "../"); +const targetDir = path.join(projectDir, "target"); + +const jsPostfix = ` +window.DEBUG = true; +let buf = ""; +console.error = (...params) => { + const lastLines = "...\\n" + buf.split("\\n").slice(-10).join("\\n"); + // buf = buf + "ERR " + params.join(" ") + "\\n"; + // const location = new Error().stack.split("\\n")[2]; + alert(params.join(" ") +"\\n...\\n" + lastLines); +}; +console.log = console.info = console.warn = (...params) => { + buf = buf + params.join(" ") + "\\n"; +}; +`; + +const jsSuffix = ` +setTimeout(() => { + const showlogs = document.getElementById("showlogs"); + showlogs.addEventListener("click", () => { + const lastLines = "...\\n" + buf.split("\\n").slice(-20).join("\\n"); + alert(lastLines); + }, true); + showlogs.innerText = "Show last 20 log lines"; +}, 10000); +`; + +async function build() { + // get version number + const version = JSON.parse(await fs.readFile(path.join(projectDir, "package.json"), "utf8")).version; + // clear target dir + await removeDirIfExists(targetDir); + await fs.mkdir(targetDir); + // transform html file + const devHtml = await fs.readFile(path.join(projectDir, "index.html"), "utf8"); + const doc = cheerio.load(devHtml); + doc("link[rel=stylesheet]").attr("href", "brawl.css"); + // doc("html").attr("manifest", "manifest.appcache"); + doc("script").replaceWith( + `` + + ``); + await fs.writeFile(path.join(targetDir, "index.html"), doc.html(), "utf8"); + // create js bundle + const rollupConfig = { + input: 'src/main.js', + output: { + file: path.join(targetDir, "brawl.js"), + format: 'iife', + name: 'main' + } + }; + const bundle = await rollup.rollup(rollupConfig); + await bundle.write(rollupConfig); + // create css bundle + const cssMainFile = path.join(projectDir, "src/ui/web/css/main.css"); + const preCss = await fs.readFile(cssMainFile, "utf8"); + const cssBundler = postcss([postcssImport]); + const postCss = await cssBundler.process(preCss, {from: cssMainFile}); + await fs.writeFile(path.join(targetDir, "brawl.css"), postCss, "utf8"); + // write appcache manifest + const manifestLines = [ + `CACHE MANIFEST`, + `# v${version}`, + "brawl.js", + "brawl.css", + "index.html", + "" + ]; + await fs.writeFile(path.join(targetDir, "manifest.appcache"), manifestLines.join("\n"), "utf8"); + console.log(`built brawl ${version} successfully`); +} + +async function removeDirIfExists(targetDir) { + try { + const files = await fs.readdir(targetDir); + await Promise.all(files.map(filename => fs.unlink(path.join(targetDir, filename)))); + await fs.rmdir(targetDir); + } catch (err) { + if (err.code !== "ENOENT") { + throw err; + } + } +} + +build().catch(err => console.error(err)); diff --git a/src/domain/session/room/RoomViewModel.js b/src/domain/session/room/RoomViewModel.js index 23875e20..09de2b8b 100644 --- a/src/domain/session/room/RoomViewModel.js +++ b/src/domain/session/room/RoomViewModel.js @@ -66,7 +66,16 @@ export default class RoomViewModel extends EventEmitter { sendMessage(message) { if (message) { - this._room.sendEvent("m.room.message", {msgtype: "m.text", body: message}); + try { + this._room.sendEvent("m.room.message", {msgtype: "m.text", body: message}); + } catch (err) { + console.error(`room.sendMessage(): ${err.message}:\n${err.stack}`); + this._timelineError = err; + this.emit("change", "error"); + return false; + } + return true; } + return false; } } diff --git a/src/matrix/hs-api.js b/src/matrix/hs-api.js index 0dd1e225..2e9bedbe 100644 --- a/src/matrix/hs-api.js +++ b/src/matrix/hs-api.js @@ -67,7 +67,11 @@ export default class HomeServerApi { method, headers, body: bodyString, - signal: controller && controller.signal + signal: controller && controller.signal, + mode: "cors", + credentials: "omit", + referrer: "no-referrer", + cache: "no-cache", }); promise = promise.then(async (response) => { if (response.ok) { diff --git a/src/matrix/room/sending/SendQueue.js b/src/matrix/room/sending/SendQueue.js index ec7296e8..f85e9240 100644 --- a/src/matrix/room/sending/SendQueue.js +++ b/src/matrix/room/sending/SendQueue.js @@ -96,6 +96,7 @@ export default class SendQueue { async enqueueEvent(eventType, content) { const pendingEvent = await this._createAndStoreEvent(eventType, content); this._pendingEvents.set(pendingEvent); + console.log("added to _pendingEvents set", this._pendingEvents.length); if (!this._isSending && !this._offline) { this._sendLoop(); } @@ -127,11 +128,14 @@ export default class SendQueue { } async _createAndStoreEvent(eventType, content) { + console.log("_createAndStoreEvent"); const txn = await this._storage.readWriteTxn([this._storage.storeNames.pendingEvents]); let pendingEvent; try { const pendingEventsStore = txn.pendingEvents; + console.log("_createAndStoreEvent getting maxQueueIndex"); const maxQueueIndex = await pendingEventsStore.getMaxQueueIndex(this._roomId) || 0; + console.log("_createAndStoreEvent got maxQueueIndex", maxQueueIndex); const queueIndex = maxQueueIndex + 1; pendingEvent = new PendingEvent({ roomId: this._roomId, @@ -140,6 +144,7 @@ export default class SendQueue { content, txnId: makeTxnId() }); + console.log("_createAndStoreEvent: adding to pendingEventsStore"); pendingEventsStore.add(pendingEvent.data); } catch (err) { txn.abort(); diff --git a/src/matrix/storage/idb/query-target.js b/src/matrix/storage/idb/query-target.js index fa5b99f5..7e848218 100644 --- a/src/matrix/storage/idb/query-target.js +++ b/src/matrix/storage/idb/query-target.js @@ -17,6 +17,10 @@ export default class QueryTarget { } } + supports(methodName) { + return this._target.supports(methodName); + } + get(key) { return reqAsPromise(this._target.get(key)); } diff --git a/src/matrix/storage/idb/store.js b/src/matrix/storage/idb/store.js index 58709573..3634b42f 100644 --- a/src/matrix/storage/idb/store.js +++ b/src/matrix/storage/idb/store.js @@ -6,8 +6,16 @@ class QueryTargetWrapper { constructor(qt) { this._qt = qt; } + + supports(methodName) { + return !!this._qt[methodName]; + } openKeyCursor(...params) { + // not supported on Edge 15 + if (!this._qt.openKeyCursor) { + return this.openCursor(...params); + } try { return this._qt.openKeyCursor(...params); } catch(err) { diff --git a/src/matrix/storage/idb/stores/PendingEventStore.js b/src/matrix/storage/idb/stores/PendingEventStore.js index d73b649e..d413ec63 100644 --- a/src/matrix/storage/idb/stores/PendingEventStore.js +++ b/src/matrix/storage/idb/stores/PendingEventStore.js @@ -36,7 +36,13 @@ export default class PendingEventStore { async exists(roomId, queueIndex) { const keyRange = IDBKeyRange.only(encodeKey(roomId, queueIndex)); - const key = await this._eventStore.getKey(keyRange); + let key; + if (this._eventStore.supports("getKey")) { + key = await this._eventStore.getKey(keyRange); + } else { + const value = await this._eventStore.get(keyRange); + key = value && value.key; + } return !!key; } diff --git a/src/matrix/storage/idb/utils.js b/src/matrix/storage/idb/utils.js index e51c5dab..299fa894 100644 --- a/src/matrix/storage/idb/utils.js +++ b/src/matrix/storage/idb/utils.js @@ -39,14 +39,14 @@ export function txnAsPromise(txn) { }); } -export function iterateCursor(cursor, processValue) { +export function iterateCursor(cursorRequest, processValue) { // TODO: does cursor already have a value here?? return new Promise((resolve, reject) => { - cursor.onerror = (event) => { - reject(new Error("Query failed: " + event.target.errorCode)); + cursorRequest.onerror = () => { + reject(new StorageError("Query failed", cursorRequest.error)); }; // collect results - cursor.onsuccess = (event) => { + cursorRequest.onsuccess = (event) => { const cursor = event.target.result; if (!cursor) { resolve(false); diff --git a/src/ui/web/session/room/MessageComposer.js b/src/ui/web/session/room/MessageComposer.js index a4fb3715..79e2fd5e 100644 --- a/src/ui/web/session/room/MessageComposer.js +++ b/src/ui/web/session/room/MessageComposer.js @@ -16,8 +16,9 @@ export default class MessageComposer extends TemplateView { _onKeyDown(event) { if (event.key === "Enter") { - this.viewModel.sendMessage(this._input.value); - this._input.value = ""; + if (this.viewModel.sendMessage(this._input.value)) { + this._input.value = ""; + } } } } diff --git a/yarn.lock b/yarn.lock index c926d2a4..92a7cbc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/node@*": + version "12.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f" + integrity sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w== + "@types/node@^12.0.8": version "12.0.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.8.tgz#551466be11b2adc3f3d47156758f610bd9f6b1d8" @@ -17,6 +22,51 @@ acorn@^6.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +cheerio@^1.0.0-rc.3: + version "1.0.0-rc.3" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" + integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.1" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + colors@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" @@ -27,6 +77,21 @@ commander@^2.19.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -44,6 +109,55 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +dom-serializer@0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" + integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -54,11 +168,26 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -82,6 +211,23 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + http-errors@~1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -106,6 +252,16 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@^2.0.1, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +lodash@^4.15.0: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -121,6 +277,13 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -128,16 +291,80 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== + dependencies: + "@types/node" "*" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +postcss-import@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" + integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw== + dependencies: + postcss "^7.0.1" + postcss-value-parser "^3.2.3" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-value-parser@^3.2.3: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss@^7.0.1, postcss@^7.0.18: + version "7.0.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" + integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q= + dependencies: + pify "^2.3.0" + +readable-stream@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +resolve@^1.1.7: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + rollup@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.15.6.tgz#caf0ed28d2d78e3a59c1398e5a3695fb600a0ef0" @@ -147,6 +374,11 @@ rollup@^1.15.6: "@types/node" "^12.0.8" acorn "^6.1.1" +safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -181,11 +413,37 @@ setprototypeof@1.1.1: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -195,3 +453,8 @@ unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=