Compare commits
112 Commits
9d6fcbc48f
...
6a69bbcaf7
Author | SHA1 | Date | |
---|---|---|---|
6a69bbcaf7 | |||
577f041928 | |||
285249254a | |||
9f9d3c1480 | |||
9a16ed0480 | |||
ce740b61ec | |||
499f0764da | |||
bac8786ab4 | |||
6529b1d937 | |||
2d4850520d | |||
b1d0a0f095 | |||
ae5360386a | |||
85bca37a8c | |||
a6dd34cf81 | |||
![]() |
9eaf71ec3d | ||
6eb741760f | |||
3550f1558b | |||
![]() |
b62927c28d | ||
![]() |
0f06d8fcd7 | ||
![]() |
613041d5cb | ||
783938821c | |||
1f6261dba0 | |||
4aa5856fbc | |||
![]() |
57901853a9 | ||
![]() |
3eb0a99813 | ||
74232689fb | |||
d003166e33 | |||
0097de5122 | |||
5a4faca86f | |||
92220fc11c | |||
633dbc90f0 | |||
5f0c8c1d2f | |||
![]() |
1fe9f22109 | ||
b7e3737a70 | |||
![]() |
4f2316481e | ||
a49b0ee6a5 | |||
![]() |
6318b358d2 | ||
![]() |
35bdcd9684 | ||
c1db18b323 | |||
c8aee0c979 | |||
d8091ecafd | |||
a56ab9cadd | |||
a4da6243f5 | |||
![]() |
35b5748af9 | ||
70befa7c4d | |||
![]() |
3770d747ba | ||
2f07441fb7 | |||
2b73aaabb2 | |||
![]() |
7eed075963 | ||
![]() |
d66be879cd | ||
![]() |
373d644134 | ||
0c8b9da3f6 | |||
d1a5a0b4cf | |||
8ddf59666b | |||
10f349b948 | |||
f4ab8813f3 | |||
45315d7c47 | |||
a30bbe961c | |||
b029846985 | |||
![]() |
9d3d1b707e | ||
![]() |
6c9cb12480 | ||
9dab5e2dbc | |||
![]() |
95a0ff3913 | ||
![]() |
83d1d4dea8 | ||
![]() |
9375316956 | ||
a4dbafe3ef | |||
79475fe48d | |||
e15cf25745 | |||
3478901450 | |||
d48a3bf5ed | |||
ab358abe98 | |||
5280c47477 | |||
8c0d3dc669 | |||
d45ab87a8b | |||
156ec36d1e | |||
e93526c639 | |||
cad0230c47 | |||
82f8e4bbde | |||
5c26a11023 | |||
4fe1bbd0e5 | |||
eb89e2c3bf | |||
37e7d757c3 | |||
![]() |
d61def25b9 | ||
e108be1fb8 | |||
773408dc12 | |||
![]() |
d71c50ef22 | ||
![]() |
c3073101b1 | ||
![]() |
d77c8d69e3 | ||
ae4203ccf9 | |||
d9b249c828 | |||
aba5a9ce8e | |||
8341ed24d0 | |||
d27216c8a8 | |||
5d28bc36e1 | |||
4603f7a7c1 | |||
0a3f6ff240 | |||
0fcf2f7b97 | |||
9bf9f5faec | |||
56f4a3f940 | |||
c7a835ad1c | |||
2f90b14625 | |||
24642ca1a8 | |||
![]() |
1523cc93c2 | ||
![]() |
bee7427176 | ||
![]() |
e921e6a9e6 | ||
e471a76377 | |||
091a1c87a2 | |||
3f58fa194f | |||
7977b21a15 | |||
1dbba098dd | |||
9ce2dcf199 | |||
![]() |
47d47b8b22 |
5
.gitignore
vendored
@ -18,4 +18,7 @@ latex-files/*.run.xml
|
||||
latex-files/*.toc
|
||||
|
||||
# config
|
||||
mongodb.config.js
|
||||
mongodb.config.js
|
||||
|
||||
# exclude Mac-File .DS_Store
|
||||
*.DS_Store
|
BIN
gesamtdokumentation_ws1819/prsta_bericht/Gruppenbericht.pdf
Normal file
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 143 KiB |
After Width: | Height: | Size: 3.8 MiB |
After Width: | Height: | Size: 3.6 MiB |
After Width: | Height: | Size: 3.3 MiB |
After Width: | Height: | Size: 3.4 MiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Icons_CD.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Layout.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Links_MU.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Logo1_CD.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Logo2_CD.png
Normal file
After Width: | Height: | Size: 34 KiB |
4652
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat1.pdf
Normal file
3777
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat2.pdf
Normal file
11957
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat3.pdf
Normal file
11981
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat4.pdf
Normal file
15727
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat5.pdf
Normal file
112333
gesamtdokumentation_ws1819/prsta_bericht/grafiken/PDF_Plakat6.pdf
Normal file
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Profil.jpg
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/Profil_MU.png
Normal file
After Width: | Height: | Size: 146 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/ajax.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
gesamtdokumentation_ws1819/prsta_bericht/grafiken/system.png
Normal file
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,307 @@
|
||||
@online{spa:1,
|
||||
author = {t3n},
|
||||
title = {Was ist eigentlich eine Single-Page-Webanwendung?},
|
||||
month = {04},
|
||||
year = {2018},
|
||||
url = {https://t3n.de/news/single-page-webanwendung-1023623/},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{spa:2,
|
||||
author = {Nebil Aboobacker},
|
||||
title = {Was ist eine Single Page Application (SPA)?},
|
||||
month = {05},
|
||||
year = {2018},
|
||||
url = {https://www.yuhiro.de/was-ist-eine-single-page-application-spa/},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{vue,
|
||||
author = {Marc Teufel},
|
||||
title = {Vue.js Tutorial: So entwickelt man Komponenten mit Vue.js},
|
||||
month = {07},
|
||||
year = {2018},
|
||||
url = {https://entwickler.de/online/javascript/einfuehrung-vuejs-vue-579851816.html},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{vue:warum,
|
||||
author = {Verena Sappelt},
|
||||
title = {Vue.js – Vorteile: Das Beste aus zwei Welten},
|
||||
month = {01},
|
||||
year = {2019},
|
||||
url = {https://www.ppw.de/blog/vue-js-vorteile-das-beste-aus-zwei-welten/},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{vue:router,
|
||||
author = {Said Hayani},
|
||||
title = {How to use routing in Vue.js to create a better user experience},
|
||||
month = {06},
|
||||
year = {2018},
|
||||
url = {https://medium.freecodecamp.org/how-to-use-routing-in-vue-js-to-create-a-better-user-experience-98d225bbcdd9},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{vue:router2,
|
||||
title = {Vue Router - Getting Started},
|
||||
month = {01},
|
||||
year = {2014},
|
||||
url = {https://router.vuejs.org/guide/#javascript},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{vue:router3,
|
||||
author = {Raymond Camden},
|
||||
title = {Working with Routes in Vue.js},
|
||||
month = {012},
|
||||
year = {2017},
|
||||
url = {https://www.raymondcamden.com/2017/11/12/working-with-routes-in-vue},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{api2,
|
||||
author = {Björn Behrendt},
|
||||
title = {Application-Programming-Interface (API)},
|
||||
month = {06},
|
||||
year = {2018},
|
||||
url = {https://www.gruenderszene.de/lexikon/begriffe/application-programming-interface-api?interstitial},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{scrib,
|
||||
title = {Scribble},
|
||||
month = {08},
|
||||
year = {2017},
|
||||
url = {https://de.wikipedia.org/wiki/Scribble},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{md,
|
||||
title = {Material Design},
|
||||
month = {01},
|
||||
year = {2019},
|
||||
url = {https://de.wikipedia.org/wiki/Material_Design},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{md2,
|
||||
author = {Google},
|
||||
title = {Homepage Material Design},
|
||||
url = {https://material.io},
|
||||
note = {(o.D.), Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{bootstrap,
|
||||
author = {Federico Zivolo and Bootstrap contributors},
|
||||
title = {Bootstrap Material Design},
|
||||
month = {08},
|
||||
year = {2018},
|
||||
url = {https://fezvrasta.github.io/bootstrap-material-design/},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{less,
|
||||
author = {Alexis Sellier },
|
||||
title = {LESS - Die dynamische Stylesheet Sprache},
|
||||
month = {01},
|
||||
year = {2013},
|
||||
url = {http://www.lesscss.de},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{ajax1,
|
||||
author = {Jesse James Garret},
|
||||
title = {Ajax: A New Approach to Web Applications},
|
||||
month = {07},
|
||||
year = {2008},
|
||||
url = {https://web.archive.org/web/20080702075113/http://www.adaptivepath.com/ideas/essays/archives/000385.php},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{ajax2,
|
||||
author = {Matthias Hertel},
|
||||
title = {The AJAX Engine},
|
||||
month = {02},
|
||||
year = {2007},
|
||||
url = {http://www.mathertel.de/AJAXEngine/#view=Home},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
|
||||
@book{ajax3,
|
||||
author = {David Sawyer McFarland},
|
||||
title = {JavaScript \& jQuery - the missing manual},
|
||||
year = {2012},
|
||||
publisher = {O'Reilly Media, inc.},
|
||||
address = {1005 Gravenstein Highway North, Sebastopol, CA 95472},
|
||||
}
|
||||
|
||||
@online{api,
|
||||
title = {Programmierschnittstelle},
|
||||
month = {02},
|
||||
year = {2019},
|
||||
url = {https://de.wikipedia.org/wiki/Programmierschnittstelle},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{rest,
|
||||
author = {Thomas Bayer},
|
||||
title = {REST Web Services},
|
||||
month = {11},
|
||||
year = {2002},
|
||||
url = {https://www.oio.de/public/xml/rest-webservices.htm},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{mongo,
|
||||
title = {What is MongoDB?},
|
||||
year = {2019},
|
||||
url = {https://www.mongodb.com/what-is-mongodb},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
|
||||
@online{mongoose,
|
||||
author = {Nick Karnik},
|
||||
title = {Introduction to Mongoose for MongoDB},
|
||||
month = {02},
|
||||
year = {2018},
|
||||
url = {https://medium.freecodecamp.org/introduction-to-mongoose-for-mongodb-d2a7aa593c57},
|
||||
note = {Zuletzt besucht am 26.02.2019}
|
||||
}
|
||||
|
||||
@online{Bear,
|
||||
author = {Sevilleja, Chris},
|
||||
month = {02},
|
||||
year = {2019},
|
||||
title = {Build a RESTful API Using Node and Express 4},
|
||||
url = {https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4},
|
||||
note = {Zuletzt besucht am 01.03.219}
|
||||
}
|
||||
|
||||
|
||||
@online{gitefi,
|
||||
author = {Matthias Hopf},
|
||||
month = {02},
|
||||
year = {2019},
|
||||
title = {Git efi},
|
||||
url = {https://git.efi.th-nuernberg.de/gitea/hopfma/om/wiki/_pages},
|
||||
note = {Zuletzt besucht am 25.02.2019}
|
||||
}
|
||||
|
||||
|
||||
@online{Powtoon,
|
||||
title = {Powtoon - Brings Awesomeness to your presentations},
|
||||
month = {02},
|
||||
year = {2019},
|
||||
url = {https://www.powtoon.com/my-powtoons/#/},
|
||||
note = {Zuletzt besucht am 01.03.219}
|
||||
}
|
||||
|
||||
|
||||
@online{Risingstack,
|
||||
author = {Gergely Nemeth},
|
||||
year = {2017},
|
||||
title = {10 Best Practices for Writing Node.js REST APIs | @RisingStack},
|
||||
url = {https://blog.risingstack.com/10-best-practices-for-writing-node-js-rest-apis/},
|
||||
note = {Zuletzt besucht am 01.03.2019}
|
||||
}
|
||||
|
||||
@online{trello:uri,
|
||||
author = {ATLASSIAN},
|
||||
title = {Trello},
|
||||
year = {2019},
|
||||
url = {https://trello.com/home},
|
||||
note = {(Zuletzt besucht am 25.02.2019)}
|
||||
}
|
||||
@online{trello:price,
|
||||
author = {ATLASSIAN},
|
||||
title = {Trello-Preisliste},
|
||||
year = {2019},
|
||||
url = {https://trello.com/pricing},
|
||||
note = {(Zuletzt besucht am 25.02.2019)}
|
||||
}
|
||||
|
||||
@online{bitrix:uri,
|
||||
author = {Bitrix, Inc.},
|
||||
title = {Führende Kostenlose Plattform Für Kommunikation Und Zusammenarbeit Mit Aufgaben, Projekten, CRM, Dokumenten, Chat u.v.a.m.},
|
||||
year = {2019},
|
||||
url = {https://www.bitrix24.de/},
|
||||
note = {(Zuletzt besucht am 25.02.2019)}
|
||||
}
|
||||
@online{bitrix:feature,
|
||||
author = {Bitrix, Inc.},
|
||||
title = {Bitrix24: Führende kostenlose Software zum Projektmanagement},
|
||||
year = {2019},
|
||||
url = {https://www.bitrix24.de/tools/tasks_and_projects/},
|
||||
note = {(Zuletzt besucht am 25.02.2019)}
|
||||
}
|
||||
|
||||
@online{sw:staleWhileRevalidate,
|
||||
author = {Jake Archibald},
|
||||
title = {The offline cookbook - JakeArchibald.com},
|
||||
month = {12},
|
||||
year = {2014},
|
||||
url = {https://jakearchibald.com/2014/offline-cookbook/#stale-while-revalidate},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{sw:cacheBackToNetwork,
|
||||
author = {Jake Archibald},
|
||||
title = {The offline cookbook - JakeArchibald.com},
|
||||
month = {12},
|
||||
year = {2014},
|
||||
url = {https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{sw:networkBackToCache,
|
||||
author = {Jake Archibald},
|
||||
title = {The offline cookbook - JakeArchibald.com},
|
||||
month = {12},
|
||||
year = {2014},
|
||||
url = {https://jakearchibald.com/2014/offline-cookbook/#network-falling-back-to-cache},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{sw:cacheThenNetwork,
|
||||
author = {Jake Archibald},
|
||||
title = {The offline cookbook - JakeArchibald.com},
|
||||
month = {12},
|
||||
year = {2014},
|
||||
url = {https://jakearchibald.com/2014/offline-cookbook/#cache-then-network},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{api:doku,
|
||||
author = {Erik Römmelt},
|
||||
title = {Build, Collaborate \& Integrate APIs | SwaggerHub - OHM News API},
|
||||
month = {02},
|
||||
year = {2019},
|
||||
url = {https://app.swaggerhub.com/apis-docs/roemmelter/om_api/1.0},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{dev:homescreen,
|
||||
author = {Pete LePage},
|
||||
title = {Your First Progressive Web App | Web Fundamentals | Google Developers},
|
||||
month = {01},
|
||||
year = {2019},
|
||||
url = {https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/#support_native_integration},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
@online{dev:codeSource,
|
||||
author = {Pete LePage},
|
||||
title = {Your First Progressive Web App | Web Fundamentals | Google Developers},
|
||||
month = {01},
|
||||
year = {2019},
|
||||
url = {https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/},
|
||||
note = {(Zuletzt besucht am 26.02.2019)}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,832 @@
|
||||
% !TeX spellcheck = de_DE
|
||||
% ---
|
||||
% Preamble
|
||||
% ---
|
||||
\documentclass[12pt]{report}
|
||||
\usepackage{defaultPreamble}
|
||||
\bibfilename{Gruppenbericht.bib}
|
||||
%
|
||||
% ---
|
||||
% Document Body
|
||||
% ---
|
||||
\begin{document}
|
||||
\pagenumbering{arabic}
|
||||
%
|
||||
% Deckblatt
|
||||
\setcounter{page}{0} % setze seitenzähler auf 0 -> alle Seitenzahlen <1 werden nicht angezeigt
|
||||
{\centering
|
||||
\clear % Select ClearSans for the title page
|
||||
\vspace*{2\baselineskip}
|
||||
%
|
||||
{\large Technische Hochschule}\\
|
||||
\vspace{0.3ex}
|
||||
{\large Georg-Simon Ohm Nürnberg}\\
|
||||
\vspace{0.3ex}
|
||||
{\large Fakultät Elektrotechnik Feinwerktechnik Informationstechnik}\\
|
||||
\vspace{2.5ex}
|
||||
%
|
||||
{\large Projekt OHM News}\\
|
||||
\vspace{3.5ex}
|
||||
%
|
||||
{\Large\b{Projektstudienarbeit}}\\
|
||||
\vspace{0.3ex}
|
||||
{\Large\b{B-ME 5}}\\
|
||||
\vspace{4.5ex}
|
||||
{\Large\b{OHM News - See only what matters}}\\
|
||||
\vspace{3.5ex}
|
||||
%
|
||||
{\large Wintersemester 2018/2019}\\
|
||||
\vspace{10\baselineskip}
|
||||
%
|
||||
\begin{table}[h]
|
||||
\centering \large
|
||||
\begin{tabular}{rl}
|
||||
\rule{0pt}{14pt}\b{Senta Mandutz} & \b{Edwina Barbalan} \\
|
||||
Matrikel-Nr.: 3022812 & Matrikel-Nr.: 3064088 \\
|
||||
\rule{0pt}{14pt}\b{Vivianne Pham} & \b{Xenia Gr\"unzinger} \\
|
||||
Matrikel-Nr.: 2928261 & Matrikel-Nr.: 3046080 \\
|
||||
\rule{0pt}{14pt}\b{Erik R\"ommelt} & \\
|
||||
Matrikel-Nr.: 2843345 & \\
|
||||
\end{tabular}
|
||||
|
||||
\end{table}
|
||||
|
||||
} % Need 1 empty line above for centering
|
||||
%
|
||||
\newpage % Seitenumbruch nach Titelblatt
|
||||
\paragraph{\Large Projekt-Roadmap}$~~$\\
|
||||
%
|
||||
\begin{table}[h]
|
||||
\centering%\small
|
||||
\begin{tabularx}{\textwidth}{|X|X|X|}
|
||||
\hline
|
||||
\rule{0pt}{14pt}\b{Tätigkeit} & \b{Dokument} & \b{Beteiligung} \\
|
||||
\hline
|
||||
\rule{0pt}{14pt}Konzeption & Projektidee & Alle \\
|
||||
Organisation und Pflege & Trello & Erik \\
|
||||
Organisation und Pflege & Bitrix24 & Erik \\
|
||||
Protokollierung der Treffen & Handschriftlich & Erik, Vivianne \\
|
||||
Transkription der Protokolle & LaTeX Protokolle & Erik \\
|
||||
Organisation und Pflege & Wiki & Vivianne \\
|
||||
Erstformulierung & Pflichtenheft & Alle \\
|
||||
Erste Entwürfe des App UI & Scribbles, Skizzen & Alle \\
|
||||
Namensüberlegungen & Notizen zur Namensfindung & Alle \\
|
||||
Corporate Design & Styleguide & Xenia \\
|
||||
Entwicklung & Erstellung der Mockups & Xenia, Edwina \\
|
||||
Entwicklung & Frontenddesign mit Bootstrap & Xenia, Edwina \\
|
||||
Entwicklung & Single-Page mit Vue.js & Xenia, Edwina \\
|
||||
Entwicklung & ServiceWorker & Erik \\
|
||||
Entwicklung & Manifest mit Json & Erik \\
|
||||
Entwicklung & Meta-Tags mit HTML & Erik \\
|
||||
Entwicklung & Erstellung der API-Schnittstelle & Senta, Edwina, Vivianne, \mbox{Xenia} \\
|
||||
Dokumentation RESTful API & Digital mit Swagger.io & Erik \\
|
||||
Entwicklung & Server mit Node.js/Express.js & Vivianne \\
|
||||
Entwicklung & Datenbank mit MongoDB & Senta \\
|
||||
Entwicklung & DB-Anbindung mit Mongoose & Senta \\
|
||||
Designentwürfe Plakat & Plakatgestaltung & Vivianne \\
|
||||
\rule{0pt}{14pt}Design und Ausformulierung & Projektpräsentation & Edwina, Vivianne \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\caption{Projekt-Roadmap Tabelle}
|
||||
\end{table}
|
||||
%
|
||||
% Inhaltsverzeichnis
|
||||
\newpage
|
||||
\tableofcontents
|
||||
%
|
||||
% Bericht
|
||||
\newpage % Seitenumbruch nach Titelblatt
|
||||
\section*{1. Einleitung}
|
||||
\phantomsection\addcontentsline{toc}{section}{1. Einleitung}
|
||||
In der heutigten Zeit werden die meisten Menschen tagtäglich mit einer Vielzahl an Reizen und Informationen überflutet. Dabei ist es nicht immer einfach den Blick auf das Wesentliche zu halten. Häufig werden wir durch Werbung, irrelevante Mails, Social Media Beiträge und weiteres schnell abgelenkt. So geht es auch vielen Studierenden und Angehörigen der Technischen Hochschule Nürnberg.\\
|
||||
Für uns war das Anlass genug. Es sollte doch eine Möglichkeit zur qualitativen Verbesserung der Informationsflut im Studienalltag geben. Auf der einen Seite müssen die Hochschulangehörigen entlastet werden, damit die Konzentration für die relevanten Themen gesteigert werden kann und auf der anderen Seite sollte genügend Freiraum für die individuellen Interessen bestehen.\\
|
||||
Im Folgenden wird die Entwicklung einer Idee zur Lösung dieser Problematik, über deren Ausarbeitung in Form eines Konzeptes bis hin zur praktischen Entwicklung eines lauffähigen Prototypen detailliert beschrieben.
|
||||
%
|
||||
\section*{2. Vorwort zur Projektidee}
|
||||
\phantomsection\addcontentsline{toc}{section}{2. Vorwort zur Projektidee}
|
||||
Die erste Konzeptversion zu der Projektidee von dem Projekt ''Ohm Management App'', dass im Verlauf der ersten Projektphase in ''OHM-News - See only what matters'' umbenannt wurde, wurde von Erik Römmelt erstellt. Nach gemeinsamer Überarbeitung durch Prof.Dr. Matthias Hopf, dem zukünftig betreuenden Professor und Erik Römmelt wurde die zu Projektbeginn gegebene Version des Projektkonzeptes ausformuliert.
|
||||
%
|
||||
\section*{3. Projektidee}
|
||||
\phantomsection\addcontentsline{toc}{section}{3. Projektidee}
|
||||
Die Projektidee basiert darauf, dass eine plattformunabhängige App für Studierende an der TH Nürnberg entwickelt werden soll, die Kurznachrichten filtert und in einem Nachrichtenfeed anzeigt. Das Filtern funktioniert durch Tags. Es können beim Nachrichten erstellen mehrere, jedoch mindestens eine eingegeben werden. Diese werden bei einer Überschneidung bei der Suche durch eine logische UND-Verknüpfung eingeschränkt. Angezeigt werden die Nachrichten abhängig von ihrer Priorität und Aktualität. \\
|
||||
Dazu können in einer Dateiablage von Professoren und Befugten wichtige Links oder andere Dateien gesammelt werden oder als Referenz darauf verwiesen werden. Damit es den Status ''Befugte'' gibt, muss es zudem eine Rollenverteilung geben, wem welche Rechte zu stehen oder beispielsweise wer nur Nachrichten empfangen kann.
|
||||
Zudem ist eine Speicherung einzelner Nachrichten aus dem Feed möglich, welche im Nachhinein in den Bookmarks oder auch Lesezeichen einsehbar sind.\\
|
||||
Des Weiteren können Push-Benachrichtigungen angezeigt werden, sodass das Risiko, wichtige Nachrichten zu übersehen, minimiert wird.
|
||||
Zuletzt gibt es noch ein Nutzerprofil. Hier können Daten zur Person eingetragen und angezeigt werden wie zum Beispiel das Profilbild, deren Status an der technischen Hochschule oder die Matrikelnummer.
|
||||
Für den Optimalfall einer Übernahme der App von der Hochschule soll modulorientiert und wartungsaufwandsarm gearbeitet werden, um die spätere Verwaltung zu erleichtern. Auch wird Wert gelegt auf eine nutzerfreundliche und möglichst intuitive Bedienoberfläche.
|
||||
%
|
||||
\subsection*{3.1. Technische Umsetzung}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{3.1. Technische Umsetzung}
|
||||
Zur Umsetzung des Projektes fiel die Zielsetzung auf die Entwicklung einer progressiven Web-App. Aufgrund ihrer Plattformunabhängigkeit und Kompatibilität mit den TH-Servern (VPN und Eduroam) und laut Erfahrungen von Professor Dr. Hopf stellt dies eine gute Lösung und sichere Wahl dar. Ebenfalls, was die Datenschutzvorkehrungen der Hochschule betrifft. \\
|
||||
Es werden die Codesprachen HTML, CSS und JavaScript verwendet und als Frameworks Vue.js, Bootstrap und node.js. \\
|
||||
Als Datenbank dient MongoDB und das zugehörige Framework mongoose.
|
||||
%
|
||||
\section*{4. Projektorganisation}
|
||||
\phantomsection\addcontentsline{toc}{section}{4. Projektorganisation}
|
||||
Wöchentlich fand ein Treffen, zum Austausch und zur Besprechung zurückliegender und anstehender Aufgaben, statt. An diesem Treffen nahmen in der Regel alle Mitglieder dieser Projektgruppe und der Projektbetreuer Prof.Dr. Matthias Hopf teil. Konnten Teammitglieder, gleich welcher Gründe, an einem Treffen nicht teilnehmen, so haben alle sich unverzüglich über Absprachen und den neu anstehenden Aufgaben selbstständig erkundigt.
|
||||
%
|
||||
\subsection*{4.1. Trello}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{4.1. Trello}
|
||||
Zu Beginn des Projekts wurde entschieden, dass zur Verbesserung des Arbeitsablaufs ein Organisationstool hilfreich wäre. So fiel ist Trello in Gespräch gekommen.\\
|
||||
Trello ist ein graphisch sehr gut aufbereitetes Projektmanagement-Tool in Form von Kanban-Boards. In der kostenfreien Version, ist es möglich ''unbegrenzt [viele] Boards, Listen, Karten, Mitglieder, Checklisten und Anhänge'' hinzuzufügen und zu nutzen\cite{trello:price}. Zur typografischen Gestaltung der Karten, um zum Beispiel eine Liste einzufügen ist die Nutzung von einigen Markdown-Markup Elementen möglich.\\
|
||||
Dem Projekt zugute kommend ist die sehr einfache Bedienbarkeit, Plattform unabhängige Verfügbarkeit, sowie die gute Übersichtlichkeit der Boards. Nachteilig ist, dass es nur sehr eingeschränkt die Zeitkomponente abbilden kann. Dies ist nur über die sogenannten ''Plugins'' möglich, wobei in der kostenfreien Version nur ein Plugin je Board zugleich genutzt werden kann. So kann einem Board entweder die Funktion ''Gantt-Diagramme nutzen'' oder ''Storypoints den Karten hinzufügen'' verwendet werden.\\
|
||||
Diese Einschränkung führte zur der Entscheidung gegen die Nutzung von Trello im Team.
|
||||
%
|
||||
\subsection*{4.2. Bitrix24}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{4.2. Bitrix24}
|
||||
Nach dem Ausschluss von Trello begann die Umsicht nach einem anderen Tool, dass kostenfrei mit einer Gruppe von fünf Personen genutzt werden kann. Und es sollte die Funktionen Gantt-Diagramme erstellen, Aufgaben an Mitglieder verteilen und den Gewichtungs-Punkte oder ''Storypoints'' an Aufgaben zuweisen erfüllen.\\
|
||||
Bitrix24 hat diese Anforderungen erfüllt, war jedoch bereits auf den ersten Blick deutlich unübersichtlicher und komplexer in der Handhabung. Da es sich bei Bitrix24 in erster Linie um ein umfangreiches CRM-System handelt, mit vielen weiteren Funktionen wie ''Aufgabenverwaltung für Gruppen'', ''Projektplanung und -management'' und ''Team-Chat''\cite{bitrix:feature}.\\
|
||||
Auch nach der Deaktivierung und Ausblendung sämtlicher Funktionen, die die Nutzung von Bitrix24 komplizierter machten, blieb die Benutzeroberfläche noch unübersichtlich. Was die Umsetzung der Aufgaben als Kanban-Karten mit Gewichtungs-Punkten und der zeitlichen Darstellung der Aufgaben in einem Gantt-Diagramm betrifft, so war dies sehr angenehm und vollends zufriedenstellend möglich.\\
|
||||
So wurden zahlreiche organisatorische Fristen, sowie Aufgaben organisatorischer und entwicklungs-technischer Natur in Bitrix24 erfasst und anschließend in einem wöchentlichen Treffen vorgestellt. Im Weiteren wurde die Nutzung und Pflege des Tools an alle Mitglieder übertragen.\\
|
||||
Es stellte sich am Ende des ersten Projektabschnittes heraus, dass das Tool Bitrix24 aufgrund der komplexen und unübersichtliche Benutzeroberfläche kaum genutzt wurde.
|
||||
%
|
||||
\section*{5. Entwicklerblog}
|
||||
\phantomsection\addcontentsline{toc}{section}{5. Entwicklerblog}
|
||||
Die Wiki Blogeinträge in dem hochschulinternen github Repository dienen dazu, die Projektfortschritte transparent zu gestalten und eine kurze prägnante Zusammenfassung für Professoren und Studierende zu gewährleisten. Einzusehen sind die Beiträge auf der git efi Seite \cite{gitefi}.
|
||||
%
|
||||
\subsection*{5.1. Protokollierung}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{5.1. Protokollierung}
|
||||
Für die Protokollierung wurden in regelmäßigen Intervallen Dokumentationen über die Tätigkeiten aller Teammitglieder geführt und diese folglich in Schrift festgehalten. Enthalten sind die Aufgabenaufteilung und die bisherige Umsetzung aller Projektteilnehmer in einer bestimmten Zeit, welche anschließend gebündelt zusammengefasst wurden.
|
||||
%
|
||||
\subsection*{5.2. Blogentwurf}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{5.2. Blogentwurf}
|
||||
Da das git efi nicht nur für Professoren sondern auch Studierenden der Fakultät efi zugänglich ist, werden die Vorgänge des Projekts in kurzen Sätzen und möglichst verständlich wiedergegeben. So können sich auch Studierende außerhalb des Fachgebietes ein ungefähres Bild von dem Fortschritt der OHM News-App machen. Nach dem Umformulieren und Reduzieren auf die Kernaussagen wurden Einträge in kontinuierlichen Abständen auf dem Hochschul github\cite{gitefi} zum Abrufen hochgeladen. Diese berufen sich auf etwa ein Monats-Abstände oder kürzer. Bei neuen Einträgen wird Professor Dr. Hopf informiert, sodass er stets den Verlauf des Projektes nachvollziehen kann. In zeitlich chronologischer Reihenfolge aufgelistet, vereinfacht dies den Überblick. Insgesamt wurden im Laufe des OHM News-App Projektes sechs Wiki Blogeinträge erstellt.
|
||||
%
|
||||
\section*{6. Pflichtenheft}
|
||||
\phantomsection\addcontentsline{toc}{section}{6. Pflichtenheft}
|
||||
Das Pflichtenheft hat die Gruppe gemeinsam zusammengestellt. Dabei sollte der Datenzugriff per MongoDB erzeugt werden, alternativ könnte auch eine Schnittstelle zur Verfügung gestellt werden. Die Grafische UI der PWA sollte einen Login, ein Menü, eine Suche, ein Profil, einen Filter nach Hashtags, ein Dashboard, Einstellungen, das Nachrichtfeld und ein Formular zum Verfassen von Nachrichten umfassen. Ein Abhängigkeitsdiagramm soll erstellt werden. Die Anwendungslogik sollte im Bereich des Routings, der Darstellung und Speicherung von Nachrichten und dem LDAP-Login umgesetzt werden. Codetests sollten durchgeführt werden und das Rollenkonzept der Nutzer sollte festgelegt werden.\\
|
||||
Des Weiteren sollte ein Anwendungsname gefunden und ein Logo erstellt werden. Ein UX Konzept sollte aufgestellt werden. Wenn es zeitlich noch möglich wäre, hätte man die Funktionen umsetzen sollen um die Datenbankabrufe zu filtern und Kanälen zu folgen. Ebenso hätte man die Anzeigekriterien festlegen können.
|
||||
%
|
||||
\section*{7. Konzepterstellung}
|
||||
\phantomsection\addcontentsline{toc}{section}{7. Konzepterstellung}
|
||||
Der erste Schritt zur Definition eines Layoutentwurfs war die Erstellung von Scribbles. Unter einem Scribble versteht man einen groben ersten Entwurf, der zur Ideenfindung beitragen soll. Nach Festlegung der grundsätzlichen Projektidee, zeichnete jedes unserer Teammitglieder Scribbles für verschiedene Seiten der App, die wir im Anschluss zusammen diskutierten. Wichtig war uns hierbei, dass jedes Teammitglied erst eigene Ideen entwickelte, um so viele verschiedene Aspekte zu sammeln.\cite{scrib} \\
|
||||
Wir versuchten alle Ideen zu vereinen und einigten uns auf einen Layoutentwurf, welcher im Anschluss in einem detaillierten Screendesign umgesetzt wurde. In Abbildung \ref{layout} ist das Screendesign für die Startseite zu sehen. Wir legten vor allem den Fokus auf die Startseite, da diese der erste Baustein der App werden sollte. Die Navigation auf die anderen Seiten erfolgt über eine Leiste am unteren Displayrand. Die weiteren Seiten legten wir zu Beginn fest, arbeiteten diese allerdings erst mit der Zeit detaillierter aus. Ein genauer Aufbau der App wird unter 9.1. beschrieben. \\
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=4.5cm]{Layout}
|
||||
\caption{Layoutentwurf der Startseite}
|
||||
\label{layout}
|
||||
\end{figure}
|
||||
Bevorstehende Implementierungen von Funktionalitäten sollten, wenn bereits im Vorfeld möglich, ebenfalls in den Layoutentwürfen berücksichtigt werden. Änderungen sind natürlich auch zu einem späteren Zeitpunkt möglich, erhöhen allerdings den Aufwand. Deswegen wurde versucht, möglichst viele Funktionalitäten bereits in die Layoutentwürfe miteinzubeziehen.\\\\
|
||||
Wir einigten uns im Projektteam darauf die App gemäß den Material Design Richtlinien von Google zu gestalten. Material Design ist eine von Google entwickelte Designvorgabe, die auf materienartigen Flächen basiert und dadurch zu einem sehr minimalistischen \mbox{Design} führt. Ziel dieser Designsprache ist unter anderem eine intuitive Benutzeroberfläche. Die Richtlinien wurden bei der Erstellung des Screendesigns berücksichtigt. \cite{md,md2}
|
||||
%
|
||||
\section*{8. Namensfindung}
|
||||
\phantomsection\addcontentsline{toc}{section}{8. Namensfindung}
|
||||
Zu Anfang haben wir uns für den Titel OHM-Management entschieden, mit dem Wissen, dass es höchstwahrscheinlich nicht dabei bleibt, da das Wort Management mit unserer angestrebten Funktionalität der App nur einschränkend passte.
|
||||
Die Verwendung des Wortstammes Kommunikation war für unsere Benennung auch nicht zutreffend, insofern der Austausch von Information nur in eine Richtung erfolgt.
|
||||
Zusätzlich gestaltete sich die Namensfindung etwas schwierig, da wir sozusagen eine App für die TH-Nürnberg entwickelten, die man auch in Verbindung mit dem OHM-Zeichen kennt. Diesbezüglich wollten wir uns bei der Benennung auch an dieses anlehnen. Um dies tun zu können, mussten wir uns erst einmal informieren, ob es ähnliche Namen bereits gibt die man aus diesem Grund dementsprechend nicht verwenden kann.
|
||||
%
|
||||
\subsection*{8.1. Recherche}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{8.1. Recherche}
|
||||
Bevor also der erste Schritt in Richtung Namensfindung gemacht werden konnte, recherchierten wir über bereits vorhandene Namen, die von der TH-Nürnberg genutzt werden. Neben Namen wie InfoTHek, OHMdoc und OHM-Shop, welche für unser Thema eher irrelevant wirkten, fanden wir auch den Titel OHM-News. Dies war ein Online Journal, welches jedoch, wie sich später rausgestellt hatte, eingestellt wurde.
|
||||
%
|
||||
\subsection*{8.2. Brainstorming}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{8.2. Brainstorming}
|
||||
In der Zwischenzeit setzten wir jedoch die Ideensammlung weiter fort und präsentierten in der Gruppe einzelne Namensvorschläge. Hieraus entstand eine Liste an kreativen Gedanken. Unsere Favoriten :
|
||||
\begin{itemize}
|
||||
\item \b{ON AIR}
|
||||
\begin{itemize}
|
||||
\item \b{O}HM \b{N}ews \b{A}pp for \b{I}nformation and \b{R}ediscovery/\b{R}ecommendations
|
||||
\item \b{O}HM \b{N}ews Stream for \b{A}ctivities, \b{I}nformation and \b{R}ecommendations
|
||||
\end{itemize}
|
||||
%
|
||||
\item \b{ON STREAM}
|
||||
%
|
||||
\begin{itemize}
|
||||
\item \b{O}HM \b{N}ews \b{Stream}
|
||||
\end{itemize}
|
||||
%
|
||||
\item \b{OHM News}
|
||||
%
|
||||
\item \b{TH i s}
|
||||
%
|
||||
\item \b{INFOhm}
|
||||
\end{itemize}
|
||||
Alle Vorschläge waren sehr durchdacht und kreativ. Jedoch hatten einige nicht ganz die Wirkung die wir uns erhofften, denn wir waren der Meinung, dass man das Wort On Air eher mit einem Radiosender verbindet. Ebenfalls der Nachteil bei der Idee On Stream war es, dass man stark an Streaming Dienste wie zum Beispiel Netflix erinnert wird.
|
||||
%
|
||||
\subsection*{8.3. Ergebnis}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{8.3. Ergebnis}
|
||||
Nach langem Überlegen kamen wir auf den Namen OHM News zurück und dieser überzeugte uns im Endeffekt alle. Dieser Titel war recht kurz, er ist leicht zu verstehen ohne viel nachzudenken, man verbindet ihn auf Anhieb mit der TH-Nürnberg auf Grund des Wortes OHM und er verweist auf die Funktionalität die unsere App bereitstellt, die da wären Neuigkeiten, sprich News, für die Studenten der Hochschule bereitzustellen.
|
||||
%
|
||||
\subsection*{8.4. Claim}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{8.4. Claim}
|
||||
Parallel zur Namensfindung, befassten wir uns auch mit dem Claim unseres Produktes. Da ein Claim die Funktion unserer App auf den Punkt bringen soll, und dabei kurz, leicht zu merken und aussagekräftig sein sollte, entschieden wir uns für eine Formulierung der Art ''nur relevante Themen werden angezeigt''. Nach einer kurzen Denkphase kamen wir auf den Claim ''See only what matters'', beziehungsweise ''Only see what matters'' vor. Dies kam bei uns allen sehr gut an, jedoch wussten wir nicht, welche von den beiden Optionen die erhoffte Bedeutung am besten hervorbringt. Sie haben zwar die selbe Bedeutung, trotz alle dem empfanden wir, dass die Betonung des Wortes „Only“ auf zwei verschiedene Faktoren des Satzes liegt. Nach reichlicher Überlegung entschieden wir uns also für die Formulierung ''See only what matters'' als Claim für unsere App.
|
||||
%
|
||||
\section*{9. Corporate Design}
|
||||
\phantomsection\addcontentsline{toc}{section}{9. Corporate Design}
|
||||
Um das ganze Konzept stimmig zu gestalten, wurde ein Corporate Design erstellt.
|
||||
Wichtigste Grundlage hierfür ist das Farbkonzept. Da die App im Hochschulrahmen verwendet werden soll, wurde für die Grundfarbe der Blauton des Hochschullogos gewählt, umso eine Zugehörigkeit zu symbolisieren. Ergänzend zu diesem Blauton werden noch zwei dezente Grautöne verwendet, wie in Abbildung \ref{farbschema} zu sehen ist. \\
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=12cm]{Farbschema_CD}
|
||||
\caption{Farbkonzept}
|
||||
\label{farbschema}
|
||||
\end{figure}
|
||||
\noindent Für die Schrift wird in der gesamten App die von Google Material Design vorgegebene Schriftart Roboto verwendet. Diese ist eine serifenlosen Schriftart und deshalb durchweg gut lesbar.
|
||||
Auch ein Logo ist wichtig, um einen gewissen wiedererkennungswert für die App zu schaffen. Da wir uns in der Gruppe für den App-Namen ''Ohm-News'' entschieden haben, war der erster Gedanke eine Zeitung für das Logo herzunehmen (siehe Abbildung \ref{logo1}). Die Grafik war allerdings schwierig in das Produkt einzubinden, weil sie sehr detailreich ist. \\
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=4cm]{Logo1_CD}
|
||||
\caption{Erster Logoentwurf}
|
||||
\label{logo1}
|
||||
\end{figure}
|
||||
\noindent Ein zweiter etwas minimalistischer Entwurf ist in Abbildung \ref{logo2} zu sehen, für welchen sich das Projektteam schlussendlich auch entschied. Es zeigt ein Globussymbol mit dem Hochschullogo im Zentrum, um auch hier wieder die Verbindung zur Hochschule schaffen. \\
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=4cm]{Logo2_CD}
|
||||
\caption{Finales Logo}
|
||||
\label{logo2}
|
||||
\end{figure}
|
||||
%
|
||||
\noindent Das Logo wurde dann auch zu einem App Icon erweitert. In Abbildung \ref{icons} ist das Icon für Android sowie IOS Geräte zu sehen. Das Android Icon wurde analog den Material-Design Richtlinien gestaltet und besitzt deshalb einen leichten Schatten. Bei dem IOS Icon wurde das Logo lediglich auf einen einfarbigen Hintergrund gesetzt. \\
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=10cm]{Icons_CD}
|
||||
\caption{App Icons}
|
||||
\label{icons}
|
||||
\end{figure}
|
||||
%
|
||||
\section*{10. Erstellung der Mockups}
|
||||
\phantomsection\addcontentsline{toc}{section}{10. Erstellung der Mockups}
|
||||
Auf Basis des Screendesigns wurden erste Mockups erstellt, welche mittels HTML und CSS umgesetzt wurden. Um die Elemente entsprechend den Material-Design Richtlinien zu gestalten, wurde das CSS-Framework Bootstrap mit eingebunden, das eine Auswahl an vordefinierten Gestaltungselementen und Stilen in Form von CSS-Stylesheets bereitstellt. Dazu gehören Elemente wie Buttons, Formulare, Navigationszeilen und viele mehr. Wir verwendeten Bootstrap Dateien, die auf Material Design abgestimmt sind. So wird ein einheitliches Design gewährleistet und die Styles müssen nicht selbst erstellt werden. Ein weitere Vorteil von Bootstrap, ist, dass es ein responsives Webdesign unterstützt und man deshalb plattformunabhängig entwickeln kann. Dafür sorgt ein Grid-Layout, welches den Benutzerbildschirm in 12 Spalten teilt und die Elemente, je nach verfügbarer Auflösung, anzeigt. Im ersten Projektabschnitt legten wir den Fokus besonders auf eine mobile Ansicht. Eine Desktopansicht wird ebenfalls unterstüzt, kann allerdings noch stark optimiert werden. \cite{bootstrap} \\
|
||||
Durch die Ergänzung von eigenen CSS-Dateien konnten Änderungen an den vordefinierten Stilen vorgenommen werden. Sowohl unsere als auch die von Bootstrap bereitgestellten Dateien, wurden auf Grundlage von Less-Stylesheets erstellt. Dabei wird auf effiziente Weise CSS generiert. Variablen sowie Funktionen sind möglich und Vererbung wird durch \mbox{verschachtelte} Selektoren dargestellt. \cite{less} \\
|
||||
Wir habe für jeden Menüpunkt eine HTML-Seite erstellt, welche im Unterpunkt genauer beschrieben werden.
|
||||
%
|
||||
\subsection*{10.1. Aufbau der App}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{10.1. Aufbau der App}
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\begin{minipage}[t]{5cm}
|
||||
\vspace{0pt}
|
||||
\centering
|
||||
\includegraphics[width=4cm]{Homescreen_MU}
|
||||
\caption{Startseite}
|
||||
\label{abbildung_homescreen}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}[t]{11cm}
|
||||
\vspace{0pt}
|
||||
Auf der Startseite der App gelangt der Nutzer als erstes auf einen Newsfeed. Der Newsfeed besteht aus einzelnen Nachrichten in Form von Karten und soll für jeden Nutzer nur \mbox{relevante} Nachrichten anzeigen. Jede Nachricht besitzt einen oder \mbox{mehrere} Tags. Eine Nachricht wird für einen Nutzer als relevant eingestuft, wenn dieser mindestens einen Tag aus der Nachricht abonniert hat. Somit erhält jeder Nutzer eine individuelle Startseite. Zusätzlich befindet sich auf der Nachrichtenkarte oben rechts ein Icon, welches die Nachricht zu einer Fakultät zuordnet. Unten rechts kann das Lesezeichen-Icon geklickt werden, um eine Nachricht zu speichern. Auf diese Weise können die Studierenden wichtige Informationen schnell wiederfinden.\\\\
|
||||
Im Header ist die Suche zu finden, in der Tags explizit gefiltert werden können. Der \mbox{Header} ist von jeder Seite aus zugängig. Im Footer befindet sich die Navigationszeile, von wo aus der Nutzer auf die weiteren Seiten gelangt.
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\begin{minipage}[t]{5cm}
|
||||
\vspace{0pt}
|
||||
\centering
|
||||
\includegraphics[width=5cm]{Links_MU}
|
||||
\caption{Infoseite}
|
||||
\label{abbildung_infoseite}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}[t]{11cm}
|
||||
\vspace{0pt}
|
||||
Der zweiten Menüpunkt, der durch ein Globus-Icon dargestellt wird, soll eine Informationsseite beinhalten. Das Konzept hierfür ist allerdings noch nicht konkret ausgearbeitet, da wir uns zuerst auf die Mitteilungsfunktionen konzentrieren wollten. Aktuell wird ein Empty State angezeigt.
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
%
|
||||
\medskip
|
||||
\begin{figure}[H]
|
||||
\begin{minipage}[t]{5cm}
|
||||
\vspace{0pt}
|
||||
\centering
|
||||
\includegraphics[width=5cm]{CreateMessage_MU}
|
||||
\caption{Formular}
|
||||
\label{abbildung_createmsg}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}[t]{10cm}
|
||||
\vspace{0pt}
|
||||
Über das Plus-Icon, in der Mitte der Navigationszeile, gelangt man zu einem Formular. Hier können neue Nachrichten erstellt werden. Nachrichten sollen nur von ausgewählten Nutzergruppen, wie Fakultäten, Studienbüro und ähnlichen gesendet werden können.
|
||||
Für eine Nachricht wird ein Betreff, mindestens ein Tag und der Nachrichteninhalt benötigt. Es soll eine Auswahl an vordefinierten Tags geben, damit am Ende nicht jeder Verfasser wahllos Tags setzten kann und \mbox{Duplikate} vermieden werden. Dieser Menüpunkt ist der einzige in dem keine Navigationszeile angezeigt wird. Nach Absenden einer Nachricht, gelangt man zurück auf die Startseite. Über den Button 'Abbrechen' wird man auf den vorherigen Menüpunkt zurückgeleitet.
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\begin{minipage}[t]{5cm}
|
||||
\vspace{0pt}
|
||||
\centering
|
||||
\includegraphics[width=5cm]{Gespeicherte_MU}
|
||||
\caption{Gespeicherte}
|
||||
\label{abbildung_gespeichert}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}[t]{11cm}
|
||||
\vspace{0pt}
|
||||
Der nächste Menüpunkt wird über das Lesezeichen-Icon erreicht und zeigt die gespeicherten Nachrichten an. Diese Seite ist ähnlich aufgebaut wie der Newsfeed der Startseite, beinhaltet allerdings nur die vom Nutzer gespeicherten Nachrichten.
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
%
|
||||
\medskip
|
||||
\begin{figure}[H]
|
||||
\begin{minipage}[t]{5cm}
|
||||
\vspace{0pt}
|
||||
\centering
|
||||
\includegraphics[width=5cm]{Profil_MU}
|
||||
\caption{Profil}
|
||||
\label{abbildung_profil}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}[t]{11cm}
|
||||
\vspace{0pt}
|
||||
Der letzte Menüpunkt ist das Profil. \\
|
||||
Oben sieht man zuerst das Profilbild, hier verwendeten wir die runde Form anstatt der üblichen Quadratischen. Darunter sieht man dann die im Vorfeld angegebene Information des Benutzers. Am Ende der sogenannten Karte befinden sich zwei Knöpfe, die Anzeigen wie vielen Kanälen man folgt und wie viele Beiträge man bis jetzt gespeichert hat. Auf der Karte rechts oben im Eck findet man den Bearbeitungs-Knopf, in Form eines kleinen Stiftes, dies ermöglicht dem Benutzer, die Seite gemäß seinen Wünschen anzupassen.
|
||||
\end{minipage}
|
||||
\end{figure}
|
||||
%
|
||||
\section*{11. Single-Page Entwicklung}
|
||||
\phantomsection\addcontentsline{toc}{section}{11. Single-Page Entwicklung}
|
||||
Neben klassischen Webanwendungen gibt es ebenfalls Single-Page Webanwendungen. Bei klassischen Webapplikationen gibt es mehrere untereinander verlinkte HTML-Dokumente, die dann gemeinsam eine komplette Anwendung ausmachen. Der Nachteil hierbei ist, dass die Seite beim Wechsel durch die erneute Kommunikation mit dem Server neu heruntergeladen werden muss. SPA’s jedoch bestehen nur aus einer HTML-Datei. Dies bewirkt, dass neue oder veränderte Daten dynamisch geladen werden und somit die Kommunikation zwischen Server und Client verringert wird. Es ermöglicht dem Benutzer, nach dem einmaligen laden der Seite, diese auch weiterhin im offline Modus zu steuern. Sollte also die Interaktion mit dem Server unterbrochen werden, werden die zwischengespeicherten Daten einfach aus dem Webbrowser verwendet.\cite{spa:1}\cite{spa:2}
|
||||
%
|
||||
\subsection*{11.1. Warum Vue.js?}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{11.1. Warum Vue.js?}
|
||||
Neben dem Vue.js Framework gibt es noch weitere wie zum Beispiel react.js, angular.js, meteor.js und viele mehr. Warum wir uns jedoch für das Vue.js Framework entschieden haben, werden wir Ihnen nun erläutern. Vue.js das jüngste von den drei größten Frameworks, es hat jedoch den Vorteil, dass es aus den Fehlern der Vorgänger lernen konnte und diese schon im Vorfeld überdenken und ausmerzen konnte. Da es auf Sprachen wie HTML, CSS und JavaScript aufbaut, lässt es sich problemlos in schon bestehende Projekte einbauen.
|
||||
Die Syntax ist hierbei, im Vergleich zu anderen, besser lesbar. Hierfür werden nämlich sogenannte ''Single File Components'' verwendet.\cite{vue:warum} Sogenannte Komponenten sind wiederverwendbare Vue-Instanzen mit einem Namen, die als benutzerdefiniertes Element in einer Vue-Stamminstanz verwendet werden. Wie so eine erstellte Komponente aussieht, werden wir Ihnen im folgenden erörtern.
|
||||
%
|
||||
\subsection*{11.2. Vue.js in vorhandene Mockups einbinden}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{11.2. Vue.js in vorhandene Mockups einbinden}
|
||||
Nach reichlicher Recherche und dem einlesen in das uns vorher unbekannte Framework, war es an der Zeit unsere HTML-Seiten in Vue-Komponenten umzuwandern. Wir setzten uns erstmal zusammen und erstellten die Startseite.
|
||||
Im Folgenden wird der Aufbau der Home-Komponente näher erläutert. In Listing 1 ist der dazugehörige Quellcode zu sehen. Nicht enthalten sind zur Komponente zugehörige Methoden. Die Home-Komponente wird in unserem Projekt als HomeRouter betitelt.
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={HomeRouter-Komponente},captionpos=b]
|
||||
const HomeRouter = {
|
||||
template: `
|
||||
<div id="om-msg-cards">
|
||||
<MsgCard
|
||||
v-for="id in messagelist.slice().reverse()"
|
||||
:key="id"
|
||||
:msg="messages[id] || {}"
|
||||
></MsgCard>
|
||||
</div>`,
|
||||
//Restliche Komponente
|
||||
...
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Im Newsfeed, welcher der Hauptbestand der Startseite ist, wird eine Liste von Nachrichten dynamisch generiert, sodass jeder Nutzer später einmal eine individuelle Ansicht erhält, abhängig von den Tags, die dieser abonniert. \\
|
||||
Jede Komponente besitzt ein Template in Form eines Strings, welcher HTML-Code \mbox{beinhaltet}. Die Komponente HomeRouter ist verschachtelt und enthält die Komponente MsgCard. Der Quellcode für diese Komponete ist in Listing 2 zu sehen.
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={MsgCard-Komponente},captionpos=b]
|
||||
Vue.component('MsgCard', {
|
||||
template: `<div class="om-card card">
|
||||
<h6 class="msg-head">
|
||||
<b>{{ msg.subject }}</b>
|
||||
<img src="favicon.ico" width=20px height=20px>
|
||||
</h6>
|
||||
{{ msg.message }}<br><br>
|
||||
<a href="#">{{ msg.tag }}</a></p>
|
||||
<div class="om-card-footer"> <div class="om-user-line">
|
||||
<i class="material-icons">account_circle</i>
|
||||
Erstellt von {{ msg.user }}</div>
|
||||
<i class="material-icons">bookmark_border</i>
|
||||
</div></div>`,
|
||||
props: ['msg']
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Eine MsgCard stellt eine einzelne Nachricht in Form einer Karte dar. In der HomeRouter-Komponete geht eine For-Schleife alle vorhandenen Nachrichten-Ids durch. Dabei werden der MsgCard-Komponente alle relevanten Informationen übergeben, die für eine Darstellung benötig wird. Am Ende stellt die App eine fortlaufende Liste mit allen Nachrichten dar.\\\\
|
||||
Da wir nun ein bisschen geübter im Umgang mit Vue waren, teilten wir uns die restlichen Seiten auf. Dabei gingen wir ähnlich vor, wie bei der Home-Komponente.
|
||||
%
|
||||
\subsection*{11.3. Routing}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{11.3. Routing}
|
||||
Vue.js bietet eine Reihe von Funktionen, mit denen Sie wiederverwendbare Webkomponenten erstellen können. Routing ist eine dieser Methoden. Der Benutzer kann somit zwischen den Seiten wechseln, ohne diese erneut zu aktualisieren. Dies ermöglicht dem Benutzer eine einfache und dynamische Navigation durch die Webanwendung. Wir werden Ihnen nun, anhand unseres Codes erklären, wie ein Vue.js-Router funktioniert.\cite{vue:router} \\
|
||||
Zunächst richten wir hierfür die Navigation über die Navigationsbar ein, die wir mittels einem Router-Link-Element erstellt haben. Dieser gibt an, auf welche der angegebenen JS-Datei zugegriffen wird sobald man auf das ausgewählte Item klickt.
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Navbar},captionpos=b]
|
||||
<nav class="nav nav-tabs nav-justified om-nav" v-if="$route.path !=='/createMessage' ">
|
||||
<router-link to="/home" class="nav-item nav-link">
|
||||
<i class="material-icons">home</i></router-link>
|
||||
<router-link to="/files" class="nav-item nav-link">
|
||||
<i class="material-icons">language</i></router-link>
|
||||
<router-link to="/createMessage" class="nav-item nav-link outlined">
|
||||
<i class="material-icons">add_circle</i></router-link>
|
||||
<router-link to="/bookmark" class="nav-item nav-link">
|
||||
<i class="material-icons">bookmark</i></router-link>
|
||||
<router-link to="/profil" class="nav-item nav-link">
|
||||
<i class="material-icons">person</i></router-link>
|
||||
</nav>
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Im Folgenden werden Komponenten definiert und dann in ein neues Array von Objekten, so genannte Routen, eingefügt. Zu beachten ist die Zuordnung eines URL-Pfads zu der dazugehörigen Komponente. Daraufhin wird ein Vue-Router definiert, der an ein neues Vue-Objekt übergeben wird. Wenn nun beispielsweise ''/home'' geladen ist, wird die Home-Komponente in der Router-Ansicht gerendert und aufgerufen. Die erste Zeile mit dem ''/'' steht für die Startseite, auf die man gelangt, sobald man die App öffnet.\cite{vue:router3} \\
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Routing},captionpos=b]
|
||||
const routes = [
|
||||
{ path: "/", component: HomeRouter },
|
||||
{ path: "/home", component: HomeRouter },
|
||||
{ path: "/files", component: FileRouter },
|
||||
{ path: "/createMessage", component: CreateMsgRouter },
|
||||
{ path: "/bookmark", component: BookmarkRouter },
|
||||
{ path: "/profil", component: ProfilRouter },
|
||||
];
|
||||
const router = new VueRouter({
|
||||
routes
|
||||
});
|
||||
var app = new Vue({
|
||||
router,
|
||||
el: '#api',
|
||||
methods: {
|
||||
...
|
||||
},
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
\section*{12. Service Worker}
|
||||
\phantomsection\addcontentsline{toc}{section}{12. Service Worker}
|
||||
Der ServiceWorker ist eine JavaScript Datei, die üblicherweise im root-Verzeichnis der Webanwendung liegt. Für die Funktionsweise ist die Namensgebung der Datei nicht maßgebend. Damit der ServiceWorker überhaupt funktionieren kann, wird eine SSL-Verbindung benötigt. Ist eine sicher Verbindung gegeben, kann der ServiceWorker (im Weiteren auch mit ''SW'' abgekürzt) nach erfolgreichem Laden der Webseite im Browser des Clients registriert werden. Nachdem der SW zeitlich unabhängig, also asynchron im Browser läuft, muss bei der Entwicklung und Umsetzung des ServiceWorker-Codes darauf geachtet werden, dass in Promises geschrieben wird. Da Promises ein wenig schwieriger nachzuvollziehen sind und insbesondere das Problem der sogenannten Callback-Hell nicht lösen, bietet es dich an den SW in Async/Await Struktur zu schreiben. Diese basiert auf dem asynchronen Prinzip der Promises und lässt sich dennoch lesen wie synchrone Funktionen.\\
|
||||
Zunächst wird der ServiceWorker, nach dem vollständigen Laden der Webanwendung, versuchen sich im Browser des Clients zu registrieren. Schlägt die Registrierung fehl, ist dies ein Anzeichen dafür, dass der genutzte Browser keine ServiceWorker unterstützt. Es folgen zwei Code Umsetzungen, beide dienen der Registrierung:\\
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Register, Promise/Then-Codestruktur},captionpos=b]
|
||||
/* Promise / Then */
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('/serviceWorker.js').then(function(registration) {
|
||||
// Registration was successful
|
||||
}, function(err) {
|
||||
// registration failed
|
||||
});
|
||||
});
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Register, Async/Await-Codestruktur},captionpos=b]
|
||||
/* Async / Await */
|
||||
const registerServiceWorker = async () => {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.register('/serviceWorker.js', {scope: '/'});
|
||||
// Registration successful
|
||||
} catch (err) {
|
||||
// Registration failed
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', registerServiceWorker());
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Einmal in der Promise.then Schreibweise und einmal in der Async/Await Schreibweise.\\
|
||||
Nach erfolgreicher Registrierung, folgt das ServiceWorker Event Installation. Dabei wird eine neue ServiceWorker Version im Browser angelegt und ein Abbild der festgelegten Dateien, hier als Beispiel nur die ''index.html'' (siehe filesToCache), im sogenannten ''Local Storage'' mittels Cache-Managements (auch Cache API genannt) gespeichert. Diese beiden Code Blöcke zeigen den Install-Vorgang:
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Install, Promise/Then-Codestruktur},captionpos=b]
|
||||
/* Promise / Then */
|
||||
const cacheName = 'appname-v1-0';
|
||||
const filesToCache = [ '/index.html' ];
|
||||
self.addEventListener('install', function(event) {
|
||||
console.log('[ServiceWorker] Install');
|
||||
event.waitUntil(
|
||||
caches.open(cacheName).then(function(cache) {
|
||||
console.log('[ServiceWorker] Caching app shell');
|
||||
return cache.addAll(filesToCache);
|
||||
})
|
||||
);
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Install, Async/Await-Codestruktur},captionpos=b]
|
||||
/* Async / Await */
|
||||
const installNewCache = async (event) => {
|
||||
const cacheName = 'appname-v1-0';
|
||||
const filesToCache = [ '/index.html' ];
|
||||
const cacheStatic = await caches.open(cacheName);
|
||||
cacheStatic.addAll(filesToCache);
|
||||
console.log('[ServiceWorker] Cache static files.');
|
||||
return;
|
||||
}
|
||||
self.addEventListener('install', event => {
|
||||
// don't wait
|
||||
self.skipWaiting();
|
||||
// cache static files
|
||||
event.waitUntil(installNewCache());
|
||||
console.log('[ServiceWorker] Install');
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Anschließend folgt die Aktivierung. Hier wird aufgeräumt und zwar die alten ServiceWorker Versionen. Es sollte immer nur eine ServiceWorker Version je Webanwendung im Browser registriert und installiert sein.
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Activate, Promise/Then-Codestruktur},captionpos=b]
|
||||
/* Promise / Then */
|
||||
self.addEventListener('activate', function(event) {
|
||||
// ServiceWorker activated
|
||||
event.waitUntil(
|
||||
caches.keys().then(function(cacheKeyList) {
|
||||
return Promise.all(
|
||||
cacheKeyList.map(function(cacheKeyList) {
|
||||
if (cacheWhitelist.indexOf(cacheKeyList) === -1) {
|
||||
// Old Cache removed
|
||||
return caches.delete(cacheKeyList);
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
return self.clients.claim();
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Activate, Async/Await-Codestruktur},captionpos=b]
|
||||
/* Async / Await */
|
||||
const cacheCleanUp = async () => {
|
||||
const cacheKeyList = await caches.keys();
|
||||
const deletions = cacheKeyList
|
||||
.filter(key => key.startsWith(appPrefix) && !cacheKeyList.includes(key))
|
||||
.map(key => {
|
||||
caches.delete(key)
|
||||
// Old Cache removed
|
||||
});
|
||||
for (const success of deletions) {
|
||||
await success;
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(cacheCleanUp());
|
||||
clients.claim();
|
||||
// ServiceWorker activated
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Als letzter Schritt bleibt nur noch der 'fetch'. Das ist jenes Event in dem der ServiceWorker neue, aktuelle Dateien aus dem Netzwerk bezieht und die Dateiversionen im Cache, lokalen Speicher aktualisiert. Hier gibt es verschiedene Vorgehensweisen. Wir haben uns entschieden, das der ServiceWorker nur jene API GET-Anfragen speichern soll. Dies dient der Vermeidung doppelter und korrupter Datensätze. Im Weiteren soll überprüft werden, ob die angefragten Dateien mit den gespeicherten Dateien übereinstimmt. Falls nicht, gibt es keine gespeicherten Daten und eine Netzwerkanfrage wird zwingend benötigt. Andernfalls zeige die gespeicherten Daten an und tätige anschließend eine Anfrage ans Netzwerk. Wenn aktuellere Daten aus dem Netzwerk empfangen werden, so aktualisiere die gespeicherten Dateien und zeige die aktuelleren Daten an. Zusätzlich wird noch ein wenig der Ursprung der Anfrage überprüft.
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Fetch, Promise/Then-Codestruktur},captionpos=b]
|
||||
/* Promise / Then */
|
||||
self.addEventListener('fetch', function(event) {
|
||||
/* We should only cache GET requests */
|
||||
if (event.request.method !== 'GET') {
|
||||
/* If we don't block the event as shown below,
|
||||
then the request will go to the network as usual. */
|
||||
console.log('[ServiceWorker] Fetch event ignored.',
|
||||
event.request.method, event.request.url);
|
||||
return;
|
||||
}
|
||||
event.respondWith(
|
||||
caches.match(event.request)
|
||||
.then(function(response) {
|
||||
return fetch(event.request)
|
||||
.then(function(response) {
|
||||
// Check if response is valid, status is 200, response type is basic
|
||||
// (indicates request is from origin, means that requests to third party
|
||||
// assets aren't cached as well.
|
||||
if(!response || response.status !== 200 || response.type !== 'basic') {
|
||||
return response;
|
||||
}
|
||||
caches.open(CACHE_NAME)
|
||||
.then(function(cache) {
|
||||
// We have to clone the response here because request bodies can only
|
||||
// be read once. Placing a response in the cache counts as a read.
|
||||
cache.put(event.request, response.clone());
|
||||
});
|
||||
// Cache hit - return response
|
||||
if (response) return response;
|
||||
return response;
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
// Report a lack of connectivity to the user.
|
||||
});
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={Fetch, Async/Await-Codestruktur},captionpos=b]
|
||||
/* Async / Await */
|
||||
self.addEventListener('fetch', event => {
|
||||
/* We should only cache GET requests */
|
||||
if (event.request.method !== 'GET') {
|
||||
/* If we don't block the event as shown below,
|
||||
then the request will go to the network as usual. */
|
||||
console.log('[ServiceWorker] Fetch event ignored.',
|
||||
event.request.method, event.request.url);
|
||||
return;
|
||||
}
|
||||
event.respondWith(async function update() {
|
||||
try {
|
||||
var requestURL = new URL(event.request.url);
|
||||
// Start the network request as soon as possible.
|
||||
const networkPromise = fetch(requestURL);
|
||||
const cachedResponse = await caches.match(event.request);
|
||||
const networkResponse = await networkPromise;
|
||||
// Check if response is valid, status is 200, response type is basic
|
||||
// (indicates request is from origin, means that requests to third party
|
||||
// assets aren't cached as well.
|
||||
if (!networkResponse || networkResponse.status !== 200
|
||||
|| networkResponse.type !== 'basic') return networkResponse;
|
||||
const cache = await caches.open(staticCacheKey);
|
||||
// We have to clone the response here because request bodies can only
|
||||
// be read once. Placing a response in the cache counts as a read.
|
||||
cache.put(event.request, networkResponse.clone());
|
||||
if (cachedResponse) return cachedResponse;
|
||||
// ServiceWorker fetch
|
||||
return networkResponse;
|
||||
} catch (err) {
|
||||
// Report a lack of connectivity to the user.
|
||||
}
|
||||
}());
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Die Bildausschnitte mit dem Code wurden teils von mir erstellt, teils stammen diese von dieser Internetseite\cite{dev:codeSource}\cite{sw:cacheThenNetwork}.
|
||||
%
|
||||
\pagebreak
|
||||
\section*{13. ''Add-To-Homescreen''-Funktion}
|
||||
\phantomsection\addcontentsline{toc}{section}{13. ''Add-To-Homescreen''-Funktion}
|
||||
Für die Implementierung der ''Add-to-Homescreen''-Funktionalität sind für Android, iOS und die diversen Browser unterschiedliche Schritte nötig.\\
|
||||
Bei Android genügt es eine manifest.json Datei im root-Verzeichnis der App abzulegen. Diese Manifest-Datei enthält Meta-Informationen von App-Icon, über App-Name, über die Start-URL bis hin zu der Theme-Farbe für den Hintergrund des App-Icons oder dem Navigationsmenü im Browser. Wenn ein Nutzer im Abstand von 5 Minuten (Standard-Einstellung) die Webseite zweimalig aufruft, so wird dieser gefragt, ob er die App zum Homescreen hinzufügen möchte. Ab da kann er diese über das App-Icon als auch über den Browser starten.\\
|
||||
Für iOS müssen die Meta-Informationen im Bereich des Head-Elements, der index.html eingefügt werden. So wird dort das Aussehen von mehreren App-Icon Versionen definiert. Dies wird benötigt, da die meisten Apple-Geräte unterschiedliche Density (Pixel per Inch) haben. Des Weiteren werden Konfigurationseinstellungen aktiviert oder deaktiviert, als auch das Aussehen des Ladescreens für iOS Geräte festgelegt.\\
|
||||
Auch die Windows-Mobilgeräte muss in der index.html Datei im Head-Bereich mittels Meta-Informationen mitgeteilt werden, wie der Ladebildschirm oder das Appicon aussehen soll (vgl.\cite{dev:homescreen}).
|
||||
%
|
||||
\section*{14. Erstellung der API-Schnittstelle}
|
||||
\phantomsection\addcontentsline{toc}{section}{14. Erstellung der API-Schnittstelle}
|
||||
Nachdem Server und die Clientseite der PWA funktionsfähig waren, war es noch relevant, dass zwischen diesen beiden kommuniziert werden kann. Dafür verwendet man die API.\cite{api} API steht für ''Application Programming Interface'' und diese Programmierschnittstelle kann wie in diesem Projekt zum Zugriff auf die Datenbank verwendet werden. Dabei handelt es sich in diesem Fall um einen RESTful Webservice.\cite{rest} \\
|
||||
%
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.3\textwidth]{ajax.png}
|
||||
\caption{Ajax Modell einer Webanwendung. Quelle: nach Haischt, Daniel; https://de.wikipedia.org/wiki/Ajax\_(Programmierung)\#/media/File:Ajax-vergleich.svg}
|
||||
\label{ajax}
|
||||
\end{figure}
|
||||
%
|
||||
\noindent Das asynchrone Datenübertragungskonzept AJAX wurde zur Kommunikation zwischen Browser und Server verwendet.\cite{ajax1} \cite{ajax2} \cite{ajax3} Dabei werden wie in Abbildung \ref{ajax} zu sehen ist HTTP Requests von dem Browser an den Server geschickt. Diese werden daraufhin von dem Server verarbeitet und es werden entweder Daten zurückgegeben oder ein HTTP Response mit einer Rückmeldung. Mit der Verwendung von AJAX hat man einige Vorteile, zum Beispiel, dass man die Seite nicht neu laden muss, damit die neuen Inhalte erscheinen und dass der Browser bereits weiter Requests schicken kann, ohne auf die Responses des Servers warten zu müssen. Da die gesamte PWA des Projekts in JavaScript geschrieben ist, ist es zudem vorteilhaft, dass die AJAX-Engine in JavaScript geschrieben wird. Die Daten aus der Datenbank werden im JSON-Format transportiert.\\
|
||||
\\
|
||||
Um die Funktionsweise einer derartigen Schnittstelle zu verstehen, wurde der Code einer PWA die Professor Matthias Hopf geschrieben und der Gruppe zur Verfügung gestellt hat, analysiert. Dieser war jedoch etwas zu komplex für einen Einsteiger in das Thema. Deswegen wurde auf simplere Beispiele in Tutorials zurückgegriffen. Diese Beispiele konnten nun auf das eigene Projekt übertragen und getestet werden. Nach einer ausführlichen Erläuterung durch Professor Hopf anhand eines Beispiels im Projektzusammenhang, war ein grundsätzliches Verständnis über die Schnittstelle vorhanden. Nun konnte die konkrete Umsetzung der API beginnen.\\
|
||||
Die erste Methode die umgesetzt wurde war ''list\_messages''. Diese zeigt nun alle Nachrichten der Datenbank auf der Startseite der PWA an. Dazu musste zuerst vom Server die IDs aller Nachrichten abgefragt werden. Man schreibt eine API Funktion, die ein GET Request an den Server schickt. Dieser sucht nach den IDs per find Anfrage in der Datenbank und antwortet mit einem HTTP Response, der das Array mit den IDs enthält. Auf der Client Seite wird nun für jede ID per GET Request alle Informationen der Nachricht angefragt. Der Server sucht die gefragten Information und schickt diese zurück mit dem dazugehörigen Nachrichtentext an den Browser.\\
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={''list\_messages''-Methode},captionpos=b]
|
||||
list_messages: function () {
|
||||
$.ajax({url: "api/ids", method: "GET"})
|
||||
.done(jd => {
|
||||
_messagelist.splice(0, _messagelist.length);
|
||||
_messagelist.push.apply(_messagelist, jd);
|
||||
console.log("jd: "+jd);
|
||||
for (var e in jd) {
|
||||
if (!_messages[jd[e]]) {
|
||||
get_insert_message(jd[e]);
|
||||
}
|
||||
}
|
||||
}).fail(function (e, f, g) {
|
||||
console.log("err: " + e + f + g);
|
||||
});
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
Was für Vorgänge beim Senden einer Nachricht in einer API getätigt werden, ist im Folgenden aufgeführt. Hierfür muss die Mongodb heruntergeladen und angebunden sein.\\
|
||||
In der Server.js Datei wird durch die ''App.post''-Methode eine Nachricht erstellt. Dabei wird in ''createMsg'' die Funktion aufgerufen, in einen String umgewandelt und die Nachricht anschließend in der Datenbank gespeichert. Mit der POST-Methode können Nachrichten in die Datenbank gespeichert werden und anhand von einer GET-Methode angezeigt werden.\\
|
||||
Nun müssen in der createMsg.js alle Werte einsetzbar gestaltet werden. Wichtig dabei ist, sich an das vorgegebene Mongo Schema zu halten. Durch die ajax-Methode ''post'' können große Datenmengen an den Server geschickt werden. Zuletzt soll die Konsole auch einen Error anzeigen, falls der Abruf der Funktion erfolglos war. \\
|
||||
In Abbildung \ref{sys} kann man diese Vorgänge nachverfolgen. Diese beiden Funktionen haben am Ende funktioniert und können zusammen verwendet werden. \\
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.7\textwidth]{system.png}
|
||||
\caption{Erstellen einer Nachricht und Anzeigen aller Nachrichten}
|
||||
\label{sys}
|
||||
\end{figure}
|
||||
%
|
||||
\section*{15. Aufsetzung des Servers}
|
||||
\phantomsection\addcontentsline{toc}{section}{15. Aufsetzung des Servers}
|
||||
Zunächst muss ein http port eingerichtet werden. Über einen lokalen Server über node.js ist die Ohm News-App abrufbar. Mit der createServer Methode
|
||||
%
|
||||
\begin{center}
|
||||
\begin{lstlisting}[caption={''list\_messages''-Methode},captionpos=b]
|
||||
http.createServer(app).listen(http_port, function () {
|
||||
console.log("Express http server listening on port " + http_port);
|
||||
});
|
||||
\end{lstlisting}
|
||||
\end{center}
|
||||
%
|
||||
lässt sich ein Server aufsetzen. Hier wird auch der Listener für den Port impliziert und auf der Konsole ausgegeben, wenn die Verbindung erfolgreich war. \\
|
||||
Um die wichtigsten Fehlermeldungen und Bugs auszugeben, wird für unsere node.js App der Logger ''Morgan'' verwendet. Zusätzlich wird eine try-catch Funktion eingeordnet, da Zertifikat und Schlüssel noch nicht zertifiziert sind (siehe SSL und Keys) und somit vorerst ein Fehler angezeigt wird.
|
||||
%
|
||||
\subsection*{15.1. SSL und Keys}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{15.1. SSL und Keys}
|
||||
Um die Applikation für die Nutzer sicher zu gestalten und eine Verschlüsselung sensibler Daten zu gewährleisten, sorgt ein SSL(Secure Socket Layer). Dadurch wird ein sicherer Kanal zwischen Web-Server und Client bereitgestellt und aus der http- wird eine https-Verbindung.
|
||||
\setlength{\parindent}{0cm}
|
||||
Übergangsweise werden ein selbst verifizierter Schlüssel und Zertifikat erstellt, welche später durch echte ausgetauscht werden. In einem neu erstellten Ordner ''keys'' werden das Zertifikat und der Schlüssel platziert.
|
||||
%
|
||||
\section*{16. Datenbankanbindung}
|
||||
\phantomsection\addcontentsline{toc}{section}{16. Datenbankanbindung}
|
||||
Für diese Anwendung wird eine Datenbank benötigt, weil die geschriebenen Nachrichten gespeichert werden müssen. Später sollen auch User mit ihren Userinformationen gespeichert werden. Im Falle dieses Projekts wurde sich für eine MongoDB entschieden.\\
|
||||
MongoDB ist eine dokumentenorientierte NoSQL Datenbank. Diese ist für diese Anwendung sinnvoll, da sie im Vergleich zu SQL Datenbanken flexibler handhabbar ist und somit auch viele Einstellungen noch im Nachhinein geändert werden können.\cite{mongo} \\
|
||||
Um den Umgang mit MongoDB zu vereinfachen wurde Mongoose, eine Object Data Modeling Bibliothek, verwendet.\cite{mongoose} \\
|
||||
Da man zu Beginn des Projekts noch nicht mit NoSQL Datenbanken gearbeitet hatte, mussten zuerst Tutorials und Erklärungen gelesen werden. Anhand von Beispieltests mit einer lokalen Datenbank konnte die grundsätzliche Funktionsweise bald verstanden werden. Daraufhin wurde das grobe Schema für eine Nachricht aufgebaut. Eine Nachricht sollte einen Betreff, eine Nachricht, den schreibenden User und die Tags beinhalten wie man in Listing \ref{lst:json} an einer beispielhaften JSON-Datei sehen kann. Die Datenbank musste konfiguriert und gestartet werden.
|
||||
%
|
||||
\begin{center}
|
||||
\lstset{language=xml}
|
||||
\begin{lstlisting}[caption={Nachricht im JSON-Format},captionpos=b,label=lst:json]
|
||||
{
|
||||
"messages": [{
|
||||
"subject": "Test"
|
||||
"message": "Hallo Welt!"
|
||||
"tag": "#OHM_News"
|
||||
"user": "User1"
|
||||
}]
|
||||
}
|
||||
\end{lstlisting}
|
||||
\lstsetdefault
|
||||
\end{center}
|
||||
%
|
||||
Die serverseitigen Codeteile zur API und der Code für die Datenbank sind momentan zur Vereinfachung in der server.js Datei. Später sollen diese zur Übersichtbarkeit und Wartbarkeit ausgelagert werden. Das Schema für die Nachricht und die Konfiguration der Datenbank sind zu diesem Zweck bereits in eigenen js-Dateien zu finden.\\
|
||||
Sobald all das lokal funktioniert hat, wurde die Portierung auf einen Server der Hochschule vorgenommen.
|
||||
%
|
||||
\section*{17. Plakatgestaltung}
|
||||
\phantomsection\addcontentsline{toc}{section}{17. Plakatgestaltung}
|
||||
Zu dem Plakat für die OHM News App wurde eine Ideensammlung in Form von Skizzen angefertigt.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=6.5cm, angle=90, scale=1.409]{IMG_Skizze1.jpg}\quad
|
||||
\includegraphics[width=6.5cm]{IMG_Skizze2.jpg}
|
||||
\includegraphics[width=6.5cm, angle=270, scale=1.409]{IMG_Skizze3.jpg}\quad
|
||||
\includegraphics[width=6.5cm, angle=270, scale=1.409]{IMG_Skizze4.jpg}
|
||||
\end{figure}
|
||||
%
|
||||
Die Umsetzung derer folgte in Form von ersten Entwürfen in Illustrator, welche der gesamten Gruppe vorgestellt wurden. \\
|
||||
Zu den hier unten aufgeführten Plakatentwürfen wurden jeweils zwei Versionen erstellt. Diese zwei kamen jedoch in die engere Auswahl und sollten noch weiter ausgearbeitet werden.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat1.pdf}\quad
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat2.pdf}
|
||||
\end{figure}
|
||||
%
|
||||
Bei der nächsten Vorauswahl an fünf OHM News Plakat-Versionen wurde daraufhin auf zwei reduziert, welche hier zu sehen sind.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat3.pdf}\quad
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat4.pdf}
|
||||
\end{figure}
|
||||
%
|
||||
Diese wurden weiter bearbeitet und Änderungen in Absprache mit der Projektgruppe vor\-genommen. Auch die Meinung von Professor Dr. Hopf beeinflusste die Plakatgestaltung.\\
|
||||
Einige Ansätze später und nach etlichem Experimentieren stand die Endauswahl bei diesen nächsten zwei Exemplaren. Besonderen Zeitaufwand nahm die Suche nach einer geeigneten Schrift für die zweite Version in Anspruch. Es gestaltete sich als äußerst schwierig, den künstlerischen leicht verspielten Ausdruck des Plakatlayouts mit der Seriösität des Hochschulcharakters in einer Schrift zu vereinen.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat5.pdf}\quad
|
||||
\includegraphics[width=6.5cm]{PDF_Plakat6.pdf}
|
||||
\end{figure}
|
||||
%
|
||||
Zuletzt fiel die Wahl auf das linke mit blauem Verlauf versehene Plakat. Denn es vermittelt genau das, was der Slogan des Projektes aussagt. Der Fokus liegt auf der Nachrichtenbox, also das was wichtig ist, und der Rest verschwimmt im Hintergrund. \\
|
||||
Bei den wöchentlichen Treffen wurde im Allgemeinen der Fortschritt des Plakatdesigns analysiert und mit konstruktiver Kritik versehen. Dieses Feedback wurde im Rahmen des Möglichen umgesetzt und so kristallisierte sich die finale Version heraus. Nach gründlichem Finetuning und einer Umformatierung von DIN A3 auf DIN A1 wurde die Endfassung per Mail eingeschickt und schließlich ausgedruckt. Im Anhang ist sie in voller Auflösung aufzufinden.
|
||||
%
|
||||
\section*{18. PowerPoint Präsentation}
|
||||
\phantomsection\addcontentsline{toc}{section}{18. PowerPoint Präsentation}
|
||||
Als sich das Projekt für dieses Semester zum Ende hinneigte, war es an der Zeit sich für die Projektpräsentation vorzubereiten. Hierfür erstellte ich für die Gruppe eine PowerPoint Präsentation. Zunächst besprachen wir Gemeinschaftlich, wie diese ungefähr aussehen sollte. Wir waren alle einstimmig der Meinung, dass wir die Präsentation sehr einfach gestalten wollen, ohne zu lange Textpassagen mit einzubinden. Wir wollten es nämlich verhindern, dass das Publikum von zu vielen Faktoren in der Darstellung abgelenkt werden, zum Beispiel durch lesen von langem Fließtext. Durch den Gebrauch von bildlicher Veranschaulichung, versuchten wir es den Zuschauern zu ermöglichen, das Verständnis zu erleichtern.
|
||||
Auch hatten wir die Idee, eine fiktive Persona zu erstellen, zu dem der Betrachter einen Bezug finden kann und diese durch das vorgetragene Thema begleitet.
|
||||
%
|
||||
\subsection*{18.1. Gestaltungselemente}
|
||||
\phantomsection\addcontentsline{toc}{subsection}{18.1. Gestaltungselemente}
|
||||
Da man jedoch, aus Urheberrechtlichen Gründen, nicht einfach wahllos Charaktere aus dem Internet benutzen kann, suchte ich nach einer Seite, auf der man solche Animationen erstellen kann. Ich bin auch direkt fündig geworden, trotz alle dem war es erstmal schwer etwas zu finden das man auch Gratis verwenden konnte.
|
||||
Dann bin ich auf die Seite www.Powtoon.com gestoßen. Dort fing ich als nächstes an, unseren sogenannten Klaus in all den Stimmungen, die wir für unsere Präsentation brauchten, zu gestalten. \\
|
||||
Wir entschieden im Vorfeld als Gruppe, dass sich unser Männchen so wenig wie möglich bewegen soll, aus dem gleichen Grund wie auch oben schon erwähnt und zwar um den Fokus nicht zu sehr darauf zu richten und das Publikum nicht zu sehr abzulenken. Nachdem das erledigt war, war es an der Zeit, die eben erstellten Videos von unserer Persona einzeln so zu kürzen und zu beschneiden, dass man sie gut auf die gewünschte Position einsetzen konnte. Als dieses erledigt wurde, besprach ich weitere Vorgehen einzeln mit den anderen Gruppenmitgliedern. Ich Informierte mich darüber, über welches Thema jeder einzelne vorträgt und wie sie sich ihren Präsentationsteil vorstellen. Diese Wünsche und Vorstellung setzte ich dann dementsprechend in unserer Präsentation um.
|
||||
Falls sie an dem Ergebnis interessiert sind, haben sie die Möglichkeit sich dies im Git-Repository im Ordner ''presentation'' anzusehen.
|
||||
%
|
||||
\section*{19. Weiterverwendung für Infoscreens}
|
||||
\phantomsection\addcontentsline{toc}{section}{19. Weiterverwendung für Infoscreens}
|
||||
Am Mittwoch, den 24.10.2018 fand das Info-Treffen mit Frau Fabi statt, welches von Prof.Dr. \mbox{Matthias} Hopf organisiert wurde. Dieses Treffen diente der Besprechung und Erörterung zukünftiger Nutzungsmöglichkeiten der Info-Screens, das sind geplante und teils bereits montierte Bildschirme zur Information-Bereitstellung für die Hochschulangehörigen auf dem Campusgelände. Frau Fabi ist Angehörige der Fakultät efi und in ihrer Funktion für die Dokumentenlenkung und Webredaktion an dem ''Tag''-basiertem Nachrichten-System unserer Webanwendung interessiert, welches zukünftig auch auf den Bildschirmen dargestellt werden könnten. Sie ließ auch das Interesse von Herr Pöhlau, dem Dekan der Fakultät efi bekunden.\\
|
||||
Außerdem informierte Frau Fabi uns, die Projektmitglieder und unseren Projektbetreuer, dass die Fakultät efi sicher die restlichen Info-Screens montieren werde und derzeit Besprechungen hinsichtlich weiterer Sicherheitsaspekte zu den Montagebereichen am Laufen sind. Ergänzend würden sie sich eine Softwarelösung wünschen, für die Ansteuerung und ''Befüllung'' der Monitore mit den Daten unserer App. Diese wird jedoch nicht mehr im Rahmen unseres Projektes umgesetzt werden. Die Umsetzung einer Softwarelösung wäre als Idee für ein zukünftiges Projekt denkbar, nach Aussage von Prof.Dr. Matthias Hopf.
|
||||
%
|
||||
\section*{20. Soll/Ist Vergleich auf Basis des Projektplanes}
|
||||
\phantomsection\addcontentsline{toc}{section}{20. Soll/Ist Vergleich auf Basis des Projektplanes}
|
||||
Zu Beginn des Semesters hat die Gruppe zusammen ein Pflichtenheft für den ersten Abschnitt des Projekts erstellt. Ziel war es den Datenzugriff zu ermöglichen und eine Schnittstelle zur Verfügung zu stellen. Es besteht eine Datenbankanbindung über den Server der Technischen Hochschule Nürnberg. Darüber hinaus sollten die folgenden Ziele im Bereich der grafischen Benutzerschnittstelle erreicht werden.\\
|
||||
Die Oberfläche der PWA sollte über eine Login Möglichkeit, eine Menüleiste, eine Suchoption, ein Profil, eine Filterfunktion, ein Dashboard als Hauptseite, ein Einstellungsmenü, Nachrichtenfelder und ein Formular zum Verfassen einer Nachricht verfügen. Die Login Funktion ist noch nicht implementiert und die Filterfunktion soll im nächsten Semester in das Suchfeld und die Profilanzeige eingebaut werden. Die restlichen Funktionen sind in der PWA grafisch umgesetzt worden. Es sollte zusätzlich ein Abhängigkeitsdiagramm erstellt werden. Allerdings war dies aufgrund fehlender komplexer Zusammenhänge noch nicht notwendig. Für die API-Schnittstelle wurde eine Dokumentation erstellt, um den Überblick zu bewahren. Im Bereich der Anwendungslogik wurde das Routing, die Darstellung der Nachrichten, die Speicherung der Nachrichten in der Datenbank und der LDAP-Login besonders behandelt. Das Routing sowie die Erstellung, Speicherung und Darstellung der Nachrichten funktioniert. Die Login Funktion wurde noch nicht näher betrachtet. Codetests wurden bisher noch keine durchgeführt. Das Rollenkonzept der Nutzer wurde bereits besprochen, allerdings noch nicht umgesetzt.\\
|
||||
Darüber hinaus gibt noch einige nachrangige Punkte. Dazu gehört die Festlegung des Anwendungsnamens, die Erstellung eines Logos, das UX-Konzept, das Filtern der Datenbankabrufe, das Festlegen der Anzeigekriterien und die Funktion einem Kanal zu folgen. Wie oben bereits erwähnt wird das Filtern der Abrufe im nächsten Semester umgesetzt. Auch die Anzeigekriterien und die Möglichkeit einem Kanal zu folgen wird erst zu einem späteren Zeitpunkt möglich sein.
|
||||
%
|
||||
\section*{21. Fazit}
|
||||
\phantomsection\addcontentsline{toc}{section}{21. Fazit}
|
||||
Im ersten Projektabschnitt ist viel Zeit ist in der Konzeptionsphase vergangen, da es ein sehr iterativer Prozess ist und deshalb mehrere Durchläufe bis zum Endentwurf nötig waren. Verschiedene Meinungen mussten mit einbezogen werden. Doch ein gutes Konzept erspart am Ende viel Änderungsarbeit. \\
|
||||
Für die weitere Erarbeitung der App haben sich die Projektmitglieder auf die Bereiche Front\-end, Datenbank, Sever und Service-Worker aufgeteilt. Diese Aufgaben\-verteilung hat gut funktioniert. Trotzdem ist unser Team sehr oft ins Stocken geraten, da sich die Aufgaben\-bereiche gerade am Anfang oft überschnitten haben. Hinzukommt, dass wir insgesamt \mbox{wenig} Erfahrung in diesen Bereichen hatten. Wir haben uns deshalb zu Beginn intensiv in die Themen eingearbeitet, was länger dauerte als erwartet. Zusätzlich mussten wir auf \mbox{fachliche} Unterstützung zurückgreifen.\\\\
|
||||
Alles in einem kann man trotzdem von einem erfolgreichen Projektabschnitt sprechen. Ein erster funktionierender Prototyp ist fertig und kann im nächsten Zug erweitert werden. Parallele individuelle Arbeiten sind einfacher möglich, da das Grundgerüst steht. Das Team hat sich in die Materie eingearbeitet und kann im zweiten Projektabschnitt schneller durchstarten. Die Idee und das Konzept für die App sind soweit ausgereift, sodass diese nur noch umgesetzt werden müssen. Abläufe innerhalb der Gruppe sind klarer geworden, allerdings gibt es noch einiges strukturelle Abläufe, die im zweiten Projektabschnitt weiter optimiert werden können.
|
||||
%
|
||||
% Literaturverzeichnis
|
||||
\newpage
|
||||
\section*{Quellen- und Literaturverzeichnis}
|
||||
\phantomsection\addcontentsline{toc}{section}{Quellen- und Literaturverzeichnis}
|
||||
\medskip
|
||||
%\nocite{*} % Alle Inhalte zur Ausgabe markieren, nicht nur jene die zitiert wurden.
|
||||
{\setstretch{1.0}%
|
||||
\printbibliography[heading=none]}
|
||||
%
|
||||
\end{document}
|
@ -0,0 +1,171 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %%
|
||||
%% defaultPreamble.sty %%
|
||||
%% %%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %%
|
||||
%% Setup a preamble for document class: article %%
|
||||
%% 1.Pagesettings: %%
|
||||
%% - DIN A4 Paper %%
|
||||
%% - Margin: Top = 20mm %%
|
||||
%% Right = 20mm %%
|
||||
%% Bottom = 30mm %%
|
||||
%% Left = 20mm %%
|
||||
%% - Header Separation = 10mm %%
|
||||
%% - Footer Separation = 10mm %%
|
||||
%% - Paragraph Spacing = 1.5 * line height %%
|
||||
%% %%
|
||||
%% 2.Redefine Pagelayout %%
|
||||
%% - Remove printed page numbers on page 1. %%
|
||||
%% - Page 1+2 counts for the table of content. %%
|
||||
%% - Print the page numbering like "Seite" a "von" lastpage %%
|
||||
%% to the right bottom corner. %%
|
||||
%% %%
|
||||
%% 3.Contain Packages %%
|
||||
%% - geometry = Set page settings. %%
|
||||
%% - setspace = Set linespacing, prevent math formula %%
|
||||
%% streching. %%
|
||||
%% - pageslts = Get last page number. %%
|
||||
%% - fancyhr = Set header, footer and page layout. %%
|
||||
%% - babel = Set hyphenation rules to [ngerman]. %%
|
||||
%% - inputenc = Set input encoding to UTF-8 (Umlaute etc.). %%
|
||||
%% - ClearSans = Provide fontfamily ClearSans. %%
|
||||
%% - helvet = Set fontfamily to Helvetica (sans serif). %%
|
||||
%% - fontenc = Set font encoding to 8bit (support <,=,>,"). %%
|
||||
%% - xcolor = Provides support of font colors. %%
|
||||
%% - upquote = Provides support quotes in verbatim and listings. %%
|
||||
%% - listings = Provides support of indention and code colering. %%
|
||||
%% - float = Provides support of fiqures and environment float.%%
|
||||
%% - hyperref = Provides support of links (pdf anchor), URL. %%
|
||||
%% - graphicx = Provides support to add images. %%
|
||||
%% - tabularx = Provides advanced tabular support. %%
|
||||
%% - pdfpages = Provides support to include pdf pages. %%
|
||||
%% - amsmath = Provides advanced math typesetting support. %%
|
||||
%% - amsfonts = Provides advanced font typesetting support. %%
|
||||
%% - amssymb = Provides advanced symbol typesetting support. %%
|
||||
%% - blindtext = Provides support to use Lorem Ipsum text. %%
|
||||
%% - enumitem = Provides support change enum type in options. %%
|
||||
%% - biblatex = Set biblatex for citation and bibliography %%
|
||||
%% with biber as backend and the %%
|
||||
%% bibliography style 'ieee'. %%
|
||||
%% %%
|
||||
%% 4.Defines New Commands %%
|
||||
%% - \includePdf{filename} = Include a PDF file. %%
|
||||
%% - \bibfilename{file.bib} = Set bib file. %%
|
||||
%% - \printbib = Print bibliography. %%
|
||||
%% - \b{text} = Set text to bold format. %%
|
||||
%% - \mono{text} = Set text to monospace. %%
|
||||
%% - \minsep = Set item spacing to minimum. %%
|
||||
%% - \clear = Set fontfamily to ClearSans. %%
|
||||
%% Default fontfamily is Helvetica. %%
|
||||
%% %%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
\NeedsTeXFormat{LaTeX2e}%
|
||||
\ProvidesPackage{defaultPreamble}[2019/03/04 v1.4 DefaultPreamble Package from Erik Roemmelt]%
|
||||
\ProcessOptions\relax%
|
||||
%%% Packages %%%
|
||||
% ___Document___
|
||||
\RequirePackage[a4paper, left=20mm, right=20mm, top=20mm, bottom=30mm, headsep=10mm, footskip=10mm]{geometry} % Set page settings
|
||||
\RequirePackage[nodisplayskipstretch]{setspace} % Set linespacing and prevent math formula streching
|
||||
\setstretch{1.5} % Change typeset line spacing by multiplicator 1.0
|
||||
\RequirePackage[pagecontinue=false,alphMult=0,AlphMulti=0,fnsymbolmult=false,romanMult=false,RomanMulti=false]{pageslts} % Get last page number with \lastpageref{LastPage}
|
||||
\RequirePackage{fancyhdr} % Set header, footer and page layout.
|
||||
\pagestyle{fancy} % Set the pagestyle to fancyhdr settings
|
||||
%%% Fancyhdr Settings %%%
|
||||
\fancyhf{} % Clear all header and footer fields
|
||||
\fancyfoot[R]{\ifnum\value{page}<1\relax\else{Seite \thepage \hspace{1pt} von \lastpageref{VeryLastPage}}\fi} % Set page numbering "n / last" in the right field of footer
|
||||
\renewcommand{\headrulewidth}{0pt} % Set header ruler hidden
|
||||
\renewcommand{\footrulewidth}{0pt} % Set footer ruler hidden
|
||||
\fancypagestyle{plain}{% Redefine plain style
|
||||
\fancyhf{} % Clear all header and footer fields
|
||||
\fancyfoot[R]{\ifnum\value{page}<2\relax\else{Seite \thepage \hspace{1pt} von \lastpageref{VeryLastPage}}\fi} % Set page numbering "n / last" in the right field of footer, skip page numbering on page 1+2
|
||||
\renewcommand{\headrulewidth}{0pt} % Set header ruler hidden
|
||||
\renewcommand{\footrulewidth}{0pt} % Set footer ruler hidden
|
||||
}%
|
||||
% ___Font___
|
||||
\RequirePackage[ngerman]{babel} % Changes hyphenation rules
|
||||
\RequirePackage[utf8]{inputenc} % Input encoding: Unicode support (Umlaute etc.)
|
||||
\RequirePackage{ClearSans} % Provide fontfamily Clear Sans (sans serif) for title page
|
||||
\RequirePackage[scaled]{helvet} % Scales fontfamily Helvetica to .95 (sans serif)
|
||||
\renewcommand{\familydefault}{\sfdefault} % Changes default font to sans serif Helvetica
|
||||
%\RequirePackage[default]{sourcesanspro}
|
||||
%\RequirePackage[sfdefault]{FiraSans} % option 'sfdefault' activates Fira Sans as the default text font
|
||||
%\renewcommand*\oldstylenums[1]{{\firaoldstyle #1}}
|
||||
%\RequirePackage[sfdefault,light]{roboto} % Option 'sfdefault' only if the base font of the document is to be sans serif
|
||||
\RequirePackage[T1]{fontenc} % Font encoding: (8bit) Accents support (<,=,>,",...)
|
||||
\RequirePackage[dvipsnames]{xcolor} % Provides font coloring
|
||||
\definecolor{editorGray}{rgb}{0.95, 0.95, 0.95} % Defines a new Color: gray
|
||||
\definecolor{editorOcher}{rgb}{0.8, 0.4, 0} % #CC6600 -> rgb(204, 102, 0) % New Color Ocher
|
||||
\definecolor{editorGreen}{rgb}{0, 0.5, 0} % #007C00 -> rgb(0, 124, 0) % New Color Green
|
||||
\RequirePackage{upquote} % Allow quotes in verbatim and lstlisting
|
||||
\RequirePackage{listings} % Allow indention and code colering
|
||||
\lstdefinelanguage{JavaScript}{% Defines Javascript for lstlisting
|
||||
morekeywords={typeof,new,true,false,catch,function,return,null,catch,switch,var,if,in,while,do,else,case,break},morecomment=[s]{/*}{*/},morecomment=[l]//,morestring=[b]",morestring=[b]'}%
|
||||
\lstdefinelanguage{HTML5}{% Redefines HTML for lstlisting
|
||||
language=html,sensitive=true,alsoletter={<>=-},otherkeywords={% HTML tags
|
||||
<html>,<head>,<title>,</title>,<meta,/>,</head>,<body>,<canvas,\/canvas>,<script>,</script>,</body>,</html>,<!,html>,<style>,</style>,><},%
|
||||
ndkeywords={%
|
||||
% General
|
||||
=,%
|
||||
% HTML attributes
|
||||
charset=,id=,width=,height=,%
|
||||
% CSS properties
|
||||
border:,transform:,-moz-transform:,transition-duration:,transition-property:,transition-timing-function:},%
|
||||
morecomment=[s]{<!--}{-->},tag=[s]}%
|
||||
\newcommand{\lstsetdefault}{%
|
||||
\lstset{%
|
||||
% Basic design
|
||||
backgroundcolor=\color{editorGray},basicstyle={\small\ttfamily},frame=single,columns=fullflexible,%
|
||||
% Line numbers
|
||||
xleftmargin={0.75cm},numbers=left,stepnumber=1,firstnumber=1,numberfirstline=true,%
|
||||
% Code design
|
||||
keywordstyle=\color{blue}\bfseries,commentstyle=\color{darkgray}\ttfamily,ndkeywordstyle=\color{editorGreen}\bfseries,stringstyle=\color{editorOcher},%
|
||||
% Code
|
||||
language=HTML5,alsolanguage=JavaScript,alsodigit={.:;},tabsize=4,showtabs=false,showspaces=false,showstringspaces=false,extendedchars=true,breaklines=true,%
|
||||
% Support for German umlauts
|
||||
literate=%
|
||||
{Ö}{{\"O}}1%
|
||||
{Ä}{{\"A}}1%
|
||||
{Ü}{{\"U}}1%
|
||||
{ß}{{\ss}}1%
|
||||
{ü}{{\"u}}1%
|
||||
{ä}{{\"a}}1%
|
||||
{ö}{{\"o}}1%
|
||||
}}%
|
||||
\lstsetdefault%
|
||||
% ___Other___
|
||||
\RequirePackage{float} % Allow fiqures and enviroments to float
|
||||
\RequirePackage[hidelinks,pdfpagelabels=true]{hyperref} % Add a link to your document
|
||||
\RequirePackage{graphicx} % Add pictures to your document
|
||||
\RequirePackage{tabularx} % Advanced tabular support
|
||||
\RequirePackage{pdfpages} % Allows to include pdf pages
|
||||
\RequirePackage{amsmath} % Advanced math typesetting
|
||||
\RequirePackage{amsfonts} % Advanced font typesetting
|
||||
\RequirePackage{amssymb} % Advanced symoblic typesetting
|
||||
\RequirePackage{blindtext} % Blindtext, Lorem Ipsum text
|
||||
\RequirePackage[shortlabels]{enumitem} % Allows to change enumerate type easily
|
||||
% __Bibliography___
|
||||
\RequirePackage[backend=biber,style=ieee,sorting=nyt]{biblatex} % Use biblatex package
|
||||
%%% New Commands %%%
|
||||
% New command for closer spacing in list
|
||||
\newcommand{\minsep}{\topsep=0pt\itemsep=0pt\parsep=0pt\partopsep=0pt}%
|
||||
% Add new command to include a pdf file
|
||||
\newcommand*{\@includePdf}{%
|
||||
\PackageWarning{defaultPreamble}{PDF-File does not exist}%
|
||||
NoN%
|
||||
}%
|
||||
\newcommand{\includePdf}[1]{\includepdf[pages=-,fitpaper=true,frame=false,pagecommand=\thispagestyle{plain}]{#1}}% Insert the name of the pdf file
|
||||
% Add new command to set file name for *.bib file
|
||||
\newcommand*{\@bibfilename}{%
|
||||
\PackageWarning{defaultPreamble}{Bib-File-Name undefined}%
|
||||
NoN%
|
||||
}%
|
||||
\newcommand{\bibfilename}[1]{\addbibresource{#1}}% Insert the name of the BibLatex file
|
||||
% Add new command to print the bibliography
|
||||
\newcommand{\printbib}{\printbibliography[heading=bibintoc]}% Insert the name of the BibLatex file
|
||||
% Add new commant to shorten text format command: \textbf
|
||||
\renewcommand{\b}{\textbf}%
|
||||
% Add new commant to shorten text format command: \texttt
|
||||
\newcommand{\mono}{\texttt}%
|
||||
\endinput % Das ist das Ende von dieser .sty Datei
|
37
ldap_test.js
Normal file
@ -0,0 +1,37 @@
|
||||
// Terminal call: node server/ldap_test.js - needs VPN or eduroam
|
||||
const inquirer = require('inquirer'),
|
||||
ldap = require('./server/ldap_ohm.js');
|
||||
|
||||
inquirer.prompt([
|
||||
{
|
||||
name: 'username',
|
||||
type: 'input',
|
||||
message: 'Enter your VirtuOhm username:',
|
||||
validate: function( value ) {
|
||||
if (value.length) {
|
||||
return true;
|
||||
} else {
|
||||
return 'Please enter your username.';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'password',
|
||||
message: 'Enter your password:',
|
||||
validate: function(value) {
|
||||
if (value.length) {
|
||||
return true;
|
||||
} else {
|
||||
return 'Please enter your password.';
|
||||
}
|
||||
}
|
||||
}])
|
||||
.then(answers => {
|
||||
ldap.init(null);
|
||||
ldap.authorize(answers.username,answers.password,function(user) {
|
||||
console.log(JSON.stringify(user));
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
@ -1,20 +0,0 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
//const Schema = mongoose.Schema,
|
||||
//ObjectId = Schema.ObjectId;
|
||||
|
||||
const MessageSchema = mongoose.Schema({
|
||||
//_id: ObjectId,
|
||||
/*id: {
|
||||
type: String,
|
||||
getter: function(val) { return this._id.toString(); },
|
||||
unique: true
|
||||
},*/
|
||||
//id: {type: String, required: true},
|
||||
subject: { type: String, required: true },
|
||||
message: { type: String, required: true },
|
||||
user: { type: String, required: true },
|
||||
tag: {type: String },
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Message', MessageSchema);
|
22
mong.js
Normal file
@ -0,0 +1,22 @@
|
||||
var db = db.getSiblingDB('omdb');
|
||||
|
||||
// Delete all collections + all records
|
||||
db.messages.deleteMany({});
|
||||
db.tags.deleteMany({});
|
||||
db.users.deleteMany({});
|
||||
db.sessions.deleteMany({});
|
||||
|
||||
// Insert data in collections
|
||||
load('mong_msg.js');
|
||||
load('mong_tag.js');
|
||||
load('mong_usr.js');
|
||||
|
||||
// Print all collections + records count
|
||||
var collections = db.getCollectionNames();
|
||||
print('Collections inside the db:');
|
||||
for(var i = 0; i < collections.length; i++){
|
||||
var name = collections[i];
|
||||
|
||||
if(name.substr(0, 6) != 'system')
|
||||
print(name + ' - ' + db[name].count() + ' records');
|
||||
}
|
9
mong_msg.js
Normal file
@ -0,0 +1,9 @@
|
||||
db.messages.insert([
|
||||
{"subject":"DOLORE LABORIS AUTE","message":"Ex sunt elit elit in ex ad labore minim. Elit amet irure sit aliquip excepteur sit qui et aute qui mollit cillum.","user":"Jaime Potter","tag":["sit","in","dolore","ullamco"]},
|
||||
{"subject":"NON IPSUM MOLLIT","message":"Ut laborum proident magna magna qui non in voluptate reprehenderit labore. Qui consectetur dolor nisi culpa cillum quis.","user":"Goff Durham","tag":["aliqua","sunt","labore","minim"]},
|
||||
{"subject": "ESSE IPSUM INCIDIDUNT","message":"Esse enim amet laboris proident do do ut cupidatat laborum ex. Sit esse id laborum aliqua id.","user":"Helena Mercado","tag":["fugiat","nisi","incididunt","ullamco"]},
|
||||
{"subject":"PARIATUR DOLOR SUNT","message":"Exercitation officia ad consequat est voluptate est incididunt ut culpa consectetur. Consectetur irure veniam ipsum sint sit anim minim aute exercitation ullamco nostrud reprehenderit consequat.","user":"Christi Walker","tag":["consectetur","sint","qui","ipsum"]},
|
||||
{"subject":"TEMPOR ID VOLUPTATE","message":"Anim ex commodo officia consequat in magna esse sunt mollit sunt commodo. Ex sit aute reprehenderit elit magna sunt irure pariatur cupidatat labore.","user":"Kent Schroeder","tag":["adipisicing","nulla","tempor","veniam"]},
|
||||
{"subject":"LOREM EST AUTE","message":"Irure excepteur laborum quis tempor officia cillum officia est ea adipisicing duis enim aliqua. Est dolor laborum officia elit ullamco.","user":"Dominguez Stevens","tag":["mollit","amet","consectetur","dolore"]},
|
||||
{"subject":"ESSE MOLLIT CILLUM","message":"Eu culpa laborum consequat sunt aliqua excepteur. Voluptate pariatur deserunt consequat id nostrud do magna occaecat sint nulla non nostrud.","user":"Terrell Padilla","tag":["Lorem","consequat","fugiat","aliqua"]}
|
||||
])
|
3
mong_tag.js
Normal file
@ -0,0 +1,3 @@
|
||||
db.tags.insert([
|
||||
{"name":"efi"},{"name":"wichtig"},{"name":"Wintersemester19/20"},{"name":"Rückmeldung"},{"name":"bme6"},{"name":"Mkz"},{"name":"Freizeit"},{"name":"Prüfungsanmeldung"},{"name":"THNürnberg"},{"name":"Prüfung"},{"name":"Stundenplan"}
|
||||
])
|
11
mong_usr.js
Normal file
@ -0,0 +1,11 @@
|
||||
db.users.insert([
|
||||
// User: author, Pwd: author
|
||||
{"_id":"author","name":"Author","type":"MA@EFI;","roles":'{"user":true,"author":true}',"hash":"sha256","salt":"SIzKNsNKsCRVr8a9U90q6A==","pwd":"HZly68TSAKHioz6Kz0QCbXVTHpT6hMmabUbFYVlCMeE=","abos":["nulla","tempor","veniam","ipsum"],"bookmarks":[],},
|
||||
// User: admin, Pwd: SwenMho
|
||||
{"_id":"admin","name":"Test Admin","type":"MA@AMP;","roles":'{"user":true,"author":true,"admin":true}',"hash":"sha256","salt":"z3PNXGmQaWvaT7m2ZlT+0w==","pwd":"nfUfNv032J745xj3Hzya3Mkk43Dz/H0BmNTZhtx8UM0=","abos":["veniam","ipsum"],"bookmarks":[],},
|
||||
])
|
||||
|
||||
//var c = require('./server/crypto.js'),
|
||||
// e = {"_id":"writer","hash":"sha256"};
|
||||
//c.fillLocalAuth(e,"pwd");
|
||||
//console.info(JSON.stringify(e));
|
@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
url: 'mongodb://localhost:27017/mydb'
|
||||
}
|
1
node_modules/.bin/acorn
generated
vendored
@ -1 +0,0 @@
|
||||
../acorn/bin/acorn
|
1
node_modules/.bin/bunyan
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../bunyan/bin/bunyan
|
1
node_modules/.bin/eslint
generated
vendored
@ -1 +0,0 @@
|
||||
../eslint/bin/eslint.js
|
1
node_modules/.bin/esparse
generated
vendored
@ -1 +0,0 @@
|
||||
../esprima/bin/esparse.js
|
1
node_modules/.bin/esvalidate
generated
vendored
@ -1 +0,0 @@
|
||||
../esprima/bin/esvalidate.js
|
1
node_modules/.bin/js-yaml
generated
vendored
@ -1 +0,0 @@
|
||||
../js-yaml/bin/js-yaml.js
|
1
node_modules/.bin/ldapjs-add
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ldapjs/bin/ldapjs-add
|
1
node_modules/.bin/ldapjs-compare
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ldapjs/bin/ldapjs-compare
|
1
node_modules/.bin/ldapjs-delete
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ldapjs/bin/ldapjs-delete
|
1
node_modules/.bin/ldapjs-modify
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ldapjs/bin/ldapjs-modify
|
1
node_modules/.bin/ldapjs-search
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ldapjs/bin/ldapjs-search
|
1
node_modules/.bin/ncp
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ncp/bin/ncp
|
1
node_modules/.bin/which
generated
vendored
@ -1 +0,0 @@
|
||||
../which/bin/which
|
22
node_modules/@babel/code-frame/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-2018 Sebastian McKenzie <sebmck@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
19
node_modules/@babel/code-frame/README.md
generated
vendored
@ -1,19 +0,0 @@
|
||||
# @babel/code-frame
|
||||
|
||||
> Generate errors that contain a code frame that point to source locations.
|
||||
|
||||
See our website [@babel/code-frame](https://babeljs.io/docs/en/next/babel-code-frame.html) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/code-frame
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/code-frame --dev
|
||||
```
|
173
node_modules/@babel/code-frame/lib/index.js
generated
vendored
@ -1,173 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.codeFrameColumns = codeFrameColumns;
|
||||
exports.default = _default;
|
||||
|
||||
function _highlight() {
|
||||
const data = _interopRequireWildcard(require("@babel/highlight"));
|
||||
|
||||
_highlight = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
let deprecationWarningShown = false;
|
||||
|
||||
function getDefs(chalk) {
|
||||
return {
|
||||
gutter: chalk.grey,
|
||||
marker: chalk.red.bold,
|
||||
message: chalk.red.bold
|
||||
};
|
||||
}
|
||||
|
||||
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||
|
||||
function getMarkerLines(loc, source, opts) {
|
||||
const startLoc = Object.assign({
|
||||
column: 0,
|
||||
line: -1
|
||||
}, loc.start);
|
||||
const endLoc = Object.assign({}, startLoc, loc.end);
|
||||
const {
|
||||
linesAbove = 2,
|
||||
linesBelow = 3
|
||||
} = opts || {};
|
||||
const startLine = startLoc.line;
|
||||
const startColumn = startLoc.column;
|
||||
const endLine = endLoc.line;
|
||||
const endColumn = endLoc.column;
|
||||
let start = Math.max(startLine - (linesAbove + 1), 0);
|
||||
let end = Math.min(source.length, endLine + linesBelow);
|
||||
|
||||
if (startLine === -1) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (endLine === -1) {
|
||||
end = source.length;
|
||||
}
|
||||
|
||||
const lineDiff = endLine - startLine;
|
||||
const markerLines = {};
|
||||
|
||||
if (lineDiff) {
|
||||
for (let i = 0; i <= lineDiff; i++) {
|
||||
const lineNumber = i + startLine;
|
||||
|
||||
if (!startColumn) {
|
||||
markerLines[lineNumber] = true;
|
||||
} else if (i === 0) {
|
||||
const sourceLength = source[lineNumber - 1].length;
|
||||
markerLines[lineNumber] = [startColumn, sourceLength - startColumn];
|
||||
} else if (i === lineDiff) {
|
||||
markerLines[lineNumber] = [0, endColumn];
|
||||
} else {
|
||||
const sourceLength = source[lineNumber - i].length;
|
||||
markerLines[lineNumber] = [0, sourceLength];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (startColumn === endColumn) {
|
||||
if (startColumn) {
|
||||
markerLines[startLine] = [startColumn, 0];
|
||||
} else {
|
||||
markerLines[startLine] = true;
|
||||
}
|
||||
} else {
|
||||
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
start,
|
||||
end,
|
||||
markerLines
|
||||
};
|
||||
}
|
||||
|
||||
function codeFrameColumns(rawLines, loc, opts = {}) {
|
||||
const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight().shouldHighlight)(opts);
|
||||
const chalk = (0, _highlight().getChalk)(opts);
|
||||
const defs = getDefs(chalk);
|
||||
|
||||
const maybeHighlight = (chalkFn, string) => {
|
||||
return highlighted ? chalkFn(string) : string;
|
||||
};
|
||||
|
||||
if (highlighted) rawLines = (0, _highlight().default)(rawLines, opts);
|
||||
const lines = rawLines.split(NEWLINE);
|
||||
const {
|
||||
start,
|
||||
end,
|
||||
markerLines
|
||||
} = getMarkerLines(loc, lines, opts);
|
||||
const hasColumns = loc.start && typeof loc.start.column === "number";
|
||||
const numberMaxWidth = String(end).length;
|
||||
let frame = lines.slice(start, end).map((line, index) => {
|
||||
const number = start + 1 + index;
|
||||
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
|
||||
const gutter = ` ${paddedNumber} | `;
|
||||
const hasMarker = markerLines[number];
|
||||
const lastMarkerLine = !markerLines[number + 1];
|
||||
|
||||
if (hasMarker) {
|
||||
let markerLine = "";
|
||||
|
||||
if (Array.isArray(hasMarker)) {
|
||||
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
||||
const numberOfMarkers = hasMarker[1] || 1;
|
||||
markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join("");
|
||||
|
||||
if (lastMarkerLine && opts.message) {
|
||||
markerLine += " " + maybeHighlight(defs.message, opts.message);
|
||||
}
|
||||
}
|
||||
|
||||
return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join("");
|
||||
} else {
|
||||
return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
|
||||
}
|
||||
}).join("\n");
|
||||
|
||||
if (opts.message && !hasColumns) {
|
||||
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
|
||||
}
|
||||
|
||||
if (highlighted) {
|
||||
return chalk.reset(frame);
|
||||
} else {
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
function _default(rawLines, lineNumber, colNumber, opts = {}) {
|
||||
if (!deprecationWarningShown) {
|
||||
deprecationWarningShown = true;
|
||||
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
|
||||
|
||||
if (process.emitWarning) {
|
||||
process.emitWarning(message, "DeprecationWarning");
|
||||
} else {
|
||||
const deprecationError = new Error(message);
|
||||
deprecationError.name = "DeprecationWarning";
|
||||
console.warn(new Error(message));
|
||||
}
|
||||
}
|
||||
|
||||
colNumber = Math.max(colNumber, 0);
|
||||
const location = {
|
||||
start: {
|
||||
column: colNumber,
|
||||
line: lineNumber
|
||||
}
|
||||
};
|
||||
return codeFrameColumns(rawLines, location, opts);
|
||||
}
|
49
node_modules/@babel/code-frame/package.json
generated
vendored
@ -1,49 +0,0 @@
|
||||
{
|
||||
"_from": "@babel/code-frame@^7.0.0",
|
||||
"_id": "@babel/code-frame@7.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
|
||||
"_location": "/@babel/code-frame",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "@babel/code-frame@^7.0.0",
|
||||
"name": "@babel/code-frame",
|
||||
"escapedName": "@babel%2fcode-frame",
|
||||
"scope": "@babel",
|
||||
"rawSpec": "^7.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^7.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/eslint"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
|
||||
"_shasum": "06e2ab19bdb535385559aabb5ba59729482800f8",
|
||||
"_spec": "@babel/code-frame@^7.0.0",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/BME_Project_Ohm/om/node_modules/eslint",
|
||||
"author": {
|
||||
"name": "Sebastian McKenzie",
|
||||
"email": "sebmck@gmail.com"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.0.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Generate errors that contain a code frame that point to source locations.",
|
||||
"devDependencies": {
|
||||
"chalk": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
},
|
||||
"homepage": "https://babeljs.io/",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "@babel/code-frame",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel/tree/master/packages/babel-code-frame"
|
||||
},
|
||||
"version": "7.0.0"
|
||||
}
|
22
node_modules/@babel/highlight/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-2018 Sebastian McKenzie <sebmck@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
19
node_modules/@babel/highlight/README.md
generated
vendored
@ -1,19 +0,0 @@
|
||||
# @babel/highlight
|
||||
|
||||
> Syntax highlight JavaScript strings for output in terminals.
|
||||
|
||||
See our website [@babel/highlight](https://babeljs.io/docs/en/next/babel-highlight.html) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/highlight
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/highlight --dev
|
||||
```
|
129
node_modules/@babel/highlight/lib/index.js
generated
vendored
@ -1,129 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.shouldHighlight = shouldHighlight;
|
||||
exports.getChalk = getChalk;
|
||||
exports.default = highlight;
|
||||
|
||||
function _jsTokens() {
|
||||
const data = _interopRequireWildcard(require("js-tokens"));
|
||||
|
||||
_jsTokens = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _esutils() {
|
||||
const data = _interopRequireDefault(require("esutils"));
|
||||
|
||||
_esutils = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _chalk() {
|
||||
const data = _interopRequireDefault(require("chalk"));
|
||||
|
||||
_chalk = function () {
|
||||
return data;
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function getDefs(chalk) {
|
||||
return {
|
||||
keyword: chalk.cyan,
|
||||
capitalized: chalk.yellow,
|
||||
jsx_tag: chalk.yellow,
|
||||
punctuator: chalk.yellow,
|
||||
number: chalk.magenta,
|
||||
string: chalk.green,
|
||||
regex: chalk.magenta,
|
||||
comment: chalk.grey,
|
||||
invalid: chalk.white.bgRed.bold
|
||||
};
|
||||
}
|
||||
|
||||
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||
const JSX_TAG = /^[a-z][\w-]*$/i;
|
||||
const BRACKET = /^[()[\]{}]$/;
|
||||
|
||||
function getTokenType(match) {
|
||||
const [offset, text] = match.slice(-2);
|
||||
const token = (0, _jsTokens().matchToToken)(match);
|
||||
|
||||
if (token.type === "name") {
|
||||
if (_esutils().default.keyword.isReservedWordES6(token.value)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == "</")) {
|
||||
return "jsx_tag";
|
||||
}
|
||||
|
||||
if (token.value[0] !== token.value[0].toLowerCase()) {
|
||||
return "capitalized";
|
||||
}
|
||||
}
|
||||
|
||||
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
||||
return "bracket";
|
||||
}
|
||||
|
||||
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
||||
return "punctuator";
|
||||
}
|
||||
|
||||
return token.type;
|
||||
}
|
||||
|
||||
function highlightTokens(defs, text) {
|
||||
return text.replace(_jsTokens().default, function (...args) {
|
||||
const type = getTokenType(args);
|
||||
const colorize = defs[type];
|
||||
|
||||
if (colorize) {
|
||||
return args[0].split(NEWLINE).map(str => colorize(str)).join("\n");
|
||||
} else {
|
||||
return args[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function shouldHighlight(options) {
|
||||
return _chalk().default.supportsColor || options.forceColor;
|
||||
}
|
||||
|
||||
function getChalk(options) {
|
||||
let chalk = _chalk().default;
|
||||
|
||||
if (options.forceColor) {
|
||||
chalk = new (_chalk().default.constructor)({
|
||||
enabled: true,
|
||||
level: 1
|
||||
});
|
||||
}
|
||||
|
||||
return chalk;
|
||||
}
|
||||
|
||||
function highlight(code, options = {}) {
|
||||
if (shouldHighlight(options)) {
|
||||
const chalk = getChalk(options);
|
||||
const defs = getDefs(chalk);
|
||||
return highlightTokens(defs, code);
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
}
|
50
node_modules/@babel/highlight/package.json
generated
vendored
@ -1,50 +0,0 @@
|
||||
{
|
||||
"_from": "@babel/highlight@^7.0.0",
|
||||
"_id": "@babel/highlight@7.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
|
||||
"_location": "/@babel/highlight",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "@babel/highlight@^7.0.0",
|
||||
"name": "@babel/highlight",
|
||||
"escapedName": "@babel%2fhighlight",
|
||||
"scope": "@babel",
|
||||
"rawSpec": "^7.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^7.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/@babel/code-frame"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
|
||||
"_shasum": "f710c38c8d458e6dd9a201afb637fcb781ce99e4",
|
||||
"_spec": "@babel/highlight@^7.0.0",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/BME_Project_Ohm/om/node_modules/@babel/code-frame",
|
||||
"author": {
|
||||
"name": "suchipi",
|
||||
"email": "me@suchipi.com"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Syntax highlight JavaScript strings for output in terminals.",
|
||||
"devDependencies": {
|
||||
"strip-ansi": "^4.0.0"
|
||||
},
|
||||
"homepage": "https://babeljs.io/",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "@babel/highlight",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel/tree/master/packages/babel-highlight"
|
||||
},
|
||||
"version": "7.0.0"
|
||||
}
|
12
node_modules/accepts/HISTORY.md
generated
vendored
@ -1,3 +1,15 @@
|
||||
1.3.7 / 2019-04-29
|
||||
==================
|
||||
|
||||
* deps: negotiator@0.6.2
|
||||
- Fix sorting charset, encoding, and language with extra parameters
|
||||
|
||||
1.3.6 / 2019-04-28
|
||||
==================
|
||||
|
||||
* deps: mime-types@~2.1.24
|
||||
- deps: mime-db@~1.40.0
|
||||
|
||||
1.3.5 / 2018-02-28
|
||||
==================
|
||||
|
||||
|
19
node_modules/accepts/README.md
generated
vendored
@ -1,7 +1,7 @@
|
||||
# accepts
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
@ -131,13 +131,12 @@ curl -I -H'Accept: text/html' http://localhost:3000/
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/accepts.svg
|
||||
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master
|
||||
[node-version-image]: https://badgen.net/npm/node/accepts
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[npm-downloads-image]: https://badgen.net/npm/dm/accepts
|
||||
[npm-url]: https://npmjs.org/package/accepts
|
||||
[node-version-image]: https://img.shields.io/node/v/accepts.svg
|
||||
[node-version-url]: https://nodejs.org/en/download/
|
||||
[travis-image]: https://img.shields.io/travis/jshttp/accepts/master.svg
|
||||
[npm-version-image]: https://badgen.net/npm/v/accepts
|
||||
[travis-image]: https://badgen.net/travis/jshttp/accepts/master
|
||||
[travis-url]: https://travis-ci.org/jshttp/accepts
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/accepts/master.svg
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/accepts
|
||||
[downloads-image]: https://img.shields.io/npm/dm/accepts.svg
|
||||
[downloads-url]: https://npmjs.org/package/accepts
|
||||
|
49
node_modules/accepts/package.json
generated
vendored
@ -1,27 +1,27 @@
|
||||
{
|
||||
"_from": "accepts@~1.3.5",
|
||||
"_id": "accepts@1.3.5",
|
||||
"_from": "accepts@~1.3.7",
|
||||
"_id": "accepts@1.3.7",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
|
||||
"_integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"_location": "/accepts",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "accepts@~1.3.5",
|
||||
"raw": "accepts@~1.3.7",
|
||||
"name": "accepts",
|
||||
"escapedName": "accepts",
|
||||
"rawSpec": "~1.3.5",
|
||||
"rawSpec": "~1.3.7",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "~1.3.5"
|
||||
"fetchSpec": "~1.3.7"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/express"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
||||
"_shasum": "eb777df6011723a3b14e8a72c0805c8e86746bd2",
|
||||
"_spec": "accepts@~1.3.5",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/BME_Project_Ohm/om/node_modules/express",
|
||||
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"_shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd",
|
||||
"_spec": "accepts@~1.3.7",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/a1_BME_Project_Ohm/om/node_modules/express",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jshttp/accepts/issues"
|
||||
},
|
||||
@ -38,21 +38,22 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.18",
|
||||
"negotiator": "0.6.1"
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Higher-level content negotiation",
|
||||
"devDependencies": {
|
||||
"eslint": "4.18.1",
|
||||
"eslint-config-standard": "11.0.0",
|
||||
"eslint-plugin-import": "2.9.0",
|
||||
"eslint-plugin-markdown": "1.0.0-beta.6",
|
||||
"eslint-plugin-node": "6.0.1",
|
||||
"eslint-plugin-promise": "3.6.0",
|
||||
"eslint-plugin-standard": "3.0.1",
|
||||
"istanbul": "0.4.5",
|
||||
"mocha": "~1.21.5"
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint": "5.16.0",
|
||||
"eslint-config-standard": "12.0.0",
|
||||
"eslint-plugin-import": "2.17.2",
|
||||
"eslint-plugin-markdown": "1.0.0",
|
||||
"eslint-plugin-node": "8.0.1",
|
||||
"eslint-plugin-promise": "4.1.1",
|
||||
"eslint-plugin-standard": "4.0.0",
|
||||
"mocha": "6.1.4",
|
||||
"nyc": "14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -78,8 +79,8 @@
|
||||
"scripts": {
|
||||
"lint": "eslint --plugin markdown --ext js,md .",
|
||||
"test": "mocha --reporter spec --check-leaks --bail test/",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
|
||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
|
||||
"test-cov": "nyc --reporter=html --reporter=text npm test",
|
||||
"test-travis": "nyc --reporter=text npm test"
|
||||
},
|
||||
"version": "1.3.5"
|
||||
"version": "1.3.7"
|
||||
}
|
||||
|
19
node_modules/acorn-jsx/LICENSE
generated
vendored
@ -1,19 +0,0 @@
|
||||
Copyright (C) 2012-2017 by Ingvar Stepanyan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
44
node_modules/acorn-jsx/README.md
generated
vendored
@ -1,44 +0,0 @@
|
||||
# Acorn-JSX
|
||||
|
||||
[](https://travis-ci.org/RReverser/acorn-jsx)
|
||||
[](https://www.npmjs.org/package/acorn-jsx)
|
||||
|
||||
This is plugin for [Acorn](http://marijnhaverbeke.nl/acorn/) - a tiny, fast JavaScript parser, written completely in JavaScript.
|
||||
|
||||
It was created as an experimental alternative, faster [React.js JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) parser.
|
||||
|
||||
According to [benchmarks](https://github.com/RReverser/acorn-jsx/blob/master/test/bench.html), Acorn-JSX is 2x faster than official [Esprima-based parser](https://github.com/facebook/esprima) when location tracking is turned on in both (call it "source maps enabled mode"). At the same time, it consumes all the ES6+JSX syntax that can be consumed by Esprima-FB (this is proved by [official tests](https://github.com/RReverser/acorn-jsx/blob/master/test/tests-jsx.js)).
|
||||
|
||||
**UPDATE [14-Apr-2015]**: Facebook implementation started [deprecation process](https://github.com/facebook/esprima/issues/111) in favor of Acorn + Acorn-JSX + Babel for parsing and transpiling JSX syntax.
|
||||
|
||||
## Transpiler
|
||||
|
||||
Please note that this tool only parses source code to JSX AST, which is useful for various language tools and services. If you want to transpile your code to regular ES5-compliant JavaScript with source map, check out the [babel transpiler](https://babeljs.io/) which uses `acorn-jsx` under the hood.
|
||||
|
||||
## Usage
|
||||
|
||||
Requiring this module provides you with an Acorn plugin that you can use like this:
|
||||
|
||||
```javascript
|
||||
var acorn = require("acorn");
|
||||
var jsx = require("acorn-jsx");
|
||||
acorn.Parser.extend(jsx()).parse("my(<jsx/>, 'code');");
|
||||
```
|
||||
|
||||
Note that official spec doesn't support mix of XML namespaces and object-style access in tag names (#27) like in `<namespace:Object.Property />`, so it was deprecated in `acorn-jsx@3.0`. If you still want to opt-in to support of such constructions, you can pass the following option:
|
||||
|
||||
```javascript
|
||||
acorn.Parser.extend(jsx({ allowNamespacedObjects: true }))
|
||||
```
|
||||
|
||||
Also, since most apps use pure React transformer, a new option was introduced that allows to prohibit namespaces completely:
|
||||
|
||||
```javascript
|
||||
acorn.Parser.extend(jsx({ allowNamespaces: false }))
|
||||
```
|
||||
|
||||
Note that by default `allowNamespaces` is enabled for spec compliancy.
|
||||
|
||||
## License
|
||||
|
||||
This plugin is issued under the [MIT license](./LICENSE).
|
441
node_modules/acorn-jsx/index.js
generated
vendored
@ -1,441 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const XHTMLEntities = require('./xhtml');
|
||||
|
||||
const hexNumber = /^[\da-fA-F]+$/;
|
||||
const decimalNumber = /^\d+$/;
|
||||
|
||||
const acorn = require("acorn");
|
||||
const tt = acorn.tokTypes;
|
||||
const TokContext = acorn.TokContext;
|
||||
const tokContexts = acorn.tokContexts;
|
||||
const TokenType = acorn.TokenType;
|
||||
const isNewLine = acorn.isNewLine;
|
||||
const isIdentifierStart = acorn.isIdentifierStart;
|
||||
const isIdentifierChar = acorn.isIdentifierChar;
|
||||
|
||||
const tc_oTag = new TokContext('<tag', false);
|
||||
const tc_cTag = new TokContext('</tag', false);
|
||||
const tc_expr = new TokContext('<tag>...</tag>', true, true);
|
||||
|
||||
const tok = {
|
||||
jsxName: new TokenType('jsxName'),
|
||||
jsxText: new TokenType('jsxText', {beforeExpr: true}),
|
||||
jsxTagStart: new TokenType('jsxTagStart'),
|
||||
jsxTagEnd: new TokenType('jsxTagEnd')
|
||||
}
|
||||
|
||||
tok.jsxTagStart.updateContext = function() {
|
||||
this.context.push(tc_expr); // treat as beginning of JSX expression
|
||||
this.context.push(tc_oTag); // start opening tag context
|
||||
this.exprAllowed = false;
|
||||
};
|
||||
tok.jsxTagEnd.updateContext = function(prevType) {
|
||||
let out = this.context.pop();
|
||||
if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) {
|
||||
this.context.pop();
|
||||
this.exprAllowed = this.curContext() === tc_expr;
|
||||
} else {
|
||||
this.exprAllowed = true;
|
||||
}
|
||||
};
|
||||
|
||||
// Transforms JSX element name to string.
|
||||
|
||||
function getQualifiedJSXName(object) {
|
||||
if (!object)
|
||||
return object;
|
||||
|
||||
if (object.type === 'JSXIdentifier')
|
||||
return object.name;
|
||||
|
||||
if (object.type === 'JSXNamespacedName')
|
||||
return object.namespace.name + ':' + object.name.name;
|
||||
|
||||
if (object.type === 'JSXMemberExpression')
|
||||
return getQualifiedJSXName(object.object) + '.' +
|
||||
getQualifiedJSXName(object.property);
|
||||
}
|
||||
|
||||
module.exports = function(options) {
|
||||
options = options || {};
|
||||
return function(Parser) {
|
||||
return plugin({
|
||||
allowNamespaces: options.allowNamespaces !== false,
|
||||
allowNamespacedObjects: !!options.allowNamespacedObjects
|
||||
}, Parser);
|
||||
}
|
||||
};
|
||||
module.exports.tokTypes = tok;
|
||||
|
||||
function plugin(options, Parser) {
|
||||
return class extends Parser {
|
||||
// Reads inline JSX contents token.
|
||||
jsx_readToken() {
|
||||
let out = '', chunkStart = this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated JSX contents');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
|
||||
switch (ch) {
|
||||
case 60: // '<'
|
||||
case 123: // '{'
|
||||
if (this.pos === this.start) {
|
||||
if (ch === 60 && this.exprAllowed) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return this.getTokenFromCode(ch);
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
return this.finishToken(tok.jsxText, out);
|
||||
|
||||
case 38: // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(true);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsx_readNewLine(normalizeCRLF) {
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
let out;
|
||||
++this.pos;
|
||||
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
|
||||
++this.pos;
|
||||
out = normalizeCRLF ? '\n' : '\r\n';
|
||||
} else {
|
||||
out = String.fromCharCode(ch);
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine;
|
||||
this.lineStart = this.pos;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
jsx_readString(quote) {
|
||||
let out = '', chunkStart = ++this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated string constant');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === 38) { // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
} else if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(false);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos++);
|
||||
return this.finishToken(tt.string, out);
|
||||
}
|
||||
|
||||
jsx_readEntity() {
|
||||
let str = '', count = 0, entity;
|
||||
let ch = this.input[this.pos];
|
||||
if (ch !== '&')
|
||||
this.raise(this.pos, 'Entity must start with an ampersand');
|
||||
let startPos = ++this.pos;
|
||||
while (this.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.pos++];
|
||||
if (ch === ';') {
|
||||
if (str[0] === '#') {
|
||||
if (str[1] === 'x') {
|
||||
str = str.substr(2);
|
||||
if (hexNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 16));
|
||||
} else {
|
||||
str = str.substr(1);
|
||||
if (decimalNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 10));
|
||||
}
|
||||
} else {
|
||||
entity = XHTMLEntities[str];
|
||||
}
|
||||
break;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
if (!entity) {
|
||||
this.pos = startPos;
|
||||
return '&';
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Read a JSX identifier (valid tag or attribute name).
|
||||
//
|
||||
// Optimized version since JSX identifiers can't contain
|
||||
// escape characters and so can be read as single slice.
|
||||
// Also assumes that first character was already checked
|
||||
// by isIdentifierStart in readToken.
|
||||
|
||||
jsx_readWord() {
|
||||
let ch, start = this.pos;
|
||||
do {
|
||||
ch = this.input.charCodeAt(++this.pos);
|
||||
} while (isIdentifierChar(ch) || ch === 45); // '-'
|
||||
return this.finishToken(tok.jsxName, this.input.slice(start, this.pos));
|
||||
}
|
||||
|
||||
// Parse next token as JSX identifier
|
||||
|
||||
jsx_parseIdentifier() {
|
||||
let node = this.startNode();
|
||||
if (this.type === tok.jsxName)
|
||||
node.name = this.value;
|
||||
else if (this.type.keyword)
|
||||
node.name = this.type.keyword;
|
||||
else
|
||||
this.unexpected();
|
||||
this.next();
|
||||
return this.finishNode(node, 'JSXIdentifier');
|
||||
}
|
||||
|
||||
// Parse namespaced identifier.
|
||||
|
||||
jsx_parseNamespacedName() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let name = this.jsx_parseIdentifier();
|
||||
if (!options.allowNamespaces || !this.eat(tt.colon)) return name;
|
||||
var node = this.startNodeAt(startPos, startLoc);
|
||||
node.namespace = name;
|
||||
node.name = this.jsx_parseIdentifier();
|
||||
return this.finishNode(node, 'JSXNamespacedName');
|
||||
}
|
||||
|
||||
// Parses element name in any form - namespaced, member
|
||||
// or single identifier.
|
||||
|
||||
jsx_parseElementName() {
|
||||
if (this.type === tok.jsxTagEnd) return '';
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let node = this.jsx_parseNamespacedName();
|
||||
if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) {
|
||||
this.unexpected();
|
||||
}
|
||||
while (this.eat(tt.dot)) {
|
||||
let newNode = this.startNodeAt(startPos, startLoc);
|
||||
newNode.object = node;
|
||||
newNode.property = this.jsx_parseIdentifier();
|
||||
node = this.finishNode(newNode, 'JSXMemberExpression');
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses any type of JSX attribute value.
|
||||
|
||||
jsx_parseAttributeValue() {
|
||||
switch (this.type) {
|
||||
case tt.braceL:
|
||||
let node = this.jsx_parseExpressionContainer();
|
||||
if (node.expression.type === 'JSXEmptyExpression')
|
||||
this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
|
||||
return node;
|
||||
|
||||
case tok.jsxTagStart:
|
||||
case tt.string:
|
||||
return this.parseExprAtom();
|
||||
|
||||
default:
|
||||
this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
|
||||
}
|
||||
}
|
||||
|
||||
// JSXEmptyExpression is unique type since it doesn't actually parse anything,
|
||||
// and so it should start at the end of last read token (left brace) and finish
|
||||
// at the beginning of the next one (right brace).
|
||||
|
||||
jsx_parseEmptyExpression() {
|
||||
let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
|
||||
return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
|
||||
}
|
||||
|
||||
// Parses JSX expression enclosed into curly brackets.
|
||||
|
||||
jsx_parseExpressionContainer() {
|
||||
let node = this.startNode();
|
||||
this.next();
|
||||
node.expression = this.type === tt.braceR
|
||||
? this.jsx_parseEmptyExpression()
|
||||
: this.parseExpression();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXExpressionContainer');
|
||||
}
|
||||
|
||||
// Parses following JSX attribute name-value pair.
|
||||
|
||||
jsx_parseAttribute() {
|
||||
let node = this.startNode();
|
||||
if (this.eat(tt.braceL)) {
|
||||
this.expect(tt.ellipsis);
|
||||
node.argument = this.parseMaybeAssign();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXSpreadAttribute');
|
||||
}
|
||||
node.name = this.jsx_parseNamespacedName();
|
||||
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
|
||||
return this.finishNode(node, 'JSXAttribute');
|
||||
}
|
||||
|
||||
// Parses JSX opening tag starting after '<'.
|
||||
|
||||
jsx_parseOpeningElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
node.attributes = [];
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
while (this.type !== tt.slash && this.type !== tok.jsxTagEnd)
|
||||
node.attributes.push(this.jsx_parseAttribute());
|
||||
node.selfClosing = this.eat(tt.slash);
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment');
|
||||
}
|
||||
|
||||
// Parses JSX closing tag starting after '</'.
|
||||
|
||||
jsx_parseClosingElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment');
|
||||
}
|
||||
|
||||
// Parses entire JSX element, including it's opening tag
|
||||
// (starting after '<'), attributes, contents and closing tag.
|
||||
|
||||
jsx_parseElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let children = [];
|
||||
let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
|
||||
let closingElement = null;
|
||||
|
||||
if (!openingElement.selfClosing) {
|
||||
contents: for (;;) {
|
||||
switch (this.type) {
|
||||
case tok.jsxTagStart:
|
||||
startPos = this.start; startLoc = this.startLoc;
|
||||
this.next();
|
||||
if (this.eat(tt.slash)) {
|
||||
closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
|
||||
break contents;
|
||||
}
|
||||
children.push(this.jsx_parseElementAt(startPos, startLoc));
|
||||
break;
|
||||
|
||||
case tok.jsxText:
|
||||
children.push(this.parseExprAtom());
|
||||
break;
|
||||
|
||||
case tt.braceL:
|
||||
children.push(this.jsx_parseExpressionContainer());
|
||||
break;
|
||||
|
||||
default:
|
||||
this.unexpected();
|
||||
}
|
||||
}
|
||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
||||
this.raise(
|
||||
closingElement.start,
|
||||
'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
|
||||
}
|
||||
}
|
||||
let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment';
|
||||
|
||||
node['opening' + fragmentOrElement] = openingElement;
|
||||
node['closing' + fragmentOrElement] = closingElement;
|
||||
node.children = children;
|
||||
if (this.type === tt.relational && this.value === "<") {
|
||||
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
|
||||
}
|
||||
return this.finishNode(node, 'JSX' + fragmentOrElement);
|
||||
}
|
||||
|
||||
// Parse JSX text
|
||||
|
||||
jsx_parseText(value) {
|
||||
let node = this.parseLiteral(value);
|
||||
node.type = "JSXText";
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses entire JSX element from current position.
|
||||
|
||||
jsx_parseElement() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
this.next();
|
||||
return this.jsx_parseElementAt(startPos, startLoc);
|
||||
}
|
||||
|
||||
parseExprAtom(refShortHandDefaultPos) {
|
||||
if (this.type === tok.jsxText)
|
||||
return this.jsx_parseText(this.value);
|
||||
else if (this.type === tok.jsxTagStart)
|
||||
return this.jsx_parseElement();
|
||||
else
|
||||
return super.parseExprAtom(refShortHandDefaultPos);
|
||||
}
|
||||
|
||||
readToken(code) {
|
||||
let context = this.curContext();
|
||||
|
||||
if (context === tc_expr) return this.jsx_readToken();
|
||||
|
||||
if (context === tc_oTag || context === tc_cTag) {
|
||||
if (isIdentifierStart(code)) return this.jsx_readWord();
|
||||
|
||||
if (code == 62) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagEnd);
|
||||
}
|
||||
|
||||
if ((code === 34 || code === 39) && context == tc_oTag)
|
||||
return this.jsx_readString(code);
|
||||
}
|
||||
|
||||
if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return super.readToken(code)
|
||||
}
|
||||
|
||||
updateContext(prevType) {
|
||||
if (this.type == tt.braceL) {
|
||||
var curContext = this.curContext();
|
||||
if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);
|
||||
else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);
|
||||
else super.updateContext(prevType)
|
||||
this.exprAllowed = true;
|
||||
} else if (this.type === tt.slash && prevType === tok.jsxTagStart) {
|
||||
this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||
this.context.push(tc_cTag); // reconsider as closing tag context
|
||||
this.exprAllowed = false;
|
||||
} else {
|
||||
return super.updateContext(prevType);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
55
node_modules/acorn-jsx/package.json
generated
vendored
@ -1,55 +0,0 @@
|
||||
{
|
||||
"_from": "acorn-jsx@^5.0.0",
|
||||
"_id": "acorn-jsx@5.0.1",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
|
||||
"_location": "/acorn-jsx",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "acorn-jsx@^5.0.0",
|
||||
"name": "acorn-jsx",
|
||||
"escapedName": "acorn-jsx",
|
||||
"rawSpec": "^5.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^5.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/espree"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
|
||||
"_shasum": "32a064fd925429216a09b141102bfdd185fae40e",
|
||||
"_spec": "acorn-jsx@^5.0.0",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/BME_Project_Ohm/om/node_modules/espree",
|
||||
"bugs": {
|
||||
"url": "https://github.com/RReverser/acorn-jsx/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Alternative, faster React.js JSX parser",
|
||||
"devDependencies": {
|
||||
"acorn": "^6.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/RReverser/acorn-jsx",
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"url": "http://rreverser.com/"
|
||||
}
|
||||
],
|
||||
"name": "acorn-jsx",
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/RReverser/acorn-jsx.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run.js"
|
||||
},
|
||||
"version": "5.0.1"
|
||||
}
|
255
node_modules/acorn-jsx/xhtml.js
generated
vendored
@ -1,255 +0,0 @@
|
||||
module.exports = {
|
||||
quot: '\u0022',
|
||||
amp: '&',
|
||||
apos: '\u0027',
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
nbsp: '\u00A0',
|
||||
iexcl: '\u00A1',
|
||||
cent: '\u00A2',
|
||||
pound: '\u00A3',
|
||||
curren: '\u00A4',
|
||||
yen: '\u00A5',
|
||||
brvbar: '\u00A6',
|
||||
sect: '\u00A7',
|
||||
uml: '\u00A8',
|
||||
copy: '\u00A9',
|
||||
ordf: '\u00AA',
|
||||
laquo: '\u00AB',
|
||||
not: '\u00AC',
|
||||
shy: '\u00AD',
|
||||
reg: '\u00AE',
|
||||
macr: '\u00AF',
|
||||
deg: '\u00B0',
|
||||
plusmn: '\u00B1',
|
||||
sup2: '\u00B2',
|
||||
sup3: '\u00B3',
|
||||
acute: '\u00B4',
|
||||
micro: '\u00B5',
|
||||
para: '\u00B6',
|
||||
middot: '\u00B7',
|
||||
cedil: '\u00B8',
|
||||
sup1: '\u00B9',
|
||||
ordm: '\u00BA',
|
||||
raquo: '\u00BB',
|
||||
frac14: '\u00BC',
|
||||
frac12: '\u00BD',
|
||||
frac34: '\u00BE',
|
||||
iquest: '\u00BF',
|
||||
Agrave: '\u00C0',
|
||||
Aacute: '\u00C1',
|
||||
Acirc: '\u00C2',
|
||||
Atilde: '\u00C3',
|
||||
Auml: '\u00C4',
|
||||
Aring: '\u00C5',
|
||||
AElig: '\u00C6',
|
||||
Ccedil: '\u00C7',
|
||||
Egrave: '\u00C8',
|
||||
Eacute: '\u00C9',
|
||||
Ecirc: '\u00CA',
|
||||
Euml: '\u00CB',
|
||||
Igrave: '\u00CC',
|
||||
Iacute: '\u00CD',
|
||||
Icirc: '\u00CE',
|
||||
Iuml: '\u00CF',
|
||||
ETH: '\u00D0',
|
||||
Ntilde: '\u00D1',
|
||||
Ograve: '\u00D2',
|
||||
Oacute: '\u00D3',
|
||||
Ocirc: '\u00D4',
|
||||
Otilde: '\u00D5',
|
||||
Ouml: '\u00D6',
|
||||
times: '\u00D7',
|
||||
Oslash: '\u00D8',
|
||||
Ugrave: '\u00D9',
|
||||
Uacute: '\u00DA',
|
||||
Ucirc: '\u00DB',
|
||||
Uuml: '\u00DC',
|
||||
Yacute: '\u00DD',
|
||||
THORN: '\u00DE',
|
||||
szlig: '\u00DF',
|
||||
agrave: '\u00E0',
|
||||
aacute: '\u00E1',
|
||||
acirc: '\u00E2',
|
||||
atilde: '\u00E3',
|
||||
auml: '\u00E4',
|
||||
aring: '\u00E5',
|
||||
aelig: '\u00E6',
|
||||
ccedil: '\u00E7',
|
||||
egrave: '\u00E8',
|
||||
eacute: '\u00E9',
|
||||
ecirc: '\u00EA',
|
||||
euml: '\u00EB',
|
||||
igrave: '\u00EC',
|
||||
iacute: '\u00ED',
|
||||
icirc: '\u00EE',
|
||||
iuml: '\u00EF',
|
||||
eth: '\u00F0',
|
||||
ntilde: '\u00F1',
|
||||
ograve: '\u00F2',
|
||||
oacute: '\u00F3',
|
||||
ocirc: '\u00F4',
|
||||
otilde: '\u00F5',
|
||||
ouml: '\u00F6',
|
||||
divide: '\u00F7',
|
||||
oslash: '\u00F8',
|
||||
ugrave: '\u00F9',
|
||||
uacute: '\u00FA',
|
||||
ucirc: '\u00FB',
|
||||
uuml: '\u00FC',
|
||||
yacute: '\u00FD',
|
||||
thorn: '\u00FE',
|
||||
yuml: '\u00FF',
|
||||
OElig: '\u0152',
|
||||
oelig: '\u0153',
|
||||
Scaron: '\u0160',
|
||||
scaron: '\u0161',
|
||||
Yuml: '\u0178',
|
||||
fnof: '\u0192',
|
||||
circ: '\u02C6',
|
||||
tilde: '\u02DC',
|
||||
Alpha: '\u0391',
|
||||
Beta: '\u0392',
|
||||
Gamma: '\u0393',
|
||||
Delta: '\u0394',
|
||||
Epsilon: '\u0395',
|
||||
Zeta: '\u0396',
|
||||
Eta: '\u0397',
|
||||
Theta: '\u0398',
|
||||
Iota: '\u0399',
|
||||
Kappa: '\u039A',
|
||||
Lambda: '\u039B',
|
||||
Mu: '\u039C',
|
||||
Nu: '\u039D',
|
||||
Xi: '\u039E',
|
||||
Omicron: '\u039F',
|
||||
Pi: '\u03A0',
|
||||
Rho: '\u03A1',
|
||||
Sigma: '\u03A3',
|
||||
Tau: '\u03A4',
|
||||
Upsilon: '\u03A5',
|
||||
Phi: '\u03A6',
|
||||
Chi: '\u03A7',
|
||||
Psi: '\u03A8',
|
||||
Omega: '\u03A9',
|
||||
alpha: '\u03B1',
|
||||
beta: '\u03B2',
|
||||
gamma: '\u03B3',
|
||||
delta: '\u03B4',
|
||||
epsilon: '\u03B5',
|
||||
zeta: '\u03B6',
|
||||
eta: '\u03B7',
|
||||
theta: '\u03B8',
|
||||
iota: '\u03B9',
|
||||
kappa: '\u03BA',
|
||||
lambda: '\u03BB',
|
||||
mu: '\u03BC',
|
||||
nu: '\u03BD',
|
||||
xi: '\u03BE',
|
||||
omicron: '\u03BF',
|
||||
pi: '\u03C0',
|
||||
rho: '\u03C1',
|
||||
sigmaf: '\u03C2',
|
||||
sigma: '\u03C3',
|
||||
tau: '\u03C4',
|
||||
upsilon: '\u03C5',
|
||||
phi: '\u03C6',
|
||||
chi: '\u03C7',
|
||||
psi: '\u03C8',
|
||||
omega: '\u03C9',
|
||||
thetasym: '\u03D1',
|
||||
upsih: '\u03D2',
|
||||
piv: '\u03D6',
|
||||
ensp: '\u2002',
|
||||
emsp: '\u2003',
|
||||
thinsp: '\u2009',
|
||||
zwnj: '\u200C',
|
||||
zwj: '\u200D',
|
||||
lrm: '\u200E',
|
||||
rlm: '\u200F',
|
||||
ndash: '\u2013',
|
||||
mdash: '\u2014',
|
||||
lsquo: '\u2018',
|
||||
rsquo: '\u2019',
|
||||
sbquo: '\u201A',
|
||||
ldquo: '\u201C',
|
||||
rdquo: '\u201D',
|
||||
bdquo: '\u201E',
|
||||
dagger: '\u2020',
|
||||
Dagger: '\u2021',
|
||||
bull: '\u2022',
|
||||
hellip: '\u2026',
|
||||
permil: '\u2030',
|
||||
prime: '\u2032',
|
||||
Prime: '\u2033',
|
||||
lsaquo: '\u2039',
|
||||
rsaquo: '\u203A',
|
||||
oline: '\u203E',
|
||||
frasl: '\u2044',
|
||||
euro: '\u20AC',
|
||||
image: '\u2111',
|
||||
weierp: '\u2118',
|
||||
real: '\u211C',
|
||||
trade: '\u2122',
|
||||
alefsym: '\u2135',
|
||||
larr: '\u2190',
|
||||
uarr: '\u2191',
|
||||
rarr: '\u2192',
|
||||
darr: '\u2193',
|
||||
harr: '\u2194',
|
||||
crarr: '\u21B5',
|
||||
lArr: '\u21D0',
|
||||
uArr: '\u21D1',
|
||||
rArr: '\u21D2',
|
||||
dArr: '\u21D3',
|
||||
hArr: '\u21D4',
|
||||
forall: '\u2200',
|
||||
part: '\u2202',
|
||||
exist: '\u2203',
|
||||
empty: '\u2205',
|
||||
nabla: '\u2207',
|
||||
isin: '\u2208',
|
||||
notin: '\u2209',
|
||||
ni: '\u220B',
|
||||
prod: '\u220F',
|
||||
sum: '\u2211',
|
||||
minus: '\u2212',
|
||||
lowast: '\u2217',
|
||||
radic: '\u221A',
|
||||
prop: '\u221D',
|
||||
infin: '\u221E',
|
||||
ang: '\u2220',
|
||||
and: '\u2227',
|
||||
or: '\u2228',
|
||||
cap: '\u2229',
|
||||
cup: '\u222A',
|
||||
'int': '\u222B',
|
||||
there4: '\u2234',
|
||||
sim: '\u223C',
|
||||
cong: '\u2245',
|
||||
asymp: '\u2248',
|
||||
ne: '\u2260',
|
||||
equiv: '\u2261',
|
||||
le: '\u2264',
|
||||
ge: '\u2265',
|
||||
sub: '\u2282',
|
||||
sup: '\u2283',
|
||||
nsub: '\u2284',
|
||||
sube: '\u2286',
|
||||
supe: '\u2287',
|
||||
oplus: '\u2295',
|
||||
otimes: '\u2297',
|
||||
perp: '\u22A5',
|
||||
sdot: '\u22C5',
|
||||
lceil: '\u2308',
|
||||
rceil: '\u2309',
|
||||
lfloor: '\u230A',
|
||||
rfloor: '\u230B',
|
||||
lang: '\u2329',
|
||||
rang: '\u232A',
|
||||
loz: '\u25CA',
|
||||
spades: '\u2660',
|
||||
clubs: '\u2663',
|
||||
hearts: '\u2665',
|
||||
diams: '\u2666'
|
||||
};
|
452
node_modules/acorn/CHANGELOG.md
generated
vendored
@ -1,452 +0,0 @@
|
||||
## 6.0.4 (2018-11-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Further improvements to tokenizing regular expressions in corner cases.
|
||||
|
||||
## 6.0.3 (2018-11-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression.
|
||||
|
||||
Remove stray symlink in the package tarball.
|
||||
|
||||
## 6.0.2 (2018-09-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug where default expressions could fail to parse inside an object destructuring assignment expression.
|
||||
|
||||
## 6.0.1 (2018-09-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix wrong value in `version` export.
|
||||
|
||||
## 6.0.0 (2018-09-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Better handle variable-redefinition checks for catch bindings and functions directly under if statements.
|
||||
|
||||
Forbid `new.target` in top-level arrow functions.
|
||||
|
||||
Fix issue with parsing a regexp after `yield` in some contexts.
|
||||
|
||||
### New features
|
||||
|
||||
The package now comes with TypeScript definitions.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default value of the `ecmaVersion` option is now 9 (2018).
|
||||
|
||||
Plugins work differently, and will have to be rewritten to work with this version.
|
||||
|
||||
The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`).
|
||||
|
||||
## 5.7.3 (2018-09-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix failure to tokenize regexps after expressions like `x.of`.
|
||||
|
||||
Better error message for unterminated template literals.
|
||||
|
||||
## 5.7.2 (2018-08-24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Properly handle `allowAwaitOutsideFunction` in for statements.
|
||||
|
||||
Treat function declarations at the top level of modules like let bindings.
|
||||
|
||||
Don't allow async function declarations as the only statement under a label.
|
||||
|
||||
## 5.7.0 (2018-06-15)
|
||||
|
||||
### New features
|
||||
|
||||
Upgraded to Unicode 11.
|
||||
|
||||
## 5.6.0 (2018-05-31)
|
||||
|
||||
### New features
|
||||
|
||||
Allow U+2028 and U+2029 in string when ECMAVersion >= 10.
|
||||
|
||||
Allow binding-less catch statements when ECMAVersion >= 10.
|
||||
|
||||
Add `allowAwaitOutsideFunction` option for parsing top-level `await`.
|
||||
|
||||
## 5.5.3 (2018-03-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps.
|
||||
|
||||
## 5.5.2 (2018-03-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0.
|
||||
|
||||
## 5.5.1 (2018-03-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix misleading error message for octal escapes in template strings.
|
||||
|
||||
## 5.5.0 (2018-02-27)
|
||||
|
||||
### New features
|
||||
|
||||
The identifier character categorization is now based on Unicode version 10.
|
||||
|
||||
Acorn will now validate the content of regular expressions, including new ES9 features.
|
||||
|
||||
## 5.4.0 (2018-02-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disallow duplicate or escaped flags on regular expressions.
|
||||
|
||||
Disallow octal escapes in strings in strict mode.
|
||||
|
||||
### New features
|
||||
|
||||
Add support for async iteration.
|
||||
|
||||
Add support for object spread and rest.
|
||||
|
||||
## 5.3.0 (2017-12-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix parsing of floating point literals with leading zeroes in loose mode.
|
||||
|
||||
Allow duplicate property names in object patterns.
|
||||
|
||||
Don't allow static class methods named `prototype`.
|
||||
|
||||
Disallow async functions directly under `if` or `else`.
|
||||
|
||||
Parse right-hand-side of `for`/`of` as an assignment expression.
|
||||
|
||||
Stricter parsing of `for`/`in`.
|
||||
|
||||
Don't allow unicode escapes in contextual keywords.
|
||||
|
||||
### New features
|
||||
|
||||
Parsing class members was factored into smaller methods to allow plugins to hook into it.
|
||||
|
||||
## 5.2.1 (2017-10-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a token context corruption bug.
|
||||
|
||||
## 5.2.0 (2017-10-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix token context tracking for `class` and `function` in property-name position.
|
||||
|
||||
Make sure `%*` isn't parsed as a valid operator.
|
||||
|
||||
Allow shorthand properties `get` and `set` to be followed by default values.
|
||||
|
||||
Disallow `super` when not in callee or object position.
|
||||
|
||||
### New features
|
||||
|
||||
Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements.
|
||||
|
||||
## 5.1.2 (2017-09-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disable parsing of legacy HTML-style comments in modules.
|
||||
|
||||
Fix parsing of async methods whose names are keywords.
|
||||
|
||||
## 5.1.1 (2017-07-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix problem with disambiguating regexp and division after a class.
|
||||
|
||||
## 5.1.0 (2017-07-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`.
|
||||
|
||||
Parse zero-prefixed numbers with non-octal digits as decimal.
|
||||
|
||||
Allow object/array patterns in rest parameters.
|
||||
|
||||
Don't error when `yield` is used as a property name.
|
||||
|
||||
Allow `async` as a shorthand object property.
|
||||
|
||||
### New features
|
||||
|
||||
Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9.
|
||||
|
||||
## 5.0.3 (2017-04-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix spurious duplicate variable definition errors for named functions.
|
||||
|
||||
## 5.0.2 (2017-03-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error.
|
||||
|
||||
## 5.0.0 (2017-03-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Raise an error for duplicated lexical bindings.
|
||||
|
||||
Fix spurious error when an assignement expression occurred after a spread expression.
|
||||
|
||||
Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions.
|
||||
|
||||
Allow labels in front or `var` declarations, even in strict mode.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`.
|
||||
|
||||
## 4.0.11 (2017-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow all forms of member expressions to be parenthesized as lvalue.
|
||||
|
||||
## 4.0.10 (2017-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't expect semicolons after default-exported functions or classes, even when they are expressions.
|
||||
|
||||
Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode.
|
||||
|
||||
## 4.0.9 (2017-02-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again.
|
||||
|
||||
## 4.0.8 (2017-02-03)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet.
|
||||
|
||||
## 4.0.7 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Accept invalidly rejected code like `(x).y = 2` again.
|
||||
|
||||
Don't raise an error when a function _inside_ strict code has a non-simple parameter list.
|
||||
|
||||
## 4.0.6 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check.
|
||||
|
||||
## 4.0.5 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disallow parenthesized pattern expressions.
|
||||
|
||||
Allow keywords as export names.
|
||||
|
||||
Don't allow the `async` keyword to be parenthesized.
|
||||
|
||||
Properly raise an error when a keyword contains a character escape.
|
||||
|
||||
Allow `"use strict"` to appear after other string literal expressions.
|
||||
|
||||
Disallow labeled declarations.
|
||||
|
||||
## 4.0.4 (2016-12-19)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix crash when `export` was followed by a keyword that can't be
|
||||
exported.
|
||||
|
||||
## 4.0.3 (2016-08-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode.
|
||||
|
||||
Properly parse properties named `async` in ES2017 mode.
|
||||
|
||||
Fix bug where reserved words were broken in ES2017 mode.
|
||||
|
||||
## 4.0.2 (2016-08-11)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't ignore period or 'e' characters after octal numbers.
|
||||
|
||||
Fix broken parsing for call expressions in default parameter values of arrow functions.
|
||||
|
||||
## 4.0.1 (2016-08-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix false positives in duplicated export name errors.
|
||||
|
||||
## 4.0.0 (2016-08-07)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default `ecmaVersion` option value is now 7.
|
||||
|
||||
A number of internal method signatures changed, so plugins might need to be updated.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
The parser now raises errors on duplicated export names.
|
||||
|
||||
`arguments` and `eval` can now be used in shorthand properties.
|
||||
|
||||
Duplicate parameter names in non-simple argument lists now always produce an error.
|
||||
|
||||
### New features
|
||||
|
||||
The `ecmaVersion` option now also accepts year-style version numbers
|
||||
(2015, etc).
|
||||
|
||||
Support for `async`/`await` syntax when `ecmaVersion` is >= 8.
|
||||
|
||||
Support for trailing commas in call expressions when `ecmaVersion` is >= 8.
|
||||
|
||||
## 3.3.0 (2016-07-25)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug in tokenizing of regexp operator after a function declaration.
|
||||
|
||||
Fix parser crash when parsing an array pattern with a hole.
|
||||
|
||||
### New features
|
||||
|
||||
Implement check against complex argument lists in functions that enable strict mode in ES7.
|
||||
|
||||
## 3.2.0 (2016-06-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Improve handling of lack of unicode regexp support in host
|
||||
environment.
|
||||
|
||||
Properly reject shorthand properties whose name is a keyword.
|
||||
|
||||
### New features
|
||||
|
||||
Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object.
|
||||
|
||||
## 3.1.0 (2016-04-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Properly tokenize the division operator directly after a function expression.
|
||||
|
||||
Allow trailing comma in destructuring arrays.
|
||||
|
||||
## 3.0.4 (2016-02-25)
|
||||
|
||||
### Fixes
|
||||
|
||||
Allow update expressions as left-hand-side of the ES7 exponential operator.
|
||||
|
||||
## 3.0.2 (2016-02-10)
|
||||
|
||||
### Fixes
|
||||
|
||||
Fix bug that accidentally made `undefined` a reserved word when parsing ES7.
|
||||
|
||||
## 3.0.0 (2016-02-10)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default value of the `ecmaVersion` option is now 6 (used to be 5).
|
||||
|
||||
Support for comprehension syntax (which was dropped from the draft spec) has been removed.
|
||||
|
||||
### Fixes
|
||||
|
||||
`let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code.
|
||||
|
||||
A parenthesized class or function expression after `export default` is now parsed correctly.
|
||||
|
||||
### New features
|
||||
|
||||
When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`).
|
||||
|
||||
The identifier character ranges are now based on Unicode 8.0.0.
|
||||
|
||||
Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled.
|
||||
|
||||
## 2.7.0 (2016-01-04)
|
||||
|
||||
### Fixes
|
||||
|
||||
Stop allowing rest parameters in setters.
|
||||
|
||||
Disallow `y` rexexp flag in ES5.
|
||||
|
||||
Disallow `\00` and `\000` escapes in strict mode.
|
||||
|
||||
Raise an error when an import name is a reserved word.
|
||||
|
||||
## 2.6.2 (2015-11-10)
|
||||
|
||||
### Fixes
|
||||
|
||||
Don't crash when no options object is passed.
|
||||
|
||||
## 2.6.0 (2015-11-09)
|
||||
|
||||
### Fixes
|
||||
|
||||
Add `await` as a reserved word in module sources.
|
||||
|
||||
Disallow `yield` in a parameter default value for a generator.
|
||||
|
||||
Forbid using a comma after a rest pattern in an array destructuring.
|
||||
|
||||
### New features
|
||||
|
||||
Support parsing stdin in command-line tool.
|
||||
|
||||
## 2.5.0 (2015-10-27)
|
||||
|
||||
### Fixes
|
||||
|
||||
Fix tokenizer support in the command-line tool.
|
||||
|
||||
Stop allowing `new.target` outside of functions.
|
||||
|
||||
Remove legacy `guard` and `guardedHandler` properties from try nodes.
|
||||
|
||||
Stop allowing multiple `__proto__` properties on an object literal in strict mode.
|
||||
|
||||
Don't allow rest parameters to be non-identifier patterns.
|
||||
|
||||
Check for duplicate paramter names in arrow functions.
|
19
node_modules/acorn/LICENSE
generated
vendored
@ -1,19 +0,0 @@
|
||||
Copyright (C) 2012-2018 by various contributors (see AUTHORS)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
269
node_modules/acorn/README.md
generated
vendored
@ -1,269 +0,0 @@
|
||||
# Acorn
|
||||
|
||||
A tiny, fast JavaScript parser written in JavaScript.
|
||||
|
||||
## Community
|
||||
|
||||
Acorn is open source software released under an
|
||||
[MIT license](https://github.com/acornjs/acorn/blob/master/LICENSE).
|
||||
|
||||
You are welcome to
|
||||
[report bugs](https://github.com/acornjs/acorn/issues) or create pull
|
||||
requests on [github](https://github.com/acornjs/acorn). For questions
|
||||
and discussion, please use the
|
||||
[Tern discussion forum](https://discuss.ternjs.net).
|
||||
|
||||
## Installation
|
||||
|
||||
The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
|
||||
|
||||
```sh
|
||||
npm install acorn
|
||||
```
|
||||
|
||||
Alternately, you can download the source and build acorn yourself:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/acornjs/acorn.git
|
||||
cd acorn
|
||||
npm install
|
||||
```
|
||||
|
||||
## Interface
|
||||
|
||||
**parse**`(input, options)` is the main interface to the library. The
|
||||
`input` parameter is a string, `options` can be undefined or an object
|
||||
setting some of the options listed below. The return value will be an
|
||||
abstract syntax tree object as specified by the [ESTree
|
||||
spec](https://github.com/estree/estree).
|
||||
|
||||
```javascript
|
||||
let acorn = require("acorn");
|
||||
console.log(acorn.parse("1 + 1"));
|
||||
```
|
||||
|
||||
When encountering a syntax error, the parser will raise a
|
||||
`SyntaxError` object with a meaningful message. The error object will
|
||||
have a `pos` property that indicates the string offset at which the
|
||||
error occurred, and a `loc` object that contains a `{line, column}`
|
||||
object referring to that same position.
|
||||
|
||||
Options can be provided by passing a second argument, which should be
|
||||
an object containing any of these fields:
|
||||
|
||||
- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
|
||||
either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018) or 10 (2019, partial
|
||||
support). This influences support for strict mode, the set of
|
||||
reserved words, and support for new syntax features. Default is 7.
|
||||
|
||||
**NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
|
||||
implemented by Acorn. Other proposed new features can be implemented
|
||||
through plugins.
|
||||
|
||||
- **sourceType**: Indicate the mode the code should be parsed in. Can be
|
||||
either `"script"` or `"module"`. This influences global strict mode
|
||||
and parsing of `import` and `export` declarations.
|
||||
|
||||
- **onInsertedSemicolon**: If given a callback, that callback will be
|
||||
called whenever a missing semicolon is inserted by the parser. The
|
||||
callback will be given the character offset of the point where the
|
||||
semicolon is inserted as argument, and if `locations` is on, also a
|
||||
`{line, column}` object representing this position.
|
||||
|
||||
- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
|
||||
commas.
|
||||
|
||||
- **allowReserved**: If `false`, using a reserved word will generate
|
||||
an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher
|
||||
versions. When given the value `"never"`, reserved words and
|
||||
keywords can also not be used as property names (as in Internet
|
||||
Explorer's old parser).
|
||||
|
||||
- **allowReturnOutsideFunction**: By default, a return statement at
|
||||
the top level raises an error. Set this to `true` to accept such
|
||||
code.
|
||||
|
||||
- **allowImportExportEverywhere**: By default, `import` and `export`
|
||||
declarations can only appear at a program's top level. Setting this
|
||||
option to `true` allows them anywhere where a statement is allowed.
|
||||
|
||||
- **allowAwaitOutsideFunction**: By default, `await` expressions can
|
||||
only appear inside `async` functions. Setting this option to
|
||||
`true` allows to have top-level `await` expressions. They are
|
||||
still not allowed in non-`async` functions, though.
|
||||
|
||||
- **allowHashBang**: When this is enabled (off by default), if the
|
||||
code starts with the characters `#!` (as in a shellscript), the
|
||||
first line will be treated as a comment.
|
||||
|
||||
- **locations**: When `true`, each node has a `loc` object attached
|
||||
with `start` and `end` subobjects, each of which contains the
|
||||
one-based line and zero-based column numbers in `{line, column}`
|
||||
form. Default is `false`.
|
||||
|
||||
- **onToken**: If a function is passed for this option, each found
|
||||
token will be passed in same format as tokens returned from
|
||||
`tokenizer().getToken()`.
|
||||
|
||||
If array is passed, each found token is pushed to it.
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **onComment**: If a function is passed for this option, whenever a
|
||||
comment is encountered the function will be called with the
|
||||
following parameters:
|
||||
|
||||
- `block`: `true` if the comment is a block comment, false if it
|
||||
is a line comment.
|
||||
- `text`: The content of the comment.
|
||||
- `start`: Character offset of the start of the comment.
|
||||
- `end`: Character offset of the end of the comment.
|
||||
|
||||
When the `locations` options is on, the `{line, column}` locations
|
||||
of the comment’s start and end are passed as two additional
|
||||
parameters.
|
||||
|
||||
If array is passed for this option, each found comment is pushed
|
||||
to it as object in Esprima format:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"type": "Line" | "Block",
|
||||
"value": "comment text",
|
||||
"start": Number,
|
||||
"end": Number,
|
||||
// If `locations` option is on:
|
||||
"loc": {
|
||||
"start": {line: Number, column: Number}
|
||||
"end": {line: Number, column: Number}
|
||||
},
|
||||
// If `ranges` option is on:
|
||||
"range": [Number, Number]
|
||||
}
|
||||
```
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **ranges**: Nodes have their start and end characters offsets
|
||||
recorded in `start` and `end` properties (directly on the node,
|
||||
rather than the `loc` object, which holds line/column data. To also
|
||||
add a
|
||||
[semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678)
|
||||
`range` property holding a `[start, end]` array with the same
|
||||
numbers, set the `ranges` option to `true`.
|
||||
|
||||
- **program**: It is possible to parse multiple files into a single
|
||||
AST by passing the tree produced by parsing the first file as the
|
||||
`program` option in subsequent parses. This will add the toplevel
|
||||
forms of the parsed file to the "Program" (top) node of an existing
|
||||
parse tree.
|
||||
|
||||
- **sourceFile**: When the `locations` option is `true`, you can pass
|
||||
this option to add a `source` attribute in every node’s `loc`
|
||||
object. Note that the contents of this option are not examined or
|
||||
processed in any way; you are free to use whatever format you
|
||||
choose.
|
||||
|
||||
- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
|
||||
will be added (regardless of the `location` option) directly to the
|
||||
nodes, rather than the `loc` object.
|
||||
|
||||
- **preserveParens**: If this option is `true`, parenthesized expressions
|
||||
are represented by (non-standard) `ParenthesizedExpression` nodes
|
||||
that have a single `expression` property containing the expression
|
||||
inside parentheses.
|
||||
|
||||
**parseExpressionAt**`(input, offset, options)` will parse a single
|
||||
expression in a string, and return its AST. It will not complain if
|
||||
there is more of the string left after the expression.
|
||||
|
||||
**tokenizer**`(input, options)` returns an object with a `getToken`
|
||||
method that can be called repeatedly to get the next token, a `{start,
|
||||
end, type, value}` object (with added `loc` property when the
|
||||
`locations` option is enabled and `range` property when the `ranges`
|
||||
option is enabled). When the token's type is `tokTypes.eof`, you
|
||||
should stop calling the method, since it will keep returning that same
|
||||
token forever.
|
||||
|
||||
In ES6 environment, returned result can be used as any other
|
||||
protocol-compliant iterable:
|
||||
|
||||
```javascript
|
||||
for (let token of acorn.tokenizer(str)) {
|
||||
// iterate over the tokens
|
||||
}
|
||||
|
||||
// transform code to array of tokens:
|
||||
var tokens = [...acorn.tokenizer(str)];
|
||||
```
|
||||
|
||||
**tokTypes** holds an object mapping names to the token type objects
|
||||
that end up in the `type` properties of tokens.
|
||||
|
||||
**getLineInfo**`(input, offset)` can be used to get a `{line,
|
||||
column}` object for a given program string and offset.
|
||||
|
||||
### The `Parser` class
|
||||
|
||||
Instances of the **`Parser`** class contain all the state and logic
|
||||
that drives a parse. It has static methods `parse`,
|
||||
`parseExpressionAt`, and `tokenizer` that match the top-level
|
||||
functions by the same name.
|
||||
|
||||
When extending the parser with plugins, you need to call these methods
|
||||
on the extended version of the class. To extend a parser with plugins,
|
||||
you can use its static `extend` method.
|
||||
|
||||
```javascript
|
||||
var acorn = require("acorn");
|
||||
var jsx = require("acorn-jsx");
|
||||
var JSXParser = acorn.Parser.extend(jsx());
|
||||
JSXParser.parse("foo(<bar/>)");
|
||||
```
|
||||
|
||||
The `extend` method takes any number of plugin values, and returns a
|
||||
new `Parser` class that includes the extra parser logic provided by
|
||||
the plugins.
|
||||
|
||||
## Command line interface
|
||||
|
||||
The `bin/acorn` utility can be used to parse a file from the command
|
||||
line. It accepts as arguments its input file and the following
|
||||
options:
|
||||
|
||||
- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version
|
||||
to parse. Default is version 9.
|
||||
|
||||
- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
|
||||
|
||||
- `--locations`: Attaches a "loc" object to each node with "start" and
|
||||
"end" subobjects, each of which contains the one-based line and
|
||||
zero-based column numbers in `{line, column}` form.
|
||||
|
||||
- `--allow-hash-bang`: If the code starts with the characters #! (as
|
||||
in a shellscript), the first line will be treated as a comment.
|
||||
|
||||
- `--compact`: No whitespace is used in the AST output.
|
||||
|
||||
- `--silent`: Do not output the AST, just return the exit status.
|
||||
|
||||
- `--help`: Print the usage information and quit.
|
||||
|
||||
The utility spits out the syntax tree as JSON data.
|
||||
|
||||
## Existing plugins
|
||||
|
||||
- [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx)
|
||||
|
||||
Plugins for ECMAScript proposals:
|
||||
|
||||
- [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling:
|
||||
- [`acorn-async-iteration`](https://github.com/acornjs/acorn-async-iteration): Parse [async iteration proposal](https://github.com/tc39/proposal-async-iteration)
|
||||
- [`acorn-bigint`](https://github.com/acornjs/acorn-bigint): Parse [BigInt proposal](https://github.com/tc39/proposal-bigint)
|
||||
- [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields)
|
||||
- [`acorn-dynamic-import`](https://github.com/kesne/acorn-dynamic-import): Parse [import() proposal](https://github.com/tc39/proposal-dynamic-import)
|
||||
- [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta)
|
||||
- [`acorn-numeric-separator`](https://github.com/acornjs/acorn-numeric-separator): Parse [numeric separator proposal](https://github.com/tc39/proposal-numeric-separator)
|
||||
- [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods)n
|
4
node_modules/acorn/bin/acorn
generated
vendored
@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
require('../dist/bin.js');
|
208
node_modules/acorn/dist/acorn.d.ts
generated
vendored
@ -1,208 +0,0 @@
|
||||
export as namespace acorn
|
||||
export = acorn
|
||||
|
||||
declare namespace acorn {
|
||||
function parse(input: string, options?: Options): Node
|
||||
|
||||
function parseExpressionAt(input: string, pos?: number, options?: Options): Node
|
||||
|
||||
function tokenizer(input: string, options?: Options): {
|
||||
getToken(): Token
|
||||
[Symbol.iterator](): Iterator<Token>
|
||||
}
|
||||
|
||||
interface Options {
|
||||
ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 10 | 2015 | 2016 | 2017 | 2018 | 2019
|
||||
sourceType?: 'script' | 'module'
|
||||
onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
|
||||
onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
|
||||
allowReserved?: boolean
|
||||
allowReturnOutsideFunction?: boolean
|
||||
allowImportExportEverywhere?: boolean
|
||||
allowHashBang?: boolean
|
||||
locations?: boolean
|
||||
onToken?: ((token: Token) => any) | Token[]
|
||||
onComment?: ((
|
||||
isBlock: boolean, text: string, start: number, end: number, startLoc?: Position,
|
||||
endLoc?: Position
|
||||
) => void) | Comment[]
|
||||
ranges?: boolean
|
||||
program?: Node
|
||||
sourceFile?: string
|
||||
directSourceFile?: string
|
||||
preserveParens?: boolean
|
||||
}
|
||||
|
||||
class Parser {
|
||||
constructor(options: Options, input: string, startPos?: number)
|
||||
parse(): Node
|
||||
static parse(input: string, options?: Options): Node
|
||||
static parseExpressionAt(input: string, pos: number, options?: Options): Node
|
||||
static tokenizer(input: string, options?: Options): {
|
||||
getToken(): Token
|
||||
[Symbol.iterator](): Iterator<Token>
|
||||
}
|
||||
static extend(...plugins: (typeof Parser)[]): typeof Parser
|
||||
}
|
||||
|
||||
interface Position { line: number; column: number; offset: number }
|
||||
|
||||
const defaultOptions: Options
|
||||
|
||||
function getLineInfo(input: string, offset: number): Position
|
||||
|
||||
class SourceLocation {
|
||||
start: Position
|
||||
end: Position
|
||||
source?: string | null
|
||||
constructor(p: Parser, start: Position, end: Position)
|
||||
}
|
||||
|
||||
class Node {
|
||||
type: string
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
sourceFile?: string
|
||||
range?: [number, number]
|
||||
constructor(parser: Parser, pos: number, loc?: SourceLocation)
|
||||
}
|
||||
|
||||
class TokenType {
|
||||
label: string
|
||||
keyword: string
|
||||
beforeExpr: boolean
|
||||
startsExpr: boolean
|
||||
isLoop: boolean
|
||||
isAssign: boolean
|
||||
prefix: boolean
|
||||
postfix: boolean
|
||||
binop: number
|
||||
updateContext?: (prevType: TokenType) => void
|
||||
constructor(label: string, conf?: any)
|
||||
}
|
||||
|
||||
const tokTypes: {
|
||||
num: TokenType
|
||||
regexp: TokenType
|
||||
string: TokenType
|
||||
name: TokenType
|
||||
eof: TokenType
|
||||
bracketL: TokenType
|
||||
bracketR: TokenType
|
||||
braceL: TokenType
|
||||
braceR: TokenType
|
||||
parenL: TokenType
|
||||
parenR: TokenType
|
||||
comma: TokenType
|
||||
semi: TokenType
|
||||
colon: TokenType
|
||||
dot: TokenType
|
||||
question: TokenType
|
||||
arrow: TokenType
|
||||
template: TokenType
|
||||
ellipsis: TokenType
|
||||
backQuote: TokenType
|
||||
dollarBraceL: TokenType
|
||||
eq: TokenType
|
||||
assign: TokenType
|
||||
incDec: TokenType
|
||||
prefix: TokenType
|
||||
logicalOR: TokenType
|
||||
logicalAND: TokenType
|
||||
bitwiseOR: TokenType
|
||||
bitwiseXOR: TokenType
|
||||
bitwiseAND: TokenType
|
||||
equality: TokenType
|
||||
relational: TokenType
|
||||
bitShift: TokenType
|
||||
plusMin: TokenType
|
||||
modulo: TokenType
|
||||
star: TokenType
|
||||
slash: TokenType
|
||||
starstar: TokenType
|
||||
_break: TokenType
|
||||
_case: TokenType
|
||||
_catch: TokenType
|
||||
_continue: TokenType
|
||||
_debugger: TokenType
|
||||
_default: TokenType
|
||||
_do: TokenType
|
||||
_else: TokenType
|
||||
_finally: TokenType
|
||||
_for: TokenType
|
||||
_function: TokenType
|
||||
_if: TokenType
|
||||
_return: TokenType
|
||||
_switch: TokenType
|
||||
_throw: TokenType
|
||||
_try: TokenType
|
||||
_var: TokenType
|
||||
_const: TokenType
|
||||
_while: TokenType
|
||||
_with: TokenType
|
||||
_new: TokenType
|
||||
_this: TokenType
|
||||
_super: TokenType
|
||||
_class: TokenType
|
||||
_extends: TokenType
|
||||
_export: TokenType
|
||||
_import: TokenType
|
||||
_null: TokenType
|
||||
_true: TokenType
|
||||
_false: TokenType
|
||||
_in: TokenType
|
||||
_instanceof: TokenType
|
||||
_typeof: TokenType
|
||||
_void: TokenType
|
||||
_delete: TokenType
|
||||
}
|
||||
|
||||
class TokContext {
|
||||
constructor(token: string, isExpr: boolean, preserveSpace: boolean, override?: (p: Parser) => void)
|
||||
}
|
||||
|
||||
const tokContexts: {
|
||||
b_stat: TokContext
|
||||
b_expr: TokContext
|
||||
b_tmpl: TokContext
|
||||
p_stat: TokContext
|
||||
p_expr: TokContext
|
||||
q_tmpl: TokContext
|
||||
f_expr: TokContext
|
||||
}
|
||||
|
||||
function isIdentifierStart(code: number, astral?: boolean): boolean
|
||||
|
||||
function isIdentifierChar(code: number, astral?: boolean): boolean
|
||||
|
||||
interface AbstractToken {
|
||||
}
|
||||
|
||||
interface Comment extends AbstractToken {
|
||||
type: string
|
||||
value: string
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
range?: [number, number]
|
||||
}
|
||||
|
||||
class Token {
|
||||
type: TokenType
|
||||
value: any
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
range?: [number, number]
|
||||
constructor(p: Parser)
|
||||
}
|
||||
|
||||
function isNewLine(code: number): boolean
|
||||
|
||||
const lineBreak: RegExp
|
||||
|
||||
const lineBreakG: RegExp
|
||||
|
||||
const version: string
|
||||
}
|
5332
node_modules/acorn/dist/acorn.js
generated
vendored
1
node_modules/acorn/dist/acorn.js.map
generated
vendored
5301
node_modules/acorn/dist/acorn.mjs
generated
vendored
1
node_modules/acorn/dist/acorn.mjs.map
generated
vendored
68
node_modules/acorn/dist/bin.js
generated
vendored
@ -1,68 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var acorn = require('./acorn.js');
|
||||
|
||||
var infile;
|
||||
var forceFile;
|
||||
var silent = false;
|
||||
var compact = false;
|
||||
var tokenize = false;
|
||||
var options = {};
|
||||
|
||||
function help(status) {
|
||||
var print = (status === 0) ? console.log : console.error;
|
||||
print("usage: " + path.basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]");
|
||||
print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]");
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
for (var i = 2; i < process.argv.length; ++i) {
|
||||
var arg = process.argv[i];
|
||||
if ((arg === "-" || arg[0] !== "-") && !infile) { infile = arg; }
|
||||
else if (arg === "--" && !infile && i + 2 === process.argv.length) { forceFile = infile = process.argv[++i]; }
|
||||
else if (arg === "--locations") { options.locations = true; }
|
||||
else if (arg === "--allow-hash-bang") { options.allowHashBang = true; }
|
||||
else if (arg === "--silent") { silent = true; }
|
||||
else if (arg === "--compact") { compact = true; }
|
||||
else if (arg === "--help") { help(0); }
|
||||
else if (arg === "--tokenize") { tokenize = true; }
|
||||
else if (arg === "--module") { options.sourceType = "module"; }
|
||||
else {
|
||||
var match = arg.match(/^--ecma(\d+)$/);
|
||||
if (match)
|
||||
{ options.ecmaVersion = +match[1]; }
|
||||
else
|
||||
{ help(1); }
|
||||
}
|
||||
}
|
||||
|
||||
function run(code) {
|
||||
var result;
|
||||
try {
|
||||
if (!tokenize) {
|
||||
result = acorn.parse(code, options);
|
||||
} else {
|
||||
result = [];
|
||||
var tokenizer$$1 = acorn.tokenizer(code, options), token;
|
||||
do {
|
||||
token = tokenizer$$1.getToken();
|
||||
result.push(token);
|
||||
} while (token.type !== acorn.tokTypes.eof)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!silent) { console.log(JSON.stringify(result, null, compact ? null : 2)); }
|
||||
}
|
||||
|
||||
if (forceFile || infile && infile !== "-") {
|
||||
run(fs.readFileSync(infile, "utf8"));
|
||||
} else {
|
||||
var code = "";
|
||||
process.stdin.resume();
|
||||
process.stdin.on("data", function (chunk) { return code += chunk; });
|
||||
process.stdin.on("end", function () { return run(code); });
|
||||
}
|
66
node_modules/acorn/package.json
generated
vendored
@ -1,66 +0,0 @@
|
||||
{
|
||||
"_from": "acorn@^6.0.2",
|
||||
"_id": "acorn@6.0.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
|
||||
"_location": "/acorn",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "acorn@^6.0.2",
|
||||
"name": "acorn",
|
||||
"escapedName": "acorn",
|
||||
"rawSpec": "^6.0.2",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^6.0.2"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/espree"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
|
||||
"_shasum": "77377e7353b72ec5104550aa2d2097a2fd40b754",
|
||||
"_spec": "acorn@^6.0.2",
|
||||
"_where": "/home/erik/Documents/workspace_brackets/BME_Project_Ohm/om/node_modules/espree",
|
||||
"bin": {
|
||||
"acorn": "./bin/acorn"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/acornjs/acorn/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "ECMAScript parser",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"homepage": "https://github.com/acornjs/acorn",
|
||||
"license": "MIT",
|
||||
"main": "dist/acorn.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"url": "https://marijnhaverbeke.nl"
|
||||
},
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"url": "https://rreverser.com/"
|
||||
},
|
||||
{
|
||||
"name": "Adrian Heine",
|
||||
"url": "http://adrianheine.de"
|
||||
}
|
||||
],
|
||||
"module": "dist/acorn.mjs",
|
||||
"name": "acorn",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/acornjs/acorn.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "cd ..; npm run build:main && npm run build:bin"
|
||||
},
|
||||
"version": "6.0.4"
|
||||
}
|
20
node_modules/ajv/.tonic_example.js
generated
vendored
@ -1,20 +0,0 @@
|
||||
var Ajv = require('ajv');
|
||||
var ajv = new Ajv({allErrors: true});
|
||||
|
||||
var schema = {
|
||||
"properties": {
|
||||
"foo": { "type": "string" },
|
||||
"bar": { "type": "number", "maximum": 3 }
|
||||
}
|
||||
};
|
||||
|
||||
var validate = ajv.compile(schema);
|
||||
|
||||
test({"foo": "abc", "bar": 2});
|
||||
test({"foo": 2, "bar": 4});
|
||||
|
||||
function test(data) {
|
||||
var valid = validate(data);
|
||||
if (valid) console.log('Valid!');
|
||||
else console.log('Invalid: ' + ajv.errorsText(validate.errors));
|
||||
}
|
22
node_modules/ajv/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 Evgeny Poberezkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
1295
node_modules/ajv/README.md
generated
vendored
7030
node_modules/ajv/dist/ajv.bundle.js
generated
vendored
3
node_modules/ajv/dist/ajv.min.js
generated
vendored
1
node_modules/ajv/dist/ajv.min.js.map
generated
vendored
370
node_modules/ajv/lib/ajv.d.ts
generated
vendored
@ -1,370 +0,0 @@
|
||||
declare var ajv: {
|
||||
(options?: ajv.Options): ajv.Ajv;
|
||||
new (options?: ajv.Options): ajv.Ajv;
|
||||
ValidationError: ValidationError;
|
||||
MissingRefError: MissingRefError;
|
||||
$dataMetaSchema: object;
|
||||
}
|
||||
|
||||
declare namespace ajv {
|
||||
interface Ajv {
|
||||
/**
|
||||
* Validate data using schema
|
||||
* Schema will be compiled and cached (using serialized JSON as key, [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize by default).
|
||||
* @param {string|object|Boolean} schemaKeyRef key, ref or schema object
|
||||
* @param {Any} data to be validated
|
||||
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
|
||||
*/
|
||||
validate(schemaKeyRef: object | string | boolean, data: any): boolean | PromiseLike<any>;
|
||||
/**
|
||||
* Create validating function for passed schema.
|
||||
* @param {object|Boolean} schema schema object
|
||||
* @return {Function} validating function
|
||||
*/
|
||||
compile(schema: object | boolean): ValidateFunction;
|
||||
/**
|
||||
* Creates validating function for passed schema with asynchronous loading of missing schemas.
|
||||
* `loadSchema` option should be a function that accepts schema uri and node-style callback.
|
||||
* @this Ajv
|
||||
* @param {object|Boolean} schema schema object
|
||||
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
|
||||
* @param {Function} callback optional node-style callback, it is always called with 2 parameters: error (or null) and validating function.
|
||||
* @return {PromiseLike<ValidateFunction>} validating function
|
||||
*/
|
||||
compileAsync(schema: object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): PromiseLike<ValidateFunction>;
|
||||
/**
|
||||
* Adds schema to the instance.
|
||||
* @param {object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
|
||||
* @param {string} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addSchema(schema: Array<object> | object, key?: string): Ajv;
|
||||
/**
|
||||
* Add schema that will be used to validate other schemas
|
||||
* options in META_IGNORE_OPTIONS are alway set to false
|
||||
* @param {object} schema schema object
|
||||
* @param {string} key optional schema key
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addMetaSchema(schema: object, key?: string): Ajv;
|
||||
/**
|
||||
* Validate schema
|
||||
* @param {object|Boolean} schema schema to validate
|
||||
* @return {Boolean} true if schema is valid
|
||||
*/
|
||||
validateSchema(schema: object | boolean): boolean;
|
||||
/**
|
||||
* Get compiled schema from the instance by `key` or `ref`.
|
||||
* @param {string} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
|
||||
* @return {Function} schema validating function (with property `schema`).
|
||||
*/
|
||||
getSchema(keyRef: string): ValidateFunction;
|
||||
/**
|
||||
* Remove cached schema(s).
|
||||
* If no parameter is passed all schemas but meta-schemas are removed.
|
||||
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
|
||||
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
|
||||
* @param {string|object|RegExp|Boolean} schemaKeyRef key, ref, pattern to match key/ref or schema object
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
removeSchema(schemaKeyRef?: object | string | RegExp | boolean): Ajv;
|
||||
/**
|
||||
* Add custom format
|
||||
* @param {string} name format name
|
||||
* @param {string|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addFormat(name: string, format: FormatValidator | FormatDefinition): Ajv;
|
||||
/**
|
||||
* Define custom keyword
|
||||
* @this Ajv
|
||||
* @param {string} keyword custom keyword, should be a valid identifier, should be different from all standard, custom and macro keywords.
|
||||
* @param {object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
addKeyword(keyword: string, definition: KeywordDefinition): Ajv;
|
||||
/**
|
||||
* Get keyword definition
|
||||
* @this Ajv
|
||||
* @param {string} keyword pre-defined or custom keyword.
|
||||
* @return {object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
|
||||
*/
|
||||
getKeyword(keyword: string): object | boolean;
|
||||
/**
|
||||
* Remove keyword
|
||||
* @this Ajv
|
||||
* @param {string} keyword pre-defined or custom keyword.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
removeKeyword(keyword: string): Ajv;
|
||||
/**
|
||||
* Convert array of error message objects to string
|
||||
* @param {Array<object>} errors optional array of validation errors, if not passed errors from the instance are used.
|
||||
* @param {object} options optional options with properties `separator` and `dataVar`.
|
||||
* @return {string} human readable string with all errors descriptions
|
||||
*/
|
||||
errorsText(errors?: Array<ErrorObject> | null, options?: ErrorsTextOptions): string;
|
||||
errors?: Array<ErrorObject>;
|
||||
}
|
||||
|
||||
interface CustomLogger {
|
||||
log(...args: any[]): any;
|
||||
warn(...args: any[]): any;
|
||||
error(...args: any[]): any;
|
||||
}
|
||||
|
||||
interface ValidateFunction {
|
||||
(
|
||||
data: any,
|
||||
dataPath?: string,
|
||||
parentData?: object | Array<any>,
|
||||
parentDataProperty?: string | number,
|
||||
rootData?: object | Array<any>
|
||||
): boolean | PromiseLike<any>;
|
||||
schema?: object | boolean;
|
||||
errors?: null | Array<ErrorObject>;
|
||||
refs?: object;
|
||||
refVal?: Array<any>;
|
||||
root?: ValidateFunction | object;
|
||||
$async?: true;
|
||||
source?: object;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
$data?: boolean;
|
||||
allErrors?: boolean;
|
||||
verbose?: boolean;
|
||||
jsonPointers?: boolean;
|
||||
uniqueItems?: boolean;
|
||||
unicode?: boolean;
|
||||
format?: string;
|
||||
formats?: object;
|
||||
unknownFormats?: true | string[] | 'ignore';
|
||||
schemas?: Array<object> | object;
|
||||
schemaId?: '$id' | 'id' | 'auto';
|
||||
missingRefs?: true | 'ignore' | 'fail';
|
||||
extendRefs?: true | 'ignore' | 'fail';
|
||||
loadSchema?: (uri: string, cb?: (err: Error, schema: object) => void) => PromiseLike<object | boolean>;
|
||||
removeAdditional?: boolean | 'all' | 'failing';
|
||||
useDefaults?: boolean | 'shared';
|
||||
coerceTypes?: boolean | 'array';
|
||||
async?: boolean | string;
|
||||
transpile?: string | ((code: string) => string);
|
||||
meta?: boolean | object;
|
||||
validateSchema?: boolean | 'log';
|
||||
addUsedSchema?: boolean;
|
||||
inlineRefs?: boolean | number;
|
||||
passContext?: boolean;
|
||||
loopRequired?: number;
|
||||
ownProperties?: boolean;
|
||||
multipleOfPrecision?: boolean | number;
|
||||
errorDataPath?: string,
|
||||
messages?: boolean;
|
||||
sourceCode?: boolean;
|
||||
processCode?: (code: string) => string;
|
||||
cache?: object;
|
||||
logger?: CustomLogger | false
|
||||
}
|
||||
|
||||
type FormatValidator = string | RegExp | ((data: string) => boolean | PromiseLike<any>);
|
||||
type NumberFormatValidator = ((data: number) => boolean | PromiseLike<any>);
|
||||
|
||||
interface NumberFormatDefinition {
|
||||
type: "number",
|
||||
validate: NumberFormatValidator;
|
||||
compare?: (data1: number, data2: number) => number;
|
||||
async?: boolean;
|
||||
}
|
||||
|
||||
interface StringFormatDefinition {
|
||||
type?: "string",
|
||||
validate: FormatValidator;
|
||||
compare?: (data1: string, data2: string) => number;
|
||||
async?: boolean;
|
||||
}
|
||||
|
||||
type FormatDefinition = NumberFormatDefinition | StringFormatDefinition;
|
||||
|
||||
interface KeywordDefinition {
|
||||
type?: string | Array<string>;
|
||||
async?: boolean;
|
||||
$data?: boolean;
|
||||
errors?: boolean | string;
|
||||
metaSchema?: object;
|
||||
// schema: false makes validate not to expect schema (ValidateFunction)
|
||||
schema?: boolean;
|
||||
modifying?: boolean;
|
||||
valid?: boolean;
|
||||
// one and only one of the following properties should be present
|
||||
validate?: SchemaValidateFunction | ValidateFunction;
|
||||
compile?: (schema: any, parentSchema: object, it: CompilationContext) => ValidateFunction;
|
||||
macro?: (schema: any, parentSchema: object, it: CompilationContext) => object | boolean;
|
||||
inline?: (it: CompilationContext, keyword: string, schema: any, parentSchema: object) => string;
|
||||
}
|
||||
|
||||
interface CompilationContext {
|
||||
level: number;
|
||||
dataLevel: number;
|
||||
schema: any;
|
||||
schemaPath: string;
|
||||
baseId: string;
|
||||
async: boolean;
|
||||
opts: Options;
|
||||
formats: {
|
||||
[index: string]: FormatDefinition | undefined;
|
||||
};
|
||||
compositeRule: boolean;
|
||||
validate: (schema: object) => boolean;
|
||||
util: {
|
||||
copy(obj: any, target?: any): any;
|
||||
toHash(source: string[]): { [index: string]: true | undefined };
|
||||
equal(obj: any, target: any): boolean;
|
||||
getProperty(str: string): string;
|
||||
schemaHasRules(schema: object, rules: any): string;
|
||||
escapeQuotes(str: string): string;
|
||||
toQuotedString(str: string): string;
|
||||
getData(jsonPointer: string, dataLevel: number, paths: string[]): string;
|
||||
escapeJsonPointer(str: string): string;
|
||||
unescapeJsonPointer(str: string): string;
|
||||
escapeFragment(str: string): string;
|
||||
unescapeFragment(str: string): string;
|
||||
};
|
||||
self: Ajv;
|
||||
}
|
||||
|
||||
interface SchemaValidateFunction {
|
||||
(
|
||||
schema: any,
|
||||
data: any,
|
||||
parentSchema?: object,
|
||||
dataPath?: string,
|
||||
parentData?: object | Array<any>,
|
||||
parentDataProperty?: string | number,
|
||||
rootData?: object | Array<any>
|
||||
): boolean | PromiseLike<any>;
|
||||
errors?: Array<ErrorObject>;
|
||||
}
|
||||
|
||||
interface ErrorsTextOptions {
|
||||
separator?: string;
|
||||
dataVar?: string;
|
||||
}
|
||||
|
||||
interface ErrorObject {
|
||||
keyword: string;
|
||||
dataPath: string;
|
||||
schemaPath: string;
|
||||
params: ErrorParameters;
|
||||
// Added to validation errors of propertyNames keyword schema
|
||||
propertyName?: string;
|
||||
// Excluded if messages set to false.
|
||||
message?: string;
|
||||
// These are added with the `verbose` option.
|
||||
schema?: any;
|
||||
parentSchema?: object;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
type ErrorParameters = RefParams | LimitParams | AdditionalPropertiesParams |
|
||||
DependenciesParams | FormatParams | ComparisonParams |
|
||||
MultipleOfParams | PatternParams | RequiredParams |
|
||||
TypeParams | UniqueItemsParams | CustomParams |
|
||||
PatternRequiredParams | PropertyNamesParams |
|
||||
IfParams | SwitchParams | NoParams | EnumParams;
|
||||
|
||||
interface RefParams {
|
||||
ref: string;
|
||||
}
|
||||
|
||||
interface LimitParams {
|
||||
limit: number;
|
||||
}
|
||||
|
||||
interface AdditionalPropertiesParams {
|
||||
additionalProperty: string;
|
||||
}
|
||||
|
||||
interface DependenciesParams {
|
||||
property: string;
|
||||
missingProperty: string;
|
||||
depsCount: number;
|
||||
deps: string;
|
||||
}
|
||||
|
||||
interface FormatParams {
|
||||
format: string
|
||||
}
|
||||
|
||||
interface ComparisonParams {
|
||||
comparison: string;
|
||||
limit: number | string;
|
||||
exclusive: boolean;
|
||||
}
|
||||
|
||||
interface MultipleOfParams {
|
||||
multipleOf: number;
|
||||
}
|
||||
|
||||
interface PatternParams {
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
interface RequiredParams {
|
||||
missingProperty: string;
|
||||
}
|
||||
|
||||
interface TypeParams {
|
||||
type: string;
|
||||
}
|
||||
|
||||
interface UniqueItemsParams {
|
||||
i: number;
|
||||
j: number;
|
||||
}
|
||||
|
||||
interface CustomParams {
|
||||
keyword: string;
|
||||
}
|
||||
|
||||
interface PatternRequiredParams {
|
||||
missingPattern: string;
|
||||
}
|
||||
|
||||
interface PropertyNamesParams {
|
||||
propertyName: string;
|
||||
}
|
||||
|
||||
interface IfParams {
|
||||
failingKeyword: string;
|
||||
}
|
||||
|
||||
interface SwitchParams {
|
||||
caseIndex: number;
|
||||
}
|
||||
|
||||
interface NoParams {}
|
||||
|
||||
interface EnumParams {
|
||||
allowedValues: Array<any>;
|
||||
}
|
||||
}
|
||||
|
||||
declare class ValidationError extends Error {
|
||||
constructor(errors: Array<ajv.ErrorObject>);
|
||||
|
||||
message: string;
|
||||
errors: Array<ajv.ErrorObject>;
|
||||
ajv: true;
|
||||
validation: true;
|
||||
}
|
||||
|
||||
declare class MissingRefError extends Error {
|
||||
constructor(baseId: string, ref: string, message?: string);
|
||||
static message: (baseId: string, ref: string) => string;
|
||||
|
||||
message: string;
|
||||
missingRef: string;
|
||||
missingSchema: string;
|
||||
}
|
||||
|
||||
export = ajv;
|
503
node_modules/ajv/lib/ajv.js
generated
vendored
@ -1,503 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var compileSchema = require('./compile')
|
||||
, resolve = require('./compile/resolve')
|
||||
, Cache = require('./cache')
|
||||
, SchemaObject = require('./compile/schema_obj')
|
||||
, stableStringify = require('fast-json-stable-stringify')
|
||||
, formats = require('./compile/formats')
|
||||
, rules = require('./compile/rules')
|
||||
, $dataMetaSchema = require('./data')
|
||||
, util = require('./compile/util');
|
||||
|
||||
module.exports = Ajv;
|
||||
|
||||
Ajv.prototype.validate = validate;
|
||||
Ajv.prototype.compile = compile;
|
||||
Ajv.prototype.addSchema = addSchema;
|
||||
Ajv.prototype.addMetaSchema = addMetaSchema;
|
||||
Ajv.prototype.validateSchema = validateSchema;
|
||||
Ajv.prototype.getSchema = getSchema;
|
||||
Ajv.prototype.removeSchema = removeSchema;
|
||||
Ajv.prototype.addFormat = addFormat;
|
||||
Ajv.prototype.errorsText = errorsText;
|
||||
|
||||
Ajv.prototype._addSchema = _addSchema;
|
||||
Ajv.prototype._compile = _compile;
|
||||
|
||||
Ajv.prototype.compileAsync = require('./compile/async');
|
||||
var customKeyword = require('./keyword');
|
||||
Ajv.prototype.addKeyword = customKeyword.add;
|
||||
Ajv.prototype.getKeyword = customKeyword.get;
|
||||
Ajv.prototype.removeKeyword = customKeyword.remove;
|
||||
|
||||
var errorClasses = require('./compile/error_classes');
|
||||
Ajv.ValidationError = errorClasses.Validation;
|
||||
Ajv.MissingRefError = errorClasses.MissingRef;
|
||||
Ajv.$dataMetaSchema = $dataMetaSchema;
|
||||
|
||||
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
|
||||
|
||||
var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ];
|
||||
var META_SUPPORT_DATA = ['/properties'];
|
||||
|
||||
/**
|
||||
* Creates validator instance.
|
||||
* Usage: `Ajv(opts)`
|
||||
* @param {Object} opts optional options
|
||||
* @return {Object} ajv instance
|
||||
*/
|
||||
function Ajv(opts) {
|
||||
if (!(this instanceof Ajv)) return new Ajv(opts);
|
||||
opts = this._opts = util.copy(opts) || {};
|
||||
setLogger(this);
|
||||
this._schemas = {};
|
||||
this._refs = {};
|
||||
this._fragments = {};
|
||||
this._formats = formats(opts.format);
|
||||
var schemaUriFormat = this._schemaUriFormat = this._formats['uri-reference'];
|
||||
this._schemaUriFormatFunc = function (str) { return schemaUriFormat.test(str); };
|
||||
|
||||
this._cache = opts.cache || new Cache;
|
||||
this._loadingSchemas = {};
|
||||
this._compilations = [];
|
||||
this.RULES = rules();
|
||||
this._getId = chooseGetId(opts);
|
||||
|
||||
opts.loopRequired = opts.loopRequired || Infinity;
|
||||
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
|
||||
if (opts.serialize === undefined) opts.serialize = stableStringify;
|
||||
this._metaOpts = getMetaSchemaOptions(this);
|
||||
|
||||
if (opts.formats) addInitialFormats(this);
|
||||
addDraft6MetaSchema(this);
|
||||
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
|
||||
addInitialSchemas(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Validate data using schema
|
||||
* Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize.
|
||||
* @this Ajv
|
||||
* @param {String|Object} schemaKeyRef key, ref or schema object
|
||||
* @param {Any} data to be validated
|
||||
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
|
||||
*/
|
||||
function validate(schemaKeyRef, data) {
|
||||
var v;
|
||||
if (typeof schemaKeyRef == 'string') {
|
||||
v = this.getSchema(schemaKeyRef);
|
||||
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
|
||||
} else {
|
||||
var schemaObj = this._addSchema(schemaKeyRef);
|
||||
v = schemaObj.validate || this._compile(schemaObj);
|
||||
}
|
||||
|
||||
var valid = v(data);
|
||||
if (v.$async !== true) this.errors = v.errors;
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create validating function for passed schema.
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords.
|
||||
* @return {Function} validating function
|
||||
*/
|
||||
function compile(schema, _meta) {
|
||||
var schemaObj = this._addSchema(schema, undefined, _meta);
|
||||
return schemaObj.validate || this._compile(schemaObj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds schema to the instance.
|
||||
* @this Ajv
|
||||
* @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
|
||||
* @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
|
||||
* @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead.
|
||||
* @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addSchema(schema, key, _skipValidation, _meta) {
|
||||
if (Array.isArray(schema)){
|
||||
for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta);
|
||||
return this;
|
||||
}
|
||||
var id = this._getId(schema);
|
||||
if (id !== undefined && typeof id != 'string')
|
||||
throw new Error('schema id must be string');
|
||||
key = resolve.normalizeId(key || id);
|
||||
checkUnique(this, key);
|
||||
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add schema that will be used to validate other schemas
|
||||
* options in META_IGNORE_OPTIONS are alway set to false
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {String} key optional schema key
|
||||
* @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addMetaSchema(schema, key, skipValidation) {
|
||||
this.addSchema(schema, key, skipValidation, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate schema
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to validate
|
||||
* @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid
|
||||
* @return {Boolean} true if schema is valid
|
||||
*/
|
||||
function validateSchema(schema, throwOrLogError) {
|
||||
var $schema = schema.$schema;
|
||||
if ($schema !== undefined && typeof $schema != 'string')
|
||||
throw new Error('$schema must be a string');
|
||||
$schema = $schema || this._opts.defaultMeta || defaultMeta(this);
|
||||
if (!$schema) {
|
||||
this.logger.warn('meta-schema not available');
|
||||
this.errors = null;
|
||||
return true;
|
||||
}
|
||||
var currentUriFormat = this._formats.uri;
|
||||
this._formats.uri = typeof currentUriFormat == 'function'
|
||||
? this._schemaUriFormatFunc
|
||||
: this._schemaUriFormat;
|
||||
var valid;
|
||||
try { valid = this.validate($schema, schema); }
|
||||
finally { this._formats.uri = currentUriFormat; }
|
||||
if (!valid && throwOrLogError) {
|
||||
var message = 'schema is invalid: ' + this.errorsText();
|
||||
if (this._opts.validateSchema == 'log') this.logger.error(message);
|
||||
else throw new Error(message);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
function defaultMeta(self) {
|
||||
var meta = self._opts.meta;
|
||||
self._opts.defaultMeta = typeof meta == 'object'
|
||||
? self._getId(meta) || meta
|
||||
: self.getSchema(META_SCHEMA_ID)
|
||||
? META_SCHEMA_ID
|
||||
: undefined;
|
||||
return self._opts.defaultMeta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get compiled schema from the instance by `key` or `ref`.
|
||||
* @this Ajv
|
||||
* @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
|
||||
* @return {Function} schema validating function (with property `schema`).
|
||||
*/
|
||||
function getSchema(keyRef) {
|
||||
var schemaObj = _getSchemaObj(this, keyRef);
|
||||
switch (typeof schemaObj) {
|
||||
case 'object': return schemaObj.validate || this._compile(schemaObj);
|
||||
case 'string': return this.getSchema(schemaObj);
|
||||
case 'undefined': return _getSchemaFragment(this, keyRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _getSchemaFragment(self, ref) {
|
||||
var res = resolve.schema.call(self, { schema: {} }, ref);
|
||||
if (res) {
|
||||
var schema = res.schema
|
||||
, root = res.root
|
||||
, baseId = res.baseId;
|
||||
var v = compileSchema.call(self, schema, root, undefined, baseId);
|
||||
self._fragments[ref] = new SchemaObject({
|
||||
ref: ref,
|
||||
fragment: true,
|
||||
schema: schema,
|
||||
root: root,
|
||||
baseId: baseId,
|
||||
validate: v
|
||||
});
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _getSchemaObj(self, keyRef) {
|
||||
keyRef = resolve.normalizeId(keyRef);
|
||||
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove cached schema(s).
|
||||
* If no parameter is passed all schemas but meta-schemas are removed.
|
||||
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
|
||||
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
|
||||
* @this Ajv
|
||||
* @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function removeSchema(schemaKeyRef) {
|
||||
if (schemaKeyRef instanceof RegExp) {
|
||||
_removeAllSchemas(this, this._schemas, schemaKeyRef);
|
||||
_removeAllSchemas(this, this._refs, schemaKeyRef);
|
||||
return this;
|
||||
}
|
||||
switch (typeof schemaKeyRef) {
|
||||
case 'undefined':
|
||||
_removeAllSchemas(this, this._schemas);
|
||||
_removeAllSchemas(this, this._refs);
|
||||
this._cache.clear();
|
||||
return this;
|
||||
case 'string':
|
||||
var schemaObj = _getSchemaObj(this, schemaKeyRef);
|
||||
if (schemaObj) this._cache.del(schemaObj.cacheKey);
|
||||
delete this._schemas[schemaKeyRef];
|
||||
delete this._refs[schemaKeyRef];
|
||||
return this;
|
||||
case 'object':
|
||||
var serialize = this._opts.serialize;
|
||||
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef;
|
||||
this._cache.del(cacheKey);
|
||||
var id = this._getId(schemaKeyRef);
|
||||
if (id) {
|
||||
id = resolve.normalizeId(id);
|
||||
delete this._schemas[id];
|
||||
delete this._refs[id];
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function _removeAllSchemas(self, schemas, regex) {
|
||||
for (var keyRef in schemas) {
|
||||
var schemaObj = schemas[keyRef];
|
||||
if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
|
||||
self._cache.del(schemaObj.cacheKey);
|
||||
delete schemas[keyRef];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
|
||||
if (typeof schema != 'object' && typeof schema != 'boolean')
|
||||
throw new Error('schema should be object or boolean');
|
||||
var serialize = this._opts.serialize;
|
||||
var cacheKey = serialize ? serialize(schema) : schema;
|
||||
var cached = this._cache.get(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
|
||||
|
||||
var id = resolve.normalizeId(this._getId(schema));
|
||||
if (id && shouldAddSchema) checkUnique(this, id);
|
||||
|
||||
var willValidate = this._opts.validateSchema !== false && !skipValidation;
|
||||
var recursiveMeta;
|
||||
if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema)))
|
||||
this.validateSchema(schema, true);
|
||||
|
||||
var localRefs = resolve.ids.call(this, schema);
|
||||
|
||||
var schemaObj = new SchemaObject({
|
||||
id: id,
|
||||
schema: schema,
|
||||
localRefs: localRefs,
|
||||
cacheKey: cacheKey,
|
||||
meta: meta
|
||||
});
|
||||
|
||||
if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj;
|
||||
this._cache.put(cacheKey, schemaObj);
|
||||
|
||||
if (willValidate && recursiveMeta) this.validateSchema(schema, true);
|
||||
|
||||
return schemaObj;
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function _compile(schemaObj, root) {
|
||||
if (schemaObj.compiling) {
|
||||
schemaObj.validate = callValidate;
|
||||
callValidate.schema = schemaObj.schema;
|
||||
callValidate.errors = null;
|
||||
callValidate.root = root ? root : callValidate;
|
||||
if (schemaObj.schema.$async === true)
|
||||
callValidate.$async = true;
|
||||
return callValidate;
|
||||
}
|
||||
schemaObj.compiling = true;
|
||||
|
||||
var currentOpts;
|
||||
if (schemaObj.meta) {
|
||||
currentOpts = this._opts;
|
||||
this._opts = this._metaOpts;
|
||||
}
|
||||
|
||||
var v;
|
||||
try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); }
|
||||
catch(e) {
|
||||
delete schemaObj.validate;
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
schemaObj.compiling = false;
|
||||
if (schemaObj.meta) this._opts = currentOpts;
|
||||
}
|
||||
|
||||
schemaObj.validate = v;
|
||||
schemaObj.refs = v.refs;
|
||||
schemaObj.refVal = v.refVal;
|
||||
schemaObj.root = v.root;
|
||||
return v;
|
||||
|
||||
|
||||
/* @this {*} - custom context, see passContext option */
|
||||
function callValidate() {
|
||||
/* jshint validthis: true */
|
||||
var _validate = schemaObj.validate;
|
||||
var result = _validate.apply(this, arguments);
|
||||
callValidate.errors = _validate.errors;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function chooseGetId(opts) {
|
||||
switch (opts.schemaId) {
|
||||
case 'auto': return _get$IdOrId;
|
||||
case 'id': return _getId;
|
||||
default: return _get$Id;
|
||||
}
|
||||
}
|
||||
|
||||
/* @this Ajv */
|
||||
function _getId(schema) {
|
||||
if (schema.$id) this.logger.warn('schema $id ignored', schema.$id);
|
||||
return schema.id;
|
||||
}
|
||||
|
||||
/* @this Ajv */
|
||||
function _get$Id(schema) {
|
||||
if (schema.id) this.logger.warn('schema id ignored', schema.id);
|
||||
return schema.$id;
|
||||
}
|
||||
|
||||
|
||||
function _get$IdOrId(schema) {
|
||||
if (schema.$id && schema.id && schema.$id != schema.id)
|
||||
throw new Error('schema $id is different from id');
|
||||
return schema.$id || schema.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert array of error message objects to string
|
||||
* @this Ajv
|
||||
* @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used.
|
||||
* @param {Object} options optional options with properties `separator` and `dataVar`.
|
||||
* @return {String} human readable string with all errors descriptions
|
||||
*/
|
||||
function errorsText(errors, options) {
|
||||
errors = errors || this.errors;
|
||||
if (!errors) return 'No errors';
|
||||
options = options || {};
|
||||
var separator = options.separator === undefined ? ', ' : options.separator;
|
||||
var dataVar = options.dataVar === undefined ? 'data' : options.dataVar;
|
||||
|
||||
var text = '';
|
||||
for (var i=0; i<errors.length; i++) {
|
||||
var e = errors[i];
|
||||
if (e) text += dataVar + e.dataPath + ' ' + e.message + separator;
|
||||
}
|
||||
return text.slice(0, -separator.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add custom format
|
||||
* @this Ajv
|
||||
* @param {String} name format name
|
||||
* @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
|
||||
* @return {Ajv} this for method chaining
|
||||
*/
|
||||
function addFormat(name, format) {
|
||||
if (typeof format == 'string') format = new RegExp(format);
|
||||
this._formats[name] = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function addDraft6MetaSchema(self) {
|
||||
var $dataSchema;
|
||||
if (self._opts.$data) {
|
||||
$dataSchema = require('./refs/data.json');
|
||||
self.addMetaSchema($dataSchema, $dataSchema.$id, true);
|
||||
}
|
||||
if (self._opts.meta === false) return;
|
||||
var metaSchema = require('./refs/json-schema-draft-07.json');
|
||||
if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA);
|
||||
self.addMetaSchema(metaSchema, META_SCHEMA_ID, true);
|
||||
self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID;
|
||||
}
|
||||
|
||||
|
||||
function addInitialSchemas(self) {
|
||||
var optsSchemas = self._opts.schemas;
|
||||
if (!optsSchemas) return;
|
||||
if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas);
|
||||
else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key);
|
||||
}
|
||||
|
||||
|
||||
function addInitialFormats(self) {
|
||||
for (var name in self._opts.formats) {
|
||||
var format = self._opts.formats[name];
|
||||
self.addFormat(name, format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkUnique(self, id) {
|
||||
if (self._schemas[id] || self._refs[id])
|
||||
throw new Error('schema with key or id "' + id + '" already exists');
|
||||
}
|
||||
|
||||
|
||||
function getMetaSchemaOptions(self) {
|
||||
var metaOpts = util.copy(self._opts);
|
||||
for (var i=0; i<META_IGNORE_OPTIONS.length; i++)
|
||||
delete metaOpts[META_IGNORE_OPTIONS[i]];
|
||||
return metaOpts;
|
||||
}
|
||||
|
||||
|
||||
function setLogger(self) {
|
||||
var logger = self._opts.logger;
|
||||
if (logger === false) {
|
||||
self.logger = {log: noop, warn: noop, error: noop};
|
||||
} else {
|
||||
if (logger === undefined) logger = console;
|
||||
if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error))
|
||||
throw new Error('logger must implement log, warn and error methods');
|
||||
self.logger = logger;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function noop() {}
|
26
node_modules/ajv/lib/cache.js
generated
vendored
@ -1,26 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
var Cache = module.exports = function Cache() {
|
||||
this._cache = {};
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.put = function Cache_put(key, value) {
|
||||
this._cache[key] = value;
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.get = function Cache_get(key) {
|
||||
return this._cache[key];
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.del = function Cache_del(key) {
|
||||
delete this._cache[key];
|
||||
};
|
||||
|
||||
|
||||
Cache.prototype.clear = function Cache_clear() {
|
||||
this._cache = {};
|
||||
};
|
90
node_modules/ajv/lib/compile/async.js
generated
vendored
@ -1,90 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var MissingRefError = require('./error_classes').MissingRef;
|
||||
|
||||
module.exports = compileAsync;
|
||||
|
||||
|
||||
/**
|
||||
* Creates validating function for passed schema with asynchronous loading of missing schemas.
|
||||
* `loadSchema` option should be a function that accepts schema uri and returns promise that resolves with the schema.
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
|
||||
* @param {Function} callback an optional node-style callback, it is called with 2 parameters: error (or null) and validating function.
|
||||
* @return {Promise} promise that resolves with a validating function.
|
||||
*/
|
||||
function compileAsync(schema, meta, callback) {
|
||||
/* eslint no-shadow: 0 */
|
||||
/* global Promise */
|
||||
/* jshint validthis: true */
|
||||
var self = this;
|
||||
if (typeof this._opts.loadSchema != 'function')
|
||||
throw new Error('options.loadSchema should be a function');
|
||||
|
||||
if (typeof meta == 'function') {
|
||||
callback = meta;
|
||||
meta = undefined;
|
||||
}
|
||||
|
||||
var p = loadMetaSchemaOf(schema).then(function () {
|
||||
var schemaObj = self._addSchema(schema, undefined, meta);
|
||||
return schemaObj.validate || _compileAsync(schemaObj);
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
p.then(
|
||||
function(v) { callback(null, v); },
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
||||
|
||||
function loadMetaSchemaOf(sch) {
|
||||
var $schema = sch.$schema;
|
||||
return $schema && !self.getSchema($schema)
|
||||
? compileAsync.call(self, { $ref: $schema }, true)
|
||||
: Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
function _compileAsync(schemaObj) {
|
||||
try { return self._compile(schemaObj); }
|
||||
catch(e) {
|
||||
if (e instanceof MissingRefError) return loadMissingSchema(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
function loadMissingSchema(e) {
|
||||
var ref = e.missingSchema;
|
||||
if (added(ref)) throw new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved');
|
||||
|
||||
var schemaPromise = self._loadingSchemas[ref];
|
||||
if (!schemaPromise) {
|
||||
schemaPromise = self._loadingSchemas[ref] = self._opts.loadSchema(ref);
|
||||
schemaPromise.then(removePromise, removePromise);
|
||||
}
|
||||
|
||||
return schemaPromise.then(function (sch) {
|
||||
if (!added(ref)) {
|
||||
return loadMetaSchemaOf(sch).then(function () {
|
||||
if (!added(ref)) self.addSchema(sch, ref, undefined, meta);
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
return _compileAsync(schemaObj);
|
||||
});
|
||||
|
||||
function removePromise() {
|
||||
delete self._loadingSchemas[ref];
|
||||
}
|
||||
|
||||
function added(ref) {
|
||||
return self._refs[ref] || self._schemas[ref];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
node_modules/ajv/lib/compile/equal.js
generated
vendored
@ -1,3 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('fast-deep-equal');
|
34
node_modules/ajv/lib/compile/error_classes.js
generated
vendored
@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var resolve = require('./resolve');
|
||||
|
||||
module.exports = {
|
||||
Validation: errorSubclass(ValidationError),
|
||||
MissingRef: errorSubclass(MissingRefError)
|
||||
};
|
||||
|
||||
|
||||
function ValidationError(errors) {
|
||||
this.message = 'validation failed';
|
||||
this.errors = errors;
|
||||
this.ajv = this.validation = true;
|
||||
}
|
||||
|
||||
|
||||
MissingRefError.message = function (baseId, ref) {
|
||||
return 'can\'t resolve reference ' + ref + ' from id ' + baseId;
|
||||
};
|
||||
|
||||
|
||||
function MissingRefError(baseId, ref, message) {
|
||||
this.message = message || MissingRefError.message(baseId, ref);
|
||||
this.missingRef = resolve.url(baseId, ref);
|
||||
this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef));
|
||||
}
|
||||
|
||||
|
||||
function errorSubclass(Subclass) {
|
||||
Subclass.prototype = Object.create(Error.prototype);
|
||||
Subclass.prototype.constructor = Subclass;
|
||||
return Subclass;
|
||||
}
|
149
node_modules/ajv/lib/compile/formats.js
generated
vendored
@ -1,149 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./util');
|
||||
|
||||
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
||||
var DAYS = [0,31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
|
||||
var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i;
|
||||
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
||||
var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
|
||||
// uri-template: https://tools.ietf.org/html/rfc6570
|
||||
var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i;
|
||||
// For the source: https://gist.github.com/dperini/729294
|
||||
// For test cases: https://mathiasbynens.be/demo/url-regex
|
||||
// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983.
|
||||
// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu;
|
||||
var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i;
|
||||
var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
|
||||
var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
|
||||
var JSON_POINTER_URI_FRAGMENT = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
|
||||
var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
|
||||
|
||||
|
||||
module.exports = formats;
|
||||
|
||||
function formats(mode) {
|
||||
mode = mode == 'full' ? 'full' : 'fast';
|
||||
return util.copy(formats[mode]);
|
||||
}
|
||||
|
||||
|
||||
formats.fast = {
|
||||
// date: http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/,
|
||||
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,
|
||||
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,
|
||||
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
|
||||
uri: /^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,
|
||||
'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
|
||||
'uri-template': URITEMPLATE,
|
||||
url: URL,
|
||||
// email (sources from jsen validator):
|
||||
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
|
||||
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation')
|
||||
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,
|
||||
hostname: HOSTNAME,
|
||||
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
|
||||
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
|
||||
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
|
||||
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
|
||||
regex: regex,
|
||||
// uuid: http://tools.ietf.org/html/rfc4122
|
||||
uuid: UUID,
|
||||
// JSON-pointer: https://tools.ietf.org/html/rfc6901
|
||||
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
|
||||
'json-pointer': JSON_POINTER,
|
||||
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
|
||||
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
|
||||
'relative-json-pointer': RELATIVE_JSON_POINTER
|
||||
};
|
||||
|
||||
|
||||
formats.full = {
|
||||
date: date,
|
||||
time: time,
|
||||
'date-time': date_time,
|
||||
uri: uri,
|
||||
'uri-reference': URIREF,
|
||||
'uri-template': URITEMPLATE,
|
||||
url: URL,
|
||||
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
|
||||
hostname: hostname,
|
||||
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
|
||||
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
|
||||
regex: regex,
|
||||
uuid: UUID,
|
||||
'json-pointer': JSON_POINTER,
|
||||
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
|
||||
'relative-json-pointer': RELATIVE_JSON_POINTER
|
||||
};
|
||||
|
||||
|
||||
function isLeapYear(year) {
|
||||
// https://tools.ietf.org/html/rfc3339#appendix-C
|
||||
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
||||
}
|
||||
|
||||
|
||||
function date(str) {
|
||||
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
var matches = str.match(DATE);
|
||||
if (!matches) return false;
|
||||
|
||||
var year = +matches[1];
|
||||
var month = +matches[2];
|
||||
var day = +matches[3];
|
||||
|
||||
return month >= 1 && month <= 12 && day >= 1 &&
|
||||
day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]);
|
||||
}
|
||||
|
||||
|
||||
function time(str, full) {
|
||||
var matches = str.match(TIME);
|
||||
if (!matches) return false;
|
||||
|
||||
var hour = matches[1];
|
||||
var minute = matches[2];
|
||||
var second = matches[3];
|
||||
var timeZone = matches[5];
|
||||
return ((hour <= 23 && minute <= 59 && second <= 59) ||
|
||||
(hour == 23 && minute == 59 && second == 60)) &&
|
||||
(!full || timeZone);
|
||||
}
|
||||
|
||||
|
||||
var DATE_TIME_SEPARATOR = /t|\s/i;
|
||||
function date_time(str) {
|
||||
// http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
var dateTime = str.split(DATE_TIME_SEPARATOR);
|
||||
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true);
|
||||
}
|
||||
|
||||
|
||||
function hostname(str) {
|
||||
// https://tools.ietf.org/html/rfc1034#section-3.5
|
||||
// https://tools.ietf.org/html/rfc1123#section-2
|
||||
return str.length <= 255 && HOSTNAME.test(str);
|
||||
}
|
||||
|
||||
|
||||
var NOT_URI_FRAGMENT = /\/|:/;
|
||||
function uri(str) {
|
||||
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
|
||||
return NOT_URI_FRAGMENT.test(str) && URI.test(str);
|
||||
}
|
||||
|
||||
|
||||
var Z_ANCHOR = /[^\\]\\Z/;
|
||||
function regex(str) {
|
||||
if (Z_ANCHOR.test(str)) return false;
|
||||
try {
|
||||
new RegExp(str);
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
379
node_modules/ajv/lib/compile/index.js
generated
vendored
@ -1,379 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var resolve = require('./resolve')
|
||||
, util = require('./util')
|
||||
, errorClasses = require('./error_classes')
|
||||
, stableStringify = require('fast-json-stable-stringify');
|
||||
|
||||
var validateGenerator = require('../dotjs/validate');
|
||||
|
||||
/**
|
||||
* Functions below are used inside compiled validations function
|
||||
*/
|
||||
|
||||
var ucs2length = util.ucs2length;
|
||||
var equal = require('fast-deep-equal');
|
||||
|
||||
// this error is thrown by async schemas to return validation errors via exception
|
||||
var ValidationError = errorClasses.Validation;
|
||||
|
||||
module.exports = compile;
|
||||
|
||||
|
||||
/**
|
||||
* Compiles schema to validation function
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema object
|
||||
* @param {Object} root object with information about the root schema for this schema
|
||||
* @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution
|
||||
* @param {String} baseId base ID for IDs in the schema
|
||||
* @return {Function} validation function
|
||||
*/
|
||||
function compile(schema, root, localRefs, baseId) {
|
||||
/* jshint validthis: true, evil: true */
|
||||
/* eslint no-shadow: 0 */
|
||||
var self = this
|
||||
, opts = this._opts
|
||||
, refVal = [ undefined ]
|
||||
, refs = {}
|
||||
, patterns = []
|
||||
, patternsHash = {}
|
||||
, defaults = []
|
||||
, defaultsHash = {}
|
||||
, customRules = [];
|
||||
|
||||
root = root || { schema: schema, refVal: refVal, refs: refs };
|
||||
|
||||
var c = checkCompiling.call(this, schema, root, baseId);
|
||||
var compilation = this._compilations[c.index];
|
||||
if (c.compiling) return (compilation.callValidate = callValidate);
|
||||
|
||||
var formats = this._formats;
|
||||
var RULES = this.RULES;
|
||||
|
||||
try {
|
||||
var v = localCompile(schema, root, localRefs, baseId);
|
||||
compilation.validate = v;
|
||||
var cv = compilation.callValidate;
|
||||
if (cv) {
|
||||
cv.schema = v.schema;
|
||||
cv.errors = null;
|
||||
cv.refs = v.refs;
|
||||
cv.refVal = v.refVal;
|
||||
cv.root = v.root;
|
||||
cv.$async = v.$async;
|
||||
if (opts.sourceCode) cv.source = v.source;
|
||||
}
|
||||
return v;
|
||||
} finally {
|
||||
endCompiling.call(this, schema, root, baseId);
|
||||
}
|
||||
|
||||
/* @this {*} - custom context, see passContext option */
|
||||
function callValidate() {
|
||||
/* jshint validthis: true */
|
||||
var validate = compilation.validate;
|
||||
var result = validate.apply(this, arguments);
|
||||
callValidate.errors = validate.errors;
|
||||
return result;
|
||||
}
|
||||
|
||||
function localCompile(_schema, _root, localRefs, baseId) {
|
||||
var isRoot = !_root || (_root && _root.schema == _schema);
|
||||
if (_root.schema != root.schema)
|
||||
return compile.call(self, _schema, _root, localRefs, baseId);
|
||||
|
||||
var $async = _schema.$async === true;
|
||||
|
||||
var sourceCode = validateGenerator({
|
||||
isTop: true,
|
||||
schema: _schema,
|
||||
isRoot: isRoot,
|
||||
baseId: baseId,
|
||||
root: _root,
|
||||
schemaPath: '',
|
||||
errSchemaPath: '#',
|
||||
errorPath: '""',
|
||||
MissingRefError: errorClasses.MissingRef,
|
||||
RULES: RULES,
|
||||
validate: validateGenerator,
|
||||
util: util,
|
||||
resolve: resolve,
|
||||
resolveRef: resolveRef,
|
||||
usePattern: usePattern,
|
||||
useDefault: useDefault,
|
||||
useCustomRule: useCustomRule,
|
||||
opts: opts,
|
||||
formats: formats,
|
||||
logger: self.logger,
|
||||
self: self
|
||||
});
|
||||
|
||||
sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode)
|
||||
+ vars(defaults, defaultCode) + vars(customRules, customRuleCode)
|
||||
+ sourceCode;
|
||||
|
||||
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
|
||||
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode));
|
||||
var validate;
|
||||
try {
|
||||
var makeValidate = new Function(
|
||||
'self',
|
||||
'RULES',
|
||||
'formats',
|
||||
'root',
|
||||
'refVal',
|
||||
'defaults',
|
||||
'customRules',
|
||||
'equal',
|
||||
'ucs2length',
|
||||
'ValidationError',
|
||||
sourceCode
|
||||
);
|
||||
|
||||
validate = makeValidate(
|
||||
self,
|
||||
RULES,
|
||||
formats,
|
||||
root,
|
||||
refVal,
|
||||
defaults,
|
||||
customRules,
|
||||
equal,
|
||||
ucs2length,
|
||||
ValidationError
|
||||
);
|
||||
|
||||
refVal[0] = validate;
|
||||
} catch(e) {
|
||||
self.logger.error('Error compiling schema, function code:', sourceCode);
|
||||
throw e;
|
||||
}
|
||||
|
||||
validate.schema = _schema;
|
||||
validate.errors = null;
|
||||
validate.refs = refs;
|
||||
validate.refVal = refVal;
|
||||
validate.root = isRoot ? validate : _root;
|
||||
if ($async) validate.$async = true;
|
||||
if (opts.sourceCode === true) {
|
||||
validate.source = {
|
||||
code: sourceCode,
|
||||
patterns: patterns,
|
||||
defaults: defaults
|
||||
};
|
||||
}
|
||||
|
||||
return validate;
|
||||
}
|
||||
|
||||
function resolveRef(baseId, ref, isRoot) {
|
||||
ref = resolve.url(baseId, ref);
|
||||
var refIndex = refs[ref];
|
||||
var _refVal, refCode;
|
||||
if (refIndex !== undefined) {
|
||||
_refVal = refVal[refIndex];
|
||||
refCode = 'refVal[' + refIndex + ']';
|
||||
return resolvedRef(_refVal, refCode);
|
||||
}
|
||||
if (!isRoot && root.refs) {
|
||||
var rootRefId = root.refs[ref];
|
||||
if (rootRefId !== undefined) {
|
||||
_refVal = root.refVal[rootRefId];
|
||||
refCode = addLocalRef(ref, _refVal);
|
||||
return resolvedRef(_refVal, refCode);
|
||||
}
|
||||
}
|
||||
|
||||
refCode = addLocalRef(ref);
|
||||
var v = resolve.call(self, localCompile, root, ref);
|
||||
if (v === undefined) {
|
||||
var localSchema = localRefs && localRefs[ref];
|
||||
if (localSchema) {
|
||||
v = resolve.inlineRef(localSchema, opts.inlineRefs)
|
||||
? localSchema
|
||||
: compile.call(self, localSchema, root, localRefs, baseId);
|
||||
}
|
||||
}
|
||||
|
||||
if (v === undefined) {
|
||||
removeLocalRef(ref);
|
||||
} else {
|
||||
replaceLocalRef(ref, v);
|
||||
return resolvedRef(v, refCode);
|
||||
}
|
||||
}
|
||||
|
||||
function addLocalRef(ref, v) {
|
||||
var refId = refVal.length;
|
||||
refVal[refId] = v;
|
||||
refs[ref] = refId;
|
||||
return 'refVal' + refId;
|
||||
}
|
||||
|
||||
function removeLocalRef(ref) {
|
||||
delete refs[ref];
|
||||
}
|
||||
|
||||
function replaceLocalRef(ref, v) {
|
||||
var refId = refs[ref];
|
||||
refVal[refId] = v;
|
||||
}
|
||||
|
||||
function resolvedRef(refVal, code) {
|
||||
return typeof refVal == 'object' || typeof refVal == 'boolean'
|
||||
? { code: code, schema: refVal, inline: true }
|
||||
: { code: code, $async: refVal && !!refVal.$async };
|
||||
}
|
||||
|
||||
function usePattern(regexStr) {
|
||||
var index = patternsHash[regexStr];
|
||||
if (index === undefined) {
|
||||
index = patternsHash[regexStr] = patterns.length;
|
||||
patterns[index] = regexStr;
|
||||
}
|
||||
return 'pattern' + index;
|
||||
}
|
||||
|
||||
function useDefault(value) {
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
return '' + value;
|
||||
case 'string':
|
||||
return util.toQuotedString(value);
|
||||
case 'object':
|
||||
if (value === null) return 'null';
|
||||
var valueStr = stableStringify(value);
|
||||
var index = defaultsHash[valueStr];
|
||||
if (index === undefined) {
|
||||
index = defaultsHash[valueStr] = defaults.length;
|
||||
defaults[index] = value;
|
||||
}
|
||||
return 'default' + index;
|
||||
}
|
||||
}
|
||||
|
||||
function useCustomRule(rule, schema, parentSchema, it) {
|
||||
var validateSchema = rule.definition.validateSchema;
|
||||
if (validateSchema && self._opts.validateSchema !== false) {
|
||||
var valid = validateSchema(schema);
|
||||
if (!valid) {
|
||||
var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors);
|
||||
if (self._opts.validateSchema == 'log') self.logger.error(message);
|
||||
else throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
var compile = rule.definition.compile
|
||||
, inline = rule.definition.inline
|
||||
, macro = rule.definition.macro;
|
||||
|
||||
var validate;
|
||||
if (compile) {
|
||||
validate = compile.call(self, schema, parentSchema, it);
|
||||
} else if (macro) {
|
||||
validate = macro.call(self, schema, parentSchema, it);
|
||||
if (opts.validateSchema !== false) self.validateSchema(validate, true);
|
||||
} else if (inline) {
|
||||
validate = inline.call(self, it, rule.keyword, schema, parentSchema);
|
||||
} else {
|
||||
validate = rule.definition.validate;
|
||||
if (!validate) return;
|
||||
}
|
||||
|
||||
if (validate === undefined)
|
||||
throw new Error('custom keyword "' + rule.keyword + '"failed to compile');
|
||||
|
||||
var index = customRules.length;
|
||||
customRules[index] = validate;
|
||||
|
||||
return {
|
||||
code: 'customRule' + index,
|
||||
validate: validate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the schema is currently compiled
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
* @return {Object} object with properties "index" (compilation index) and "compiling" (boolean)
|
||||
*/
|
||||
function checkCompiling(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
var index = compIndex.call(this, schema, root, baseId);
|
||||
if (index >= 0) return { index: index, compiling: true };
|
||||
index = this._compilations.length;
|
||||
this._compilations[index] = {
|
||||
schema: schema,
|
||||
root: root,
|
||||
baseId: baseId
|
||||
};
|
||||
return { index: index, compiling: false };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the schema from the currently compiled list
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
*/
|
||||
function endCompiling(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
var i = compIndex.call(this, schema, root, baseId);
|
||||
if (i >= 0) this._compilations.splice(i, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Index of schema compilation in the currently compiled list
|
||||
* @this Ajv
|
||||
* @param {Object} schema schema to compile
|
||||
* @param {Object} root root object
|
||||
* @param {String} baseId base schema ID
|
||||
* @return {Integer} compilation index
|
||||
*/
|
||||
function compIndex(schema, root, baseId) {
|
||||
/* jshint validthis: true */
|
||||
for (var i=0; i<this._compilations.length; i++) {
|
||||
var c = this._compilations[i];
|
||||
if (c.schema == schema && c.root == root && c.baseId == baseId) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function patternCode(i, patterns) {
|
||||
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');';
|
||||
}
|
||||
|
||||
|
||||
function defaultCode(i) {
|
||||
return 'var default' + i + ' = defaults[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function refValCode(i, refVal) {
|
||||
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function customRuleCode(i) {
|
||||
return 'var customRule' + i + ' = customRules[' + i + '];';
|
||||
}
|
||||
|
||||
|
||||
function vars(arr, statement) {
|
||||
if (!arr.length) return '';
|
||||
var code = '';
|
||||
for (var i=0; i<arr.length; i++)
|
||||
code += statement(i, arr);
|
||||
return code;
|
||||
}
|
270
node_modules/ajv/lib/compile/resolve.js
generated
vendored
@ -1,270 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var URI = require('uri-js')
|
||||
, equal = require('fast-deep-equal')
|
||||
, util = require('./util')
|
||||
, SchemaObject = require('./schema_obj')
|
||||
, traverse = require('json-schema-traverse');
|
||||
|
||||
module.exports = resolve;
|
||||
|
||||
resolve.normalizeId = normalizeId;
|
||||
resolve.fullPath = getFullPath;
|
||||
resolve.url = resolveUrl;
|
||||
resolve.ids = resolveIds;
|
||||
resolve.inlineRef = inlineRef;
|
||||
resolve.schema = resolveSchema;
|
||||
|
||||
/**
|
||||
* [resolve and compile the references ($ref)]
|
||||
* @this Ajv
|
||||
* @param {Function} compile reference to schema compilation funciton (localCompile)
|
||||
* @param {Object} root object with information about the root schema for the current schema
|
||||
* @param {String} ref reference to resolve
|
||||
* @return {Object|Function} schema object (if the schema can be inlined) or validation function
|
||||
*/
|
||||
function resolve(compile, root, ref) {
|
||||
/* jshint validthis: true */
|
||||
var refVal = this._refs[ref];
|
||||
if (typeof refVal == 'string') {
|
||||
if (this._refs[refVal]) refVal = this._refs[refVal];
|
||||
else return resolve.call(this, compile, root, refVal);
|
||||
}
|
||||
|
||||
refVal = refVal || this._schemas[ref];
|
||||
if (refVal instanceof SchemaObject) {
|
||||
return inlineRef(refVal.schema, this._opts.inlineRefs)
|
||||
? refVal.schema
|
||||
: refVal.validate || this._compile(refVal);
|
||||
}
|
||||
|
||||
var res = resolveSchema.call(this, root, ref);
|
||||
var schema, v, baseId;
|
||||
if (res) {
|
||||
schema = res.schema;
|
||||
root = res.root;
|
||||
baseId = res.baseId;
|
||||
}
|
||||
|
||||
if (schema instanceof SchemaObject) {
|
||||
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
|
||||
} else if (schema !== undefined) {
|
||||
v = inlineRef(schema, this._opts.inlineRefs)
|
||||
? schema
|
||||
: compile.call(this, schema, root, undefined, baseId);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve schema, its root and baseId
|
||||
* @this Ajv
|
||||
* @param {Object} root root object with properties schema, refVal, refs
|
||||
* @param {String} ref reference to resolve
|
||||
* @return {Object} object with properties schema, root, baseId
|
||||
*/
|
||||
function resolveSchema(root, ref) {
|
||||
/* jshint validthis: true */
|
||||
var p = URI.parse(ref)
|
||||
, refPath = _getFullPath(p)
|
||||
, baseId = getFullPath(this._getId(root.schema));
|
||||
if (Object.keys(root.schema).length === 0 || refPath !== baseId) {
|
||||
var id = normalizeId(refPath);
|
||||
var refVal = this._refs[id];
|
||||
if (typeof refVal == 'string') {
|
||||
return resolveRecursive.call(this, root, refVal, p);
|
||||
} else if (refVal instanceof SchemaObject) {
|
||||
if (!refVal.validate) this._compile(refVal);
|
||||
root = refVal;
|
||||
} else {
|
||||
refVal = this._schemas[id];
|
||||
if (refVal instanceof SchemaObject) {
|
||||
if (!refVal.validate) this._compile(refVal);
|
||||
if (id == normalizeId(ref))
|
||||
return { schema: refVal, root: root, baseId: baseId };
|
||||
root = refVal;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!root.schema) return;
|
||||
baseId = getFullPath(this._getId(root.schema));
|
||||
}
|
||||
return getJsonPointer.call(this, p, baseId, root.schema, root);
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function resolveRecursive(root, ref, parsedRef) {
|
||||
/* jshint validthis: true */
|
||||
var res = resolveSchema.call(this, root, ref);
|
||||
if (res) {
|
||||
var schema = res.schema;
|
||||
var baseId = res.baseId;
|
||||
root = res.root;
|
||||
var id = this._getId(schema);
|
||||
if (id) baseId = resolveUrl(baseId, id);
|
||||
return getJsonPointer.call(this, parsedRef, baseId, schema, root);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']);
|
||||
/* @this Ajv */
|
||||
function getJsonPointer(parsedRef, baseId, schema, root) {
|
||||
/* jshint validthis: true */
|
||||
parsedRef.fragment = parsedRef.fragment || '';
|
||||
if (parsedRef.fragment.slice(0,1) != '/') return;
|
||||
var parts = parsedRef.fragment.split('/');
|
||||
|
||||
for (var i = 1; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
if (part) {
|
||||
part = util.unescapeFragment(part);
|
||||
schema = schema[part];
|
||||
if (schema === undefined) break;
|
||||
var id;
|
||||
if (!PREVENT_SCOPE_CHANGE[part]) {
|
||||
id = this._getId(schema);
|
||||
if (id) baseId = resolveUrl(baseId, id);
|
||||
if (schema.$ref) {
|
||||
var $ref = resolveUrl(baseId, schema.$ref);
|
||||
var res = resolveSchema.call(this, root, $ref);
|
||||
if (res) {
|
||||
schema = res.schema;
|
||||
root = res.root;
|
||||
baseId = res.baseId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (schema !== undefined && schema !== root.schema)
|
||||
return { schema: schema, root: root, baseId: baseId };
|
||||
}
|
||||
|
||||
|
||||
var SIMPLE_INLINED = util.toHash([
|
||||
'type', 'format', 'pattern',
|
||||
'maxLength', 'minLength',
|
||||
'maxProperties', 'minProperties',
|
||||
'maxItems', 'minItems',
|
||||
'maximum', 'minimum',
|
||||
'uniqueItems', 'multipleOf',
|
||||
'required', 'enum'
|
||||
]);
|
||||
function inlineRef(schema, limit) {
|
||||
if (limit === false) return false;
|
||||
if (limit === undefined || limit === true) return checkNoRef(schema);
|
||||
else if (limit) return countKeys(schema) <= limit;
|
||||
}
|
||||
|
||||
|
||||
function checkNoRef(schema) {
|
||||
var item;
|
||||
if (Array.isArray(schema)) {
|
||||
for (var i=0; i<schema.length; i++) {
|
||||
item = schema[i];
|
||||
if (typeof item == 'object' && !checkNoRef(item)) return false;
|
||||
}
|
||||
} else {
|
||||
for (var key in schema) {
|
||||
if (key == '$ref') return false;
|
||||
item = schema[key];
|
||||
if (typeof item == 'object' && !checkNoRef(item)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function countKeys(schema) {
|
||||
var count = 0, item;
|
||||
if (Array.isArray(schema)) {
|
||||
for (var i=0; i<schema.length; i++) {
|
||||
item = schema[i];
|
||||
if (typeof item == 'object') count += countKeys(item);
|
||||
if (count == Infinity) return Infinity;
|
||||
}
|
||||
} else {
|
||||
for (var key in schema) {
|
||||
if (key == '$ref') return Infinity;
|
||||
if (SIMPLE_INLINED[key]) {
|
||||
count++;
|
||||
} else {
|
||||
item = schema[key];
|
||||
if (typeof item == 'object') count += countKeys(item) + 1;
|
||||
if (count == Infinity) return Infinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
function getFullPath(id, normalize) {
|
||||
if (normalize !== false) id = normalizeId(id);
|
||||
var p = URI.parse(id);
|
||||
return _getFullPath(p);
|
||||
}
|
||||
|
||||
|
||||
function _getFullPath(p) {
|
||||
return URI.serialize(p).split('#')[0] + '#';
|
||||
}
|
||||
|
||||
|
||||
var TRAILING_SLASH_HASH = /#\/?$/;
|
||||
function normalizeId(id) {
|
||||
return id ? id.replace(TRAILING_SLASH_HASH, '') : '';
|
||||
}
|
||||
|
||||
|
||||
function resolveUrl(baseId, id) {
|
||||
id = normalizeId(id);
|
||||
return URI.resolve(baseId, id);
|
||||
}
|
||||
|
||||
|
||||
/* @this Ajv */
|
||||
function resolveIds(schema) {
|
||||
var schemaId = normalizeId(this._getId(schema));
|
||||
var baseIds = {'': schemaId};
|
||||
var fullPaths = {'': getFullPath(schemaId, false)};
|
||||
var localRefs = {};
|
||||
var self = this;
|
||||
|
||||
traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
|
||||
if (jsonPtr === '') return;
|
||||
var id = self._getId(sch);
|
||||
var baseId = baseIds[parentJsonPtr];
|
||||
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword;
|
||||
if (keyIndex !== undefined)
|
||||
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex));
|
||||
|
||||
if (typeof id == 'string') {
|
||||
id = baseId = normalizeId(baseId ? URI.resolve(baseId, id) : id);
|
||||
|
||||
var refVal = self._refs[id];
|
||||
if (typeof refVal == 'string') refVal = self._refs[refVal];
|
||||
if (refVal && refVal.schema) {
|
||||
if (!equal(sch, refVal.schema))
|
||||
throw new Error('id "' + id + '" resolves to more than one schema');
|
||||
} else if (id != normalizeId(fullPath)) {
|
||||
if (id[0] == '#') {
|
||||
if (localRefs[id] && !equal(sch, localRefs[id]))
|
||||
throw new Error('id "' + id + '" resolves to more than one schema');
|
||||
localRefs[id] = sch;
|
||||
} else {
|
||||
self._refs[id] = fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
baseIds[jsonPtr] = baseId;
|
||||
fullPaths[jsonPtr] = fullPath;
|
||||
});
|
||||
|
||||
return localRefs;
|
||||
}
|
66
node_modules/ajv/lib/compile/rules.js
generated
vendored
@ -1,66 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var ruleModules = require('../dotjs')
|
||||
, toHash = require('./util').toHash;
|
||||
|
||||
module.exports = function rules() {
|
||||
var RULES = [
|
||||
{ type: 'number',
|
||||
rules: [ { 'maximum': ['exclusiveMaximum'] },
|
||||
{ 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] },
|
||||
{ type: 'string',
|
||||
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
|
||||
{ type: 'array',
|
||||
rules: [ 'maxItems', 'minItems', 'items', 'contains', 'uniqueItems' ] },
|
||||
{ type: 'object',
|
||||
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
|
||||
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
|
||||
{ rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf', 'if' ] }
|
||||
];
|
||||
|
||||
var ALL = [ 'type', '$comment' ];
|
||||
var KEYWORDS = [
|
||||
'$schema', '$id', 'id', '$data', 'title',
|
||||
'description', 'default', 'definitions',
|
||||
'examples', 'readOnly', 'writeOnly',
|
||||
'contentMediaType', 'contentEncoding',
|
||||
'additionalItems', 'then', 'else'
|
||||
];
|
||||
var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ];
|
||||
RULES.all = toHash(ALL);
|
||||
RULES.types = toHash(TYPES);
|
||||
|
||||
RULES.forEach(function (group) {
|
||||
group.rules = group.rules.map(function (keyword) {
|
||||
var implKeywords;
|
||||
if (typeof keyword == 'object') {
|
||||
var key = Object.keys(keyword)[0];
|
||||
implKeywords = keyword[key];
|
||||
keyword = key;
|
||||
implKeywords.forEach(function (k) {
|
||||
ALL.push(k);
|
||||
RULES.all[k] = true;
|
||||
});
|
||||
}
|
||||
ALL.push(keyword);
|
||||
var rule = RULES.all[keyword] = {
|
||||
keyword: keyword,
|
||||
code: ruleModules[keyword],
|
||||
implements: implKeywords
|
||||
};
|
||||
return rule;
|
||||
});
|
||||
|
||||
RULES.all.$comment = {
|
||||
keyword: '$comment',
|
||||
code: ruleModules.$comment
|
||||
};
|
||||
|
||||
if (group.type) RULES.types[group.type] = group;
|
||||
});
|
||||
|
||||
RULES.keywords = toHash(ALL.concat(KEYWORDS));
|
||||
RULES.custom = {};
|
||||
|
||||
return RULES;
|
||||
};
|
9
node_modules/ajv/lib/compile/schema_obj.js
generated
vendored
@ -1,9 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./util');
|
||||
|
||||
module.exports = SchemaObject;
|
||||
|
||||
function SchemaObject(obj) {
|
||||
util.copy(obj, this);
|
||||
}
|
20
node_modules/ajv/lib/compile/ucs2length.js
generated
vendored
@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// https://mathiasbynens.be/notes/javascript-encoding
|
||||
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
|
||||
module.exports = function ucs2length(str) {
|
||||
var length = 0
|
||||
, len = str.length
|
||||
, pos = 0
|
||||
, value;
|
||||
while (pos < len) {
|
||||
length++;
|
||||
value = str.charCodeAt(pos++);
|
||||
if (value >= 0xD800 && value <= 0xDBFF && pos < len) {
|
||||
// high surrogate, and there is a next character
|
||||
value = str.charCodeAt(pos);
|
||||
if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate
|
||||
}
|
||||
}
|
||||
return length;
|
||||
};
|
267
node_modules/ajv/lib/compile/util.js
generated
vendored
@ -1,267 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
module.exports = {
|
||||
copy: copy,
|
||||
checkDataType: checkDataType,
|
||||
checkDataTypes: checkDataTypes,
|
||||
coerceToTypes: coerceToTypes,
|
||||
toHash: toHash,
|
||||
getProperty: getProperty,
|
||||
escapeQuotes: escapeQuotes,
|
||||
equal: require('fast-deep-equal'),
|
||||
ucs2length: require('./ucs2length'),
|
||||
varOccurences: varOccurences,
|
||||
varReplace: varReplace,
|
||||
cleanUpCode: cleanUpCode,
|
||||
finalCleanUpCode: finalCleanUpCode,
|
||||
schemaHasRules: schemaHasRules,
|
||||
schemaHasRulesExcept: schemaHasRulesExcept,
|
||||
toQuotedString: toQuotedString,
|
||||
getPathExpr: getPathExpr,
|
||||
getPath: getPath,
|
||||
getData: getData,
|
||||
unescapeFragment: unescapeFragment,
|
||||
unescapeJsonPointer: unescapeJsonPointer,
|
||||
escapeFragment: escapeFragment,
|
||||
escapeJsonPointer: escapeJsonPointer
|
||||
};
|
||||
|
||||
|
||||
function copy(o, to) {
|
||||
to = to || {};
|
||||
for (var key in o) to[key] = o[key];
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
function checkDataType(dataType, data, negate) {
|
||||
var EQUAL = negate ? ' !== ' : ' === '
|
||||
, AND = negate ? ' || ' : ' && '
|
||||
, OK = negate ? '!' : ''
|
||||
, NOT = negate ? '' : '!';
|
||||
switch (dataType) {
|
||||
case 'null': return data + EQUAL + 'null';
|
||||
case 'array': return OK + 'Array.isArray(' + data + ')';
|
||||
case 'object': return '(' + OK + data + AND +
|
||||
'typeof ' + data + EQUAL + '"object"' + AND +
|
||||
NOT + 'Array.isArray(' + data + '))';
|
||||
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +
|
||||
NOT + '(' + data + ' % 1)' +
|
||||
AND + data + EQUAL + data + ')';
|
||||
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkDataTypes(dataTypes, data) {
|
||||
switch (dataTypes.length) {
|
||||
case 1: return checkDataType(dataTypes[0], data, true);
|
||||
default:
|
||||
var code = '';
|
||||
var types = toHash(dataTypes);
|
||||
if (types.array && types.object) {
|
||||
code = types.null ? '(': '(!' + data + ' || ';
|
||||
code += 'typeof ' + data + ' !== "object")';
|
||||
delete types.null;
|
||||
delete types.array;
|
||||
delete types.object;
|
||||
}
|
||||
if (types.number) delete types.integer;
|
||||
for (var t in types)
|
||||
code += (code ? ' && ' : '' ) + checkDataType(t, data, true);
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);
|
||||
function coerceToTypes(optionCoerceTypes, dataTypes) {
|
||||
if (Array.isArray(dataTypes)) {
|
||||
var types = [];
|
||||
for (var i=0; i<dataTypes.length; i++) {
|
||||
var t = dataTypes[i];
|
||||
if (COERCE_TO_TYPES[t]) types[types.length] = t;
|
||||
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;
|
||||
}
|
||||
if (types.length) return types;
|
||||
} else if (COERCE_TO_TYPES[dataTypes]) {
|
||||
return [dataTypes];
|
||||
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') {
|
||||
return ['array'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function toHash(arr) {
|
||||
var hash = {};
|
||||
for (var i=0; i<arr.length; i++) hash[arr[i]] = true;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
|
||||
var SINGLE_QUOTE = /'|\\/g;
|
||||
function getProperty(key) {
|
||||
return typeof key == 'number'
|
||||
? '[' + key + ']'
|
||||
: IDENTIFIER.test(key)
|
||||
? '.' + key
|
||||
: "['" + escapeQuotes(key) + "']";
|
||||
}
|
||||
|
||||
|
||||
function escapeQuotes(str) {
|
||||
return str.replace(SINGLE_QUOTE, '\\$&')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\f/g, '\\f')
|
||||
.replace(/\t/g, '\\t');
|
||||
}
|
||||
|
||||
|
||||
function varOccurences(str, dataVar) {
|
||||
dataVar += '[^0-9]';
|
||||
var matches = str.match(new RegExp(dataVar, 'g'));
|
||||
return matches ? matches.length : 0;
|
||||
}
|
||||
|
||||
|
||||
function varReplace(str, dataVar, expr) {
|
||||
dataVar += '([^0-9])';
|
||||
expr = expr.replace(/\$/g, '$$$$');
|
||||
return str.replace(new RegExp(dataVar, 'g'), expr + '$1');
|
||||
}
|
||||
|
||||
|
||||
var EMPTY_ELSE = /else\s*{\s*}/g
|
||||
, EMPTY_IF_NO_ELSE = /if\s*\([^)]+\)\s*\{\s*\}(?!\s*else)/g
|
||||
, EMPTY_IF_WITH_ELSE = /if\s*\(([^)]+)\)\s*\{\s*\}\s*else(?!\s*if)/g;
|
||||
function cleanUpCode(out) {
|
||||
return out.replace(EMPTY_ELSE, '')
|
||||
.replace(EMPTY_IF_NO_ELSE, '')
|
||||
.replace(EMPTY_IF_WITH_ELSE, 'if (!($1))');
|
||||
}
|
||||
|
||||
|
||||
var ERRORS_REGEXP = /[^v.]errors/g
|
||||
, REMOVE_ERRORS = /var errors = 0;|var vErrors = null;|validate.errors = vErrors;/g
|
||||
, REMOVE_ERRORS_ASYNC = /var errors = 0;|var vErrors = null;/g
|
||||
, RETURN_VALID = 'return errors === 0;'
|
||||
, RETURN_TRUE = 'validate.errors = null; return true;'
|
||||
, RETURN_ASYNC = /if \(errors === 0\) return data;\s*else throw new ValidationError\(vErrors\);/
|
||||
, RETURN_DATA_ASYNC = 'return data;'
|
||||
, ROOTDATA_REGEXP = /[^A-Za-z_$]rootData[^A-Za-z0-9_$]/g
|
||||
, REMOVE_ROOTDATA = /if \(rootData === undefined\) rootData = data;/;
|
||||
|
||||
function finalCleanUpCode(out, async) {
|
||||
var matches = out.match(ERRORS_REGEXP);
|
||||
if (matches && matches.length == 2) {
|
||||
out = async
|
||||
? out.replace(REMOVE_ERRORS_ASYNC, '')
|
||||
.replace(RETURN_ASYNC, RETURN_DATA_ASYNC)
|
||||
: out.replace(REMOVE_ERRORS, '')
|
||||
.replace(RETURN_VALID, RETURN_TRUE);
|
||||
}
|
||||
|
||||
matches = out.match(ROOTDATA_REGEXP);
|
||||
if (!matches || matches.length !== 3) return out;
|
||||
return out.replace(REMOVE_ROOTDATA, '');
|
||||
}
|
||||
|
||||
|
||||
function schemaHasRules(schema, rules) {
|
||||
if (typeof schema == 'boolean') return !schema;
|
||||
for (var key in schema) if (rules[key]) return true;
|
||||
}
|
||||
|
||||
|
||||
function schemaHasRulesExcept(schema, rules, exceptKeyword) {
|
||||
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';
|
||||
for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
|
||||
}
|
||||
|
||||
|
||||
function toQuotedString(str) {
|
||||
return '\'' + escapeQuotes(str) + '\'';
|
||||
}
|
||||
|
||||
|
||||
function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
|
||||
var path = jsonPointers // false by default
|
||||
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')
|
||||
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');
|
||||
return joinPaths(currentPath, path);
|
||||
}
|
||||
|
||||
|
||||
function getPath(currentPath, prop, jsonPointers) {
|
||||
var path = jsonPointers // false by default
|
||||
? toQuotedString('/' + escapeJsonPointer(prop))
|
||||
: toQuotedString(getProperty(prop));
|
||||
return joinPaths(currentPath, path);
|
||||
}
|
||||
|
||||
|
||||
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
|
||||
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
|
||||
function getData($data, lvl, paths) {
|
||||
var up, jsonPointer, data, matches;
|
||||
if ($data === '') return 'rootData';
|
||||
if ($data[0] == '/') {
|
||||
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);
|
||||
jsonPointer = $data;
|
||||
data = 'rootData';
|
||||
} else {
|
||||
matches = $data.match(RELATIVE_JSON_POINTER);
|
||||
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);
|
||||
up = +matches[1];
|
||||
jsonPointer = matches[2];
|
||||
if (jsonPointer == '#') {
|
||||
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);
|
||||
return paths[lvl - up];
|
||||
}
|
||||
|
||||
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);
|
||||
data = 'data' + ((lvl - up) || '');
|
||||
if (!jsonPointer) return data;
|
||||
}
|
||||
|
||||
var expr = data;
|
||||
var segments = jsonPointer.split('/');
|
||||
for (var i=0; i<segments.length; i++) {
|
||||
var segment = segments[i];
|
||||
if (segment) {
|
||||
data += getProperty(unescapeJsonPointer(segment));
|
||||
expr += ' && ' + data;
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
function joinPaths (a, b) {
|
||||
if (a == '""') return b;
|
||||
return (a + ' + ' + b).replace(/' \+ '/g, '');
|
||||
}
|
||||
|
||||
|
||||
function unescapeFragment(str) {
|
||||
return unescapeJsonPointer(decodeURIComponent(str));
|
||||
}
|
||||
|
||||
|
||||
function escapeFragment(str) {
|
||||
return encodeURIComponent(escapeJsonPointer(str));
|
||||
}
|
||||
|
||||
|
||||
function escapeJsonPointer(str) {
|
||||
return str.replace(/~/g, '~0').replace(/\//g, '~1');
|
||||
}
|
||||
|
||||
|
||||
function unescapeJsonPointer(str) {
|
||||
return str.replace(/~1/g, '/').replace(/~0/g, '~');
|
||||
}
|
49
node_modules/ajv/lib/data.js
generated
vendored
@ -1,49 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var KEYWORDS = [
|
||||
'multipleOf',
|
||||
'maximum',
|
||||
'exclusiveMaximum',
|
||||
'minimum',
|
||||
'exclusiveMinimum',
|
||||
'maxLength',
|
||||
'minLength',
|
||||
'pattern',
|
||||
'additionalItems',
|
||||
'maxItems',
|
||||
'minItems',
|
||||
'uniqueItems',
|
||||
'maxProperties',
|
||||
'minProperties',
|
||||
'required',
|
||||
'additionalProperties',
|
||||
'enum',
|
||||
'format',
|
||||
'const'
|
||||
];
|
||||
|
||||
module.exports = function (metaSchema, keywordsJsonPointers) {
|
||||
for (var i=0; i<keywordsJsonPointers.length; i++) {
|
||||
metaSchema = JSON.parse(JSON.stringify(metaSchema));
|
||||
var segments = keywordsJsonPointers[i].split('/');
|
||||
var keywords = metaSchema;
|
||||
var j;
|
||||
for (j=1; j<segments.length; j++)
|
||||
keywords = keywords[segments[j]];
|
||||
|
||||
for (j=0; j<KEYWORDS.length; j++) {
|
||||
var key = KEYWORDS[j];
|
||||
var schema = keywords[key];
|
||||
if (schema) {
|
||||
keywords[key] = {
|
||||
anyOf: [
|
||||
schema,
|
||||
{ $ref: 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/data.json#' }
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return metaSchema;
|
||||
};
|
104
node_modules/ajv/lib/dot/_limit.jst
generated
vendored
@ -1,104 +0,0 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{## def.setExclusiveLimit:
|
||||
$exclusive = true;
|
||||
$errorKeyword = $exclusiveKeyword;
|
||||
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
|
||||
#}}
|
||||
|
||||
{{
|
||||
var $isMax = $keyword == 'maximum'
|
||||
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'
|
||||
, $schemaExcl = it.schema[$exclusiveKeyword]
|
||||
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
|
||||
, $op = $isMax ? '<' : '>'
|
||||
, $notOp = $isMax ? '>' : '<'
|
||||
, $errorKeyword = undefined;
|
||||
}}
|
||||
|
||||
{{? $isDataExcl }}
|
||||
{{
|
||||
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
|
||||
, $exclusive = 'exclusive' + $lvl
|
||||
, $exclType = 'exclType' + $lvl
|
||||
, $exclIsNumber = 'exclIsNumber' + $lvl
|
||||
, $opExpr = 'op' + $lvl
|
||||
, $opStr = '\' + ' + $opExpr + ' + \'';
|
||||
}}
|
||||
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
|
||||
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
|
||||
|
||||
var {{=$exclusive}};
|
||||
var {{=$exclType}} = typeof {{=$schemaValueExcl}};
|
||||
if ({{=$exclType}} != 'boolean' && {{=$exclType}} != 'undefined' && {{=$exclType}} != 'number') {
|
||||
{{ var $errorKeyword = $exclusiveKeyword; }}
|
||||
{{# def.error:'_exclusiveLimit' }}
|
||||
} else if ({{# def.$dataNotType:'number' }}
|
||||
{{=$exclType}} == 'number'
|
||||
? (
|
||||
({{=$exclusive}} = {{=$schemaValue}} === undefined || {{=$schemaValueExcl}} {{=$op}}= {{=$schemaValue}})
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaValueExcl}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
)
|
||||
: (
|
||||
({{=$exclusive}} = {{=$schemaValueExcl}} === true)
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaValue}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
)
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
|
||||
{{
|
||||
if ($schema === undefined) {
|
||||
$errorKeyword = $exclusiveKeyword;
|
||||
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
|
||||
$schemaValue = $schemaValueExcl;
|
||||
$isData = $isDataExcl;
|
||||
}
|
||||
}}
|
||||
{{??}}
|
||||
{{
|
||||
var $exclIsNumber = typeof $schemaExcl == 'number'
|
||||
, $opStr = $op; /*used in error*/
|
||||
}}
|
||||
|
||||
{{? $exclIsNumber && $isData }}
|
||||
{{ var $opExpr = '\'' + $opStr + '\''; /*used in error*/ }}
|
||||
if ({{# def.$dataNotType:'number' }}
|
||||
( {{=$schemaValue}} === undefined
|
||||
|| {{=$schemaExcl}} {{=$op}}= {{=$schemaValue}}
|
||||
? {{=$data}} {{=$notOp}}= {{=$schemaExcl}}
|
||||
: {{=$data}} {{=$notOp}} {{=$schemaValue}} )
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
{{??}}
|
||||
{{
|
||||
if ($exclIsNumber && $schema === undefined) {
|
||||
{{# def.setExclusiveLimit }}
|
||||
$schemaValue = $schemaExcl;
|
||||
$notOp += '=';
|
||||
} else {
|
||||
if ($exclIsNumber)
|
||||
$schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);
|
||||
|
||||
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
|
||||
{{# def.setExclusiveLimit }}
|
||||
$notOp += '=';
|
||||
} else {
|
||||
$exclusive = false;
|
||||
$opStr += '=';
|
||||
}
|
||||
}
|
||||
|
||||
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
|
||||
}}
|
||||
|
||||
if ({{# def.$dataNotType:'number' }}
|
||||
{{=$data}} {{=$notOp}} {{=$schemaValue}}
|
||||
|| {{=$data}} !== {{=$data}}) {
|
||||
{{?}}
|
||||
{{?}}
|
||||
{{ $errorKeyword = $errorKeyword || $keyword; }}
|
||||
{{# def.error:'_limit' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
10
node_modules/ajv/lib/dot/_limitItems.jst
generated
vendored
@ -1,10 +0,0 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }}
|
||||
if ({{# def.$dataNotType:'number' }} {{=$data}}.length {{=$op}} {{=$schemaValue}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_limitItems' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|
10
node_modules/ajv/lib/dot/_limitLength.jst
generated
vendored
@ -1,10 +0,0 @@
|
||||
{{# def.definitions }}
|
||||
{{# def.errors }}
|
||||
{{# def.setupKeyword }}
|
||||
{{# def.$data }}
|
||||
|
||||
{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }}
|
||||
if ({{# def.$dataNotType:'number' }} {{# def.strLength }} {{=$op}} {{=$schemaValue}}) {
|
||||
{{ var $errorKeyword = $keyword; }}
|
||||
{{# def.error:'_limitLength' }}
|
||||
} {{? $breakOnError }} else { {{?}}
|