Make editor work, add support for syncing to NotePost, use ES6 classes for notes

master
Skylar Ittner 5 år sedan
förälder c32f985ec4
incheckning d43cab8860

@ -10,6 +10,7 @@
<content src="index.html" />
<icon src="logo.png" />
<plugin name="cordova-plugin-whitelist" spec="1" />
<preference name="AutoHideSplashScreen" value="true" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />

@ -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.<anonymous> (/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.<anonymous> (/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.<anonymous> (/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 <https://github.com/npm/npm/issues>
50 verbose exit [ 1, true ]

@ -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;
}
}

@ -29,8 +29,11 @@
<script src="node_modules/framework7/js/framework7.min.js"></script>
<script src="node_modules/marked/marked.min.js"></script>
<script src="node_modules/easymde/dist/easymde.min.js"></script>
<script src="node_modules/shufflejs/dist/shuffle.min.js"></script>
<script src="js/Notes.class.js"></script>
<script src="js/NotePostNotes.class.js"></script>
<script src="js/notes.js"></script>
<script src="js/home.js"></script>
<script src="routes.js"></script>

@ -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();
}
});
}
}

@ -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();
}
}
}

@ -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});
});
}
}

@ -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) {

@ -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);
router.navigate("/home");

@ -4,5 +4,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
var notes = new Notes();
if (localStorage.getItem("serverurl") == null) {
var notes = new Notes();
} else {
var notes = new NotePostNotes(localStorage.getItem("serverurl"), localStorage.getItem("username"), localStorage.getItem("password"));
}

@ -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"
}
}

@ -6,43 +6,44 @@
<div class="navbar">
<div class="navbar-inner">
<div class="left">
<a href="#" class="link icon-only back">
<a href="#" class="link icon-only" onclick="exiteditor()">
<i class="icon icon-back"></i>
</a>
</div>
<div class="title">
{{if notetitle}}
{{#if notetitle}}
{{notetitle}}
{{else}}
New note
{{/if}}</div>
<div class="right">
<a href="#" onclick="saveme()" class="link icon-only">
<i class="fas fa-save"></i>
</a>
</div>
</div>
</div>
<div class="page-content ptr-content">
<textarea id="note_content" data-noteid="{{noteid}}">{{content}}</textarea>
<textarea id="note_content" data-noteid="{{noteid}}" style="z-index: 99999999;">{{content}}</textarea>
<textarea id="orig_content" style="display: none;">{{content}}</textarea>
</div>
<script src="js/editnote.js"></script>
<script>
var easymde = new EasyMDE({
element: $("#note_content")[0],
autoDownloadFontAwesome: false,
autofocus: true,
autofocus: false,
forceSync: true,
status: false,
spellChecker: false,
toolbar: [
{
name: "save",
action: function saveNote(editor) {
$("#noteform").submit();
},
className: "fas fa-save",
title: "Save",
},
"|",
"bold",
"italic",
"heading",
@ -53,6 +54,12 @@
"horizontal-rule"
]
});
$(".editor-toolbar").addClass("elevation-1");
$(".navbar").on("resize", function () {
$(".editor-toolbar").css("top", $(".navbar").css("height"));
});
</script>
</div>

@ -22,9 +22,9 @@
<div class="ptr-arrow"></div>
</div>
<div class="row notecards-row">
<div class="row notecards-row" id="notecards-bin">
{{#each notecards}}
<div class="col-100 tablet-33 desktop-33">
<div class="col-100 tablet-50 desktop-33 notecard-col">
<div class="card notecard" id="notecard-{{id}}" data-id="{{id}}" data-bg="{{color}}" data-fg="{{textcolor}}" style="background-color: #{{color}}; color: #{{textcolor}};">
<div class="menubtn">
<i class="material-icons">more_vert</i>
@ -43,11 +43,10 @@
</a>
</div>
<!-- Reload the home page if it doesn't have valid context -->
{{#unless homeloaded}}
<script>
loadHomePage(true);
window.shuffleInstance = new window.Shuffle(document.getElementById('notecards-bin'), {
itemSelector: '.notecard-col'
});
</script>
{{/unless}}
</div>

@ -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'
},
}
];

@ -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"

Laddar…
Avbryt
Spara