diff --git a/config.xml b/config.xml index 894e0da..3438454 100644 --- a/config.xml +++ b/config.xml @@ -10,6 +10,7 @@ + diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..0bd379e --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,96 @@ +0 info it worked if it ends with ok +1 verbose cli [ '/usr/bin/node', +1 verbose cli '/usr/bin/npm', +1 verbose cli 'install', +1 verbose cli 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +1 verbose cli '--production', +1 verbose cli '--save' ] +2 info using npm@3.5.2 +3 info using node@v8.10.0 +4 silly loadCurrentTree Starting +5 silly install loadCurrentTree +6 silly install readLocalPackageData +7 silly fetchPackageMetaData https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +8 silly fetchOtherPackageData https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +9 silly cache add args [ 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +9 silly cache add null ] +10 verbose cache add spec https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +11 silly cache add parsed spec Result { +11 silly cache add raw: 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +11 silly cache add scope: null, +11 silly cache add name: null, +11 silly cache add rawSpec: 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +11 silly cache add spec: 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +11 silly cache add type: 'remote' } +12 silly mapToRegistry name https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +13 silly mapToRegistry using default registry +14 silly mapToRegistry registry https://registry.npmjs.org/ +15 silly mapToRegistry uri https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +16 verbose addRemoteTarball https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git not in flight; adding +17 verbose addRemoteTarball [ 'https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git', +17 verbose addRemoteTarball null ] +18 info retry fetch attempt 1 at 10:07:53 PM +19 info attempt registry request try #1 at 10:07:53 PM +20 http fetch GET https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +21 verbose request id 9a59c3d4ecd0fe27 +22 http fetch 404 https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +23 error fetch failed https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +24 warn retry will retry, error on last attempt: Error: fetch failed with status code 404 +25 info retry fetch attempt 2 at 10:08:03 PM +26 info attempt registry request try #1 at 10:08:03 PM +27 http fetch GET https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +28 http fetch 404 https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +29 error fetch failed https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +30 warn retry will retry, error on last attempt: Error: fetch failed with status code 404 +31 info retry fetch attempt 3 at 10:09:04 PM +32 info attempt registry request try #1 at 10:09:04 PM +33 http fetch GET https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +34 http fetch 404 https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +35 error fetch failed https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git +36 silly fetchPackageMetaData Error: fetch failed with status code 404 +36 silly fetchPackageMetaData at Request. (/usr/share/npm/node_modules/npm-registry-client/lib/fetch.js:51:14) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +36 silly fetchPackageMetaData at Request.emit (events.js:211:7) +36 silly fetchPackageMetaData at Request.onRequestResponse (/usr/share/npm/node_modules/request/request.js:998:10) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +36 silly fetchPackageMetaData at ClientRequest.emit (events.js:211:7) +36 silly fetchPackageMetaData at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:551:21) +36 silly fetchPackageMetaData at HTTPParser.parserOnHeadersComplete (_http_common.js:115:23) +36 silly fetchPackageMetaData at TLSSocket.socketOnData (_http_client.js:440:20) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +36 silly fetchPackageMetaData error for https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git Error: fetch failed with status code 404 +36 silly fetchPackageMetaData at Request. (/usr/share/npm/node_modules/npm-registry-client/lib/fetch.js:51:14) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +36 silly fetchPackageMetaData at Request.emit (events.js:211:7) +36 silly fetchPackageMetaData at Request.onRequestResponse (/usr/share/npm/node_modules/request/request.js:998:10) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +36 silly fetchPackageMetaData at ClientRequest.emit (events.js:211:7) +36 silly fetchPackageMetaData at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:551:21) +36 silly fetchPackageMetaData at HTTPParser.parserOnHeadersComplete (_http_common.js:115:23) +36 silly fetchPackageMetaData at TLSSocket.socketOnData (_http_client.js:440:20) +36 silly fetchPackageMetaData at emitOne (events.js:116:13) +37 silly rollbackFailedOptional Starting +38 silly rollbackFailedOptional Finishing +39 silly runTopLevelLifecycles Starting +40 silly runTopLevelLifecycles Finishing +41 silly install printInstalled +42 verbose stack Error: fetch failed with status code 404 +42 verbose stack at Request. (/usr/share/npm/node_modules/npm-registry-client/lib/fetch.js:51:14) +42 verbose stack at emitOne (events.js:116:13) +42 verbose stack at Request.emit (events.js:211:7) +42 verbose stack at Request.onRequestResponse (/usr/share/npm/node_modules/request/request.js:998:10) +42 verbose stack at emitOne (events.js:116:13) +42 verbose stack at ClientRequest.emit (events.js:211:7) +42 verbose stack at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:551:21) +42 verbose stack at HTTPParser.parserOnHeadersComplete (_http_common.js:115:23) +42 verbose stack at TLSSocket.socketOnData (_http_client.js:440:20) +42 verbose stack at emitOne (events.js:116:13) +43 verbose cwd /home/skylar/Documents/Projects/Sources/NotePostApp +44 error Linux 4.15.0-43-generic +45 error argv "/usr/bin/node" "/usr/bin/npm" "install" "https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git" "--production" "--save" +46 error node v8.10.0 +47 error npm v3.5.2 +48 error fetch failed with status code 404 +49 error If you need help, you may report this error at: +49 error +50 verbose exit [ 1, true ] diff --git a/www/css/editor.css b/www/css/editor.css index f23ac0e..9c7c931 100644 --- a/www/css/editor.css +++ b/www/css/editor.css @@ -9,5 +9,23 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. */ .CodeMirror { - border-bottom: none; + border: none; + margin-top: 45px; +} + +.editor-toolbar { + position: fixed; + top: 56px; + right: 0; + left: 0; + z-index: 99999; + background-color: white; + border: none; + border-radius: 0px; +} + +@media (min-width: 768px) { + .editor-toolbar { + top: 64px; + } } \ No newline at end of file diff --git a/www/index.html b/www/index.html index 5b3900b..eb9f907 100644 --- a/www/index.html +++ b/www/index.html @@ -29,8 +29,11 @@ + + + diff --git a/www/js/NotePostNotes.class.js b/www/js/NotePostNotes.class.js new file mode 100644 index 0000000..72a842f --- /dev/null +++ b/www/js/NotePostNotes.class.js @@ -0,0 +1,90 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +class NotePostNotes extends Notes { + + constructor(server, username, password) { + super(); + this.server = server; + this.username = username; + this.password = password; + } + + add(note, callback) { + note.norealid = true; + super.add(note, callback); + } + + fix(note) { + super.fix(note); + note.id = note.noteid; + this.set(note); + } + + load(callback) { + var self = this; + $.ajax({ + url: this.server + "/api/getnotes", + dataType: "json", + cache: false, + method: "POST", + beforeSend: function (xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa(self.username + ":" + self.password)); + }, success: function (val) { + if (val.status == "OK") { + self.notes = val.notes; + } + if (typeof callback == 'function') { + callback(); + } + } + }); + } + + saveNote(note, callback) { + var self = this; + var data = { + text: note.content, + color: note.color, + modified: note.modified, + favorite: (note.favorite ? "1" : "0") + }; + // Don't send ID if it's a locally-made note + if (note.norealid != true) { + data.id = note.id; + } + $.ajax({ + url: this.server + "/api/savenote", + dataType: "json", + method: "POST", + data: data, + beforeSend: function (xhr) { + xhr.setRequestHeader("Authorization", "Basic " + btoa(self.username + ":" + self.password)); + } + }).always(function () { + if (typeof callback == 'function') { + callback(); + } + }); + } + + save(callback) { + this.fixAll(); + super.save(); + + var ajaxcalls = []; + for (var i = 0; i < this.notes.length; i++) { + ajaxcalls.push(this.saveNote(this.notes[i])); + } + + $.when(ajaxcalls).always(function () { + if (typeof callback == 'function') { + callback(); + } + }); + } + +} \ No newline at end of file diff --git a/www/js/Notes.class.js b/www/js/Notes.class.js index 2e354e4..8357c8b 100644 --- a/www/js/Notes.class.js +++ b/www/js/Notes.class.js @@ -4,101 +4,107 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +class Notes { -function Notes() { - this.notes = []; - -} - -Notes.prototype.get = function (id) { - for (var i = 0; i < this.notes.length; i++) { - if (this.notes[i].id == id) { - return this.notes[i]; - } + constructor() { + this.notes = []; } -} -Notes.prototype.getAll = function () { - return this.notes; -} - -Notes.prototype.set = function (note) { - for (var i = 0; i < this.notes.length; i++) { - if (this.notes[i].id == note.id) { - this.notes[i] = note; - return; + get(id) { + for (var i = 0; i < this.notes.length; i++) { + if (this.notes[i].id == id) { + return this.notes[i]; + } } + return null; } - this.notes.push(note); -} - -Notes.prototype.add = function (note, callback) { - this.notes.push(note); - if (typeof callback == 'function') { - callback(); - } -} -Notes.prototype.fix = function (note) { - // Set background color - if (typeof note.color !== 'string') { - note.color = "FFF59D"; + getAll() { + return this.notes; } - // Set text color based on background - if (typeof note.textcolor !== 'string') { - var r = parseInt(note.color.substring(0, 2), 16); - var g = parseInt(note.color.substring(2, 4), 16); - var b = parseInt(note.color.substring(4, 6), 16); - var contrast = Math.sqrt( - r * r * 0.241 + - g * g * 0.691 + - b * b * 0.068 - ); + set(note) { + for (var i = 0; i < this.notes.length; i++) { + if (this.notes[i].id == note.id) { + // Refresh HTML rendering + note.html = marked(note.content); - if (contrast > 130) { - note.textcolor = "000000"; - } else { - note.textcolor = "FFFFFF"; + this.notes[i] = note; + return; + } } + this.notes.push(note); } - // Just in case - if (typeof note.content !== 'string') { - note.content = ""; - } - // Set title - if (typeof note.title !== 'string') { - note.title = note.content.split('\n')[0].replace(/[#\-]+/gi, "").trim(); - } - // Render Markdown to HTML - if (typeof note.html !== 'string') { - note.html = marked(note.content); + + add(note, callback) { + this.notes.push(note); + if (typeof callback == 'function') { + callback(); + } } - // Save - this.set(note); -} -Notes.prototype.fixAll = function () { - for (var i = 0; i < this.notes.length; i++) { - this.fix(this.notes[i]); + fix(note) { + // Set background color + if (typeof note.color !== 'string') { + note.color = "FFF59D"; + } + // Set text color based on background + if (typeof note.textcolor !== 'string') { + var r = parseInt(note.color.substring(0, 2), 16); + var g = parseInt(note.color.substring(2, 4), 16); + var b = parseInt(note.color.substring(4, 6), 16); + var contrast = Math.sqrt( + r * r * 0.241 + + g * g * 0.691 + + b * b * 0.068 + ); + if (contrast > 130) { + note.textcolor = "000000"; + } else { + note.textcolor = "FFFFFF"; + } + } + // Just in case + if (typeof note.content !== 'string') { + note.content = ""; + } + // Set title + if (typeof note.title !== 'string') { + note.title = note.content.split('\n')[0].replace(/[#\-]+/gi, "").trim(); + } + if (typeof note.modified !== 'string') { + note.modified = (new Date()).toISOString(); + } + // Render Markdown to HTML + if (typeof note.html !== 'string') { + note.html = marked(note.content); + } + // Save + this.set(note); } -} -Notes.prototype.load = function (callback) { - if (localStorage.getItem("notes") !== null) { - data = JSON.parse(localStorage.getItem("notes")); - if (data.length > 0) { - this.notes = data; + fixAll() { + for (var i = 0; i < this.notes.length; i++) { + this.fix(this.notes[i]); } } - if (typeof callback == 'function') { - callback(); + + load(callback) { + if (localStorage.getItem("notes") !== null) { + var data = JSON.parse(localStorage.getItem("notes")); + if (data.length > 0) { + this.notes = data; + } + } + if (typeof callback == 'function') { + callback(); + } } -} -Notes.prototype.save = function (callback) { - localStorage.setItem("notes", JSON.stringify(this.notes)); - if (typeof callback == 'function') { - callback(); + save(callback) { + localStorage.setItem("notes", JSON.stringify(this.notes)); + if (typeof callback == 'function') { + callback(); + } } } \ No newline at end of file diff --git a/www/js/editnote.js b/www/js/editnote.js new file mode 100644 index 0000000..baadaff --- /dev/null +++ b/www/js/editnote.js @@ -0,0 +1,50 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + +function saveme(callback) { + var noteid = $("#note_content").data("noteid"); + if (noteid == "") { + // Make a very random ID number and check that it won't collide, + // in case the user is good at winning the lottery + do { + noteid = Math.floor(Math.random() * (9999999999 - 1000000000) + 1000000000); + console.log("Generating random note ID: " + noteid); + } while (notes.get(noteid) != null); + + var note = {id: noteid}; + note.content = $("#note_content").val(); + note.modified = (new Date()).toISOString(); + notes.add(note); + $("#note_content").data("noteid", noteid); + } else { + var note = notes.get(noteid); + note.content = $("#note_content").val(); + note.modified = (new Date()).toISOString(); + notes.set(note); + } + notes.fix(note); + notes.save(function () { + app.toast.create({ + text: 'Note saved.', + closeTimeout: 2000 + }).open(); + $("#orig_content").val(note.content); + }); + if (typeof callback == "function") { + callback(); + } +} + +function exiteditor() { + if ($("note_content").val() == "" || $("note_content").val() === $("orig_content").val()) { + router.back({force: true, ignoreCache: true, reload: true}); + } else { + saveme(function () { + router.back({force: true, ignoreCache: true, reload: true}); + }); + } +} \ No newline at end of file diff --git a/www/js/home.js b/www/js/home.js index 7b5cdba..bcd361e 100644 --- a/www/js/home.js +++ b/www/js/home.js @@ -5,27 +5,8 @@ */ -function loadHomePage(reload) { - if (typeof reload == 'undefined') { - reload = false; - } - notes.load(function () { - notes.fixAll(); - var notecards = notes.getAll(); - - router.navigate("/home", { - context: { - notecards: notecards, - homeloaded: true - }, - reloadCurrent: true - }); - }); -} - - $(".view-main").on("ptr:refresh", ".ptr-content", function () { - loadHomePage(true); + router.navigate("/home"); }); function editNote(id) { diff --git a/www/js/main.js b/www/js/main.js index cadefe5..22036e9 100644 --- a/www/js/main.js +++ b/www/js/main.js @@ -8,6 +8,8 @@ var app = new Framework7({ root: "#app", name: "NotePost", id: "com.netsyms.NotePostApp", + init: true, + initOnDeviceReady: false, routes: routes }); @@ -17,8 +19,6 @@ var mainView = app.views.create('.view-main', { var router = mainView.router; -var notes = new Notes(); - /** * Thanks to https://stackoverflow.com/a/13542669 * @param {type} color @@ -31,11 +31,7 @@ function shadeColor2(color, percent) { } function restartApplication() { - navigator.splashscreen.show(); - // We're doing the timeout so we don't run afoul of server-side rate limiting - setTimeout(function () { - window.location = "index.html"; - }, 3000); + window.location = "index.html"; } router.on("pageInit", function (pagedata) { @@ -58,4 +54,4 @@ router.on("pageInit", function (pagedata) { // Run platform-specific setup code for Cordova or NW.js initPlatform(); -loadHomePage(false); \ No newline at end of file +router.navigate("/home"); \ No newline at end of file diff --git a/www/js/notes.js b/www/js/notes.js index 0f3b198..4b334d4 100644 --- a/www/js/notes.js +++ b/www/js/notes.js @@ -4,5 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -var notes = new Notes(); \ No newline at end of file +if (localStorage.getItem("serverurl") == null) { + var notes = new Notes(); +} else { + var notes = new NotePostNotes(localStorage.getItem("serverurl"), localStorage.getItem("username"), localStorage.getItem("password")); +} \ No newline at end of file diff --git a/www/package.json b/www/package.json index 768d010..bbc590f 100644 --- a/www/package.json +++ b/www/package.json @@ -10,6 +10,7 @@ "easymde": "^2.4.2", "framework7": "^3.6.5", "jquery": "^3.3.1", - "marked": "^0.6.0" + "marked": "^0.6.0", + "shufflejs": "^5.2.1" } } diff --git a/www/pages/editnote.html b/www/pages/editnote.html index b4f6efa..5730c89 100644 --- a/www/pages/editnote.html +++ b/www/pages/editnote.html @@ -6,43 +6,44 @@
- + +
+ + \ No newline at end of file diff --git a/www/pages/home.html b/www/pages/home.html index 0698527..e87468b 100644 --- a/www/pages/home.html +++ b/www/pages/home.html @@ -22,9 +22,9 @@
-
+
{{#each notecards}} -
+
- - {{#unless homeloaded}} - {{/unless}}
\ No newline at end of file diff --git a/www/routes.js b/www/routes.js index f238c45..ae72772 100644 --- a/www/routes.js +++ b/www/routes.js @@ -8,8 +8,25 @@ var routes = [ { path: '/home', - templateUrl: './pages/home.html', - name: 'home' + name: 'home', + async: function (routeTo, routeFrom, resolve, reject) { + notes.load(function () { + console.log("Loading"); + notes.fixAll(); + var notecards = notes.getAll(); + if (routeFrom.name == "home") { + app.ptr.done(); + } + resolve({ + templateUrl: './pages/home.html', + reloadCurrent: (routeFrom.name == "home") + }, { + context: { + notecards: notecards + } + }); + }); + } }, { path: '/credits', @@ -20,5 +37,5 @@ var routes = [ path: '/editnote', templateUrl: './pages/editnote.html', name: 'editnote' - }, + } ]; \ No newline at end of file diff --git a/www/yarn.lock b/www/yarn.lock index 12de718..e2873e3 100644 --- a/www/yarn.lock +++ b/www/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.6.3.tgz#61c122c420d7a91613f393d6a06e5a4c6ae6abf3" integrity sha512-s5PLdI9NYgjBvfrv6rhirPHlAHWx+Sfo/IjsAeiXYfmemC/GSjwsyz1wLnGPazbLPXWfk62ks980o9AmsxYUEQ== +array-parallel@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/array-parallel/-/array-parallel-0.1.3.tgz#8f785308926ed5aa478c47e64d1b334b6c0c947d" + integrity sha1-j3hTCJJu1apHjEfmTRszS2wMlH0= + codemirror-spell-checker@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e" @@ -60,11 +65,26 @@ marked@^0.6.0: resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.0.tgz#a18d01cfdcf8d15c3c455b71c8329e5e0f01faa1" integrity sha512-HduzIW2xApSXKXJSpCipSxKyvMbwRRa/TwMbepmlZziKdH8548WSoDP4SxzulEKjlo8BE39l+2fwJZuRKOln6g== +matches-selector@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/matches-selector/-/matches-selector-1.2.0.tgz#d1814e7e8f43e69d22ac33c9af727dc884ecf12a" + integrity sha512-c4vLwYWyl+Ji+U43eU/G5FwxWd4ZH0ePUsFs5y0uwD9HUEFBXUQ1zUUan+78IpRD+y4pUfG0nAzNM292K7ItvA== + path-to-regexp@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704" integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w== +shufflejs@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/shufflejs/-/shufflejs-5.2.1.tgz#ebe68361aae24f28d597a2c71eaf58f340ee9f1a" + integrity sha512-qUu/1i4QHMUy/RQMH/FlNoXdliWTa5bWt55A/DeRRq7gD4kCJCMTCQK2k+r0buSREwTaZGLLu7c6E5dMueV0VA== + dependencies: + array-parallel "^0.1.3" + matches-selector "^1.0.0" + throttleit "^1.0.0" + tiny-emitter "^2.0.1" + ssr-window@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ssr-window/-/ssr-window-1.0.1.tgz#30752a6a4666e7767f0b7e6aa6fc2fdbd0d9b369" @@ -75,6 +95,16 @@ template7@^1.4.0: resolved "https://registry.yarnpkg.com/template7/-/template7-1.4.0.tgz#d400af49ea56fc08cc835a20e6167a26b288fb1b" integrity sha512-NMJWbKIoowHixUYIHq+DLvcBM47t/oZ/xfvBbYuMusjjS6BUjC02+gLWctntJuTTiEqILfefBNCXbfp/EMt/zQ== +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= + +tiny-emitter@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c" + integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow== + typo-js@*: version "1.0.3" resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.0.3.tgz#54d8ebc7949f1a7810908b6002c6841526c99d5a"