Compare commits

...

178 Commits

Author SHA1 Message Date
thecodrr
ed8271cf9d chore(tinymce-plugins): bump version to 1.5.18 2022-04-01 22:06:44 +05:00
thecodrr
da7723e7e0 fix: make inline code toggleable (fixes #444) 2022-04-01 22:02:00 +05:00
thecodrr
43e817e259 fix(importer): use correct redirect uri for onenote 2022-03-27 16:34:21 +05:00
thecodrr
eb50ebeb81 chore(importer): update packages 2022-03-27 16:26:23 +05:00
thecodrr
16b702294a chore(onenote): bump version to 1.0.1 2022-03-27 16:10:35 +05:00
thecodrr
9bd68e8c5a fix(onenote): set redirectUri via authconfig 2022-03-27 16:10:16 +05:00
thecodrr
f1b2deb893 chore(importer-web): bump version to 1.2.0 2022-03-26 22:39:03 +05:00
thecodrr
64eae3044d chore(importer): bump version to 1.2.1 2022-03-26 22:36:22 +05:00
thecodrr
f1be7a57a1 chore(importer): bump version to 1.2.0 2022-03-26 22:30:38 +05:00
Abdullah Atta
80dd83552a feat: add Zoho Notebook support in Importer (#382)
* feat: add zoho notebook importer

* fix: checklists in todo notes are not converted

* chore: use @notesnook/znel from npm
2022-03-26 22:27:20 +05:00
thecodrr
b4b7f9c519 chore: fix tests and update snjs 2022-03-26 22:14:56 +05:00
Abdullah Atta
5d0e556e1b feat: add support for OneNote in Importer (#296)
* chore: initialize onenote provider package

* add basic support for onenote

* feat: add progress

* refactor: cleanup and finalize onenote api

* feat: add onenote support in importer-web

* refactor: use a single import result component

* fix(onenote): avoid circular references

* test: add onenote tests

* chore: publish @notesnook/onenote to npm

* chore: use @notesnook/onenote from npm
2022-03-26 22:09:01 +05:00
thecodrr
ecd1640c1d fix: use custom curl parser 2022-03-26 15:15:55 +05:00
Abdullah Atta
085b7c4eb1 feat: add vericrypt utility for Notesnook encryption verification (#311)
* feat: add basic version of vericrypt utility

* feat: implement decryption logic & refresh ui

* fix: reinstall favicon

* chore: change icon

* chore: vericrypt -> notesnook vericrypt

* vericrypt: finalize ui & ux

* fix: minor adjustments to the instructions

* ci: add vericrypt deployment github action

Co-authored-by: ammarahm-ed <ammarahmed6506@gmail.com>
2022-03-26 14:15:51 +05:00
thecodrr
9838ad715e chore(tinymce-plugins): bump version to 1.5.17 2022-03-16 12:45:17 +05:00
thecodrr
f370f90a2b fix: simplify mceInsertCodeBlock 2022-03-16 12:44:58 +05:00
thecodrr
02b2a9fb17 chore(tinymce-plugins): correctly bump version to 1.5.16 2022-03-15 23:24:57 +05:00
thecodrr
17d953e59a chore(tinymce-plugins): bump version to 1.15.16 2022-03-15 07:48:22 +05:00
thecodrr
c47436927e feat(tinymce-plugins): many codeblock improvements 2022-03-15 07:38:30 +05:00
thecodrr
8f89414f89 chore(tinymce-plugins): bump version to 1.5.15 2022-03-14 16:09:13 +05:00
thecodrr
557e1de9f0 fix(tinymce-plugins): don't remove 1st line if editor empty 2022-03-14 16:08:42 +05:00
thecodrr
6cc065a0f7 fix(tinymce-plugins): <br> -> \n 2022-03-14 16:08:16 +05:00
thecodrr
cba87d8477 chore(tinymce-plugins): remove console.log 2022-03-14 16:02:35 +05:00
thecodrr
26203bf3da feat(tinymce-plugins): improve codeblock pasting 2022-03-14 16:01:21 +05:00
ammarahm-ed
e9d43f3026 feat(tinymce-plugins): touch input support in collapsibleheaders 2022-03-09 11:35:17 +05:00
thecodrr
57df03e46c chore(tinymce-plugins): bump version to 1.5.14 2022-03-08 14:21:59 +05:00
thecodrr
b673519898 feat(tinymce-plugins): add support for h1 in collapsible headers 2022-03-08 14:21:31 +05:00
thecodrr
5356e9d4ed chore(tinymce-plugins): bump version to 1.5.13 2022-03-07 17:29:51 +05:00
thecodrr
3d1b9de51b fix(tinymce-plugins): do not autofocus on set content 2022-03-07 17:29:31 +05:00
thecodrr
c1741b1924 chore(tinymce-plugins): bump version to 1.5.12 2022-03-04 23:36:54 +05:00
thecodrr
4a17164bd9 fix: minimized state of headings should get saved
(fixes #377)
2022-03-04 23:33:12 +05:00
ammarahm-ed
c26dbefe26 fix: nested checklist items not checked on mobile 2022-02-24 13:29:56 +05:00
thecodrr
f532d6f01b chore(tinymce-plugins): bump version to 1.5.11 2022-02-19 20:27:56 +05:00
thecodrr
351f56dc0d fix(tinymce-plugins): auto check last checklist item
this ensures that if tinymce auto merges two checklists
due to close proximity, the first element of the second list
would get checked instead of the first elemtn of the first list.
2022-02-19 20:27:36 +05:00
thecodrr
feb74ae910 chore(tinymce-plugins): bump version to 1.5.10 2022-02-19 20:22:11 +05:00
thecodrr
4b483d200d feat: allow checking first item via execCommand 2022-02-19 20:21:52 +05:00
Abdullah Atta
5858cae55b feat: open source notesnook crypto module (#329)
* chore: open-source notesnook crypto

* chore(crypto): remove useless webpack config

* chore(crypto): add npmignore file
2022-02-02 10:32:02 +05:00
thecodrr
e7491d1c03 chore(tinymce-plugins): bump version to 1.5.9 2022-01-31 11:52:15 +05:00
thecodrr
e740d56a84 fix(tinymce-plugins): jumpto next p tag on enter press 2022-01-31 11:51:35 +05:00
thecodrr
01c78c654d ci: fix "cd: app/importer: No such file or directory" 2022-01-24 11:15:13 +05:00
thecodrr
db67114a30 chore(importer-web): bump version to 1.1.2 2022-01-24 11:13:11 +05:00
thecodrr
7483286833 chore(importer-web): update @notesnook/importer 2022-01-24 11:12:49 +05:00
thecodrr
9606517f38 ci: deploy importer web app directly 2022-01-24 11:11:01 +05:00
thecodrr
1d86624ce3 test(importer): update snapshots 2022-01-24 11:09:23 +05:00
thecodrr
bdc2af9597 chore(importer): bump version to 1.1.3 2022-01-24 11:07:05 +05:00
thecodrr
41d77b6424 chore(importer): update @notesnook/enex 2022-01-24 11:06:53 +05:00
thecodrr
3bda97b4f5 chore(enex): bump version to 1.0.3 2022-01-24 11:04:58 +05:00
thecodrr
5d5b1e9eac fix(enex): derive md5 hash of att. manually 2022-01-24 11:03:25 +05:00
thecodrr
f46ef8347f chore(tinymce-plugins): @streetwritersco -> @streetwriters 2022-01-22 13:31:40 +05:00
thecodrr
c613e67218 chore(tinymce-plugins): bump version to 1.5.7 2022-01-22 13:27:16 +05:00
thecodrr
a9ff91d51e fix(tinymce-plugins): make inlinecode toggleable 2022-01-22 13:26:45 +05:00
thecodrr
52f51c4087 chore(importer-web): bump version to 1.1.1 2022-01-21 23:54:45 +05:00
thecodrr
f0ec25c296 chore(importer-web): update importer core 2022-01-21 23:54:11 +05:00
thecodrr
d2ae716993 chore(importer): bump version to 1.1.2 2022-01-21 23:53:24 +05:00
thecodrr
8d432d4810 fix(importer): typo in DefaultAppDomain 2022-01-21 23:53:06 +05:00
thecodrr
e2bd1cd1f1 chore(importer-web): bump version to 1.1.0 2022-01-21 23:37:42 +05:00
thecodrr
7286c60961 chore(importer-web): update importer core 2022-01-21 23:25:58 +05:00
thecodrr
8a9cd91d54 chore(importer): bump version 1.1.1 2022-01-21 23:22:03 +05:00
thecodrr
462ae4d8ab fix: move @standardnotes/common & @standardnotes/features to dependencies 2022-01-21 23:21:22 +05:00
thecodrr
45e7d5e46b chore(importer): add Standard Notes to readme 2022-01-21 21:34:51 +05:00
thecodrr
9426e937a5 test(importer): update snapshots 2022-01-21 21:34:31 +05:00
thecodrr
8ec4102395 fix: log errors during unpacking 2022-01-21 21:34:13 +05:00
thecodrr
4832d243da refactor: use snjs types instead of our own 2022-01-21 21:33:11 +05:00
thecodrr
9504f278c3 refactor: move table & codeblock construction logic into domutils 2022-01-21 21:32:44 +05:00
Ammar Ahmed
8cefa1defc feat: add standard notes support in importer (#285)
* add support for standard notes in importer

* rename types

* move editors to constants.ts

* change ContentTypes to enum

* make all properties of SNBackup optional

* add version & backup file check

* refactor buildTableWithRows function

* rename mode to language

* use inverted condition to reduce indent

* refactor table construction html strings
2022-01-20 10:49:29 +05:00
thecodrr
b4e58139e3 ci: do not build before running tests 2022-01-19 17:34:29 +05:00
thecodrr
73f60704dd ci: rename workflows for enex & importer packages 2022-01-19 17:29:51 +05:00
thecodrr
470e3040fc ci: fix syntax errors in workflows 2022-01-19 17:29:15 +05:00
thecodrr
73d9a0f371 ci: add workflows for testing enex & importer packages 2022-01-19 17:27:53 +05:00
thecodrr
7a01898b2b chore(importer-web): update importer core 2022-01-19 17:23:10 +05:00
thecodrr
41f5a4eecf chore(importer): publish v1.0.0 on npm 2022-01-19 17:19:56 +05:00
thecodrr
08744fd0ee test(importer): improve packed payload test 2022-01-19 17:09:43 +05:00
thecodrr
4788060c5a chore(enex): bump version to 1.0.2 2022-01-19 16:44:22 +05:00
thecodrr
7a5e49bcbe chore(enex): use thecodrr/node-html-parser package 2022-01-19 16:43:57 +05:00
thecodrr
536744f74a chore(enex): publish 2022-01-19 16:31:30 +05:00
thecodrr
b1c33ebf28 chore(enex): bump version to 1.0.1 2022-01-19 12:27:19 +05:00
thecodrr
323cd373e5 fix(enex): properly remove newlines from base64 data 2022-01-19 12:26:29 +05:00
thecodrr
6c5cfb1505 docs: fix doc page crash with syntax error 2022-01-19 11:59:55 +05:00
ammarahm-ed
b628e6071e docs: fix output path incorrect in config file 2022-01-17 01:23:20 +05:00
ammarahm-ed
8a2c1c0b2a docs: fix generator output path regex 2022-01-17 01:22:17 +05:00
ammarahm-ed
77734aebba docs: update retype to 1.11.2 2022-01-17 01:09:32 +05:00
ammarahm-ed
31711987c3 docs: remove rich-text-editing route 2022-01-13 11:33:59 +05:00
thecodrr
e193afb97d chore(tinymce-plugins): bump version to 1.5.6 2022-01-10 12:23:02 +05:00
thecodrr
02b8fc4eb5 fix: do not touch data-mce-bogus elements (fixes #279) 2022-01-10 12:22:21 +05:00
thecodrr
fd68f02f60 chore(tinymce-plugins): bump version to 1.5.5 2022-01-05 15:07:06 +05:00
thecodrr
6089c58177 chore(tinymce-plugins): add docs for firstLineBackspaceQuirk 2022-01-04 11:11:07 +05:00
thecodrr
cfdfbb36cb fix(tinymce-plugins): first line not backspace-able (#132) 2022-01-04 11:05:53 +05:00
thecodrr
38791a3760 Merge branch 'main' of https://github.com/streetwriters/notesnook 2022-01-04 10:16:01 +05:00
thecodrr
e1426d4c73 fix(tinymce-plugins): text after cursor is deleted on enter 2022-01-04 10:15:58 +05:00
Ammar Ahmed
71e45c23b5 fix: improve checklist responsiveness on touch devices (#267)
* Update index.js

* fix event.targetTouches can cause error

* bump version of tinymce plugins
2022-01-04 09:56:43 +05:00
thecodrr
673e0287bc fix: include .gif in keep valid extensions (fixes #240) 2021-12-30 14:50:45 +05:00
thecodrr
bda62c761a ci: move build files to public_html before deploy 2021-12-30 10:24:59 +05:00
thecodrr
412b40d64f ci: allow triggering importer action manually 2021-12-30 10:05:03 +05:00
thecodrr
975bc3e64d ci: use turbo to run build 2021-12-30 09:59:22 +05:00
thecodrr
2832af2753 chore: finalize notesnook-import v1.0.0 2021-12-30 09:48:26 +05:00
thecodrr
258e9f0a21 ci: use correct gh action names 2021-12-30 09:35:00 +05:00
thecodrr
8a9de63ebc ci: fix a step cannot have both the uses and run keys 2021-12-30 09:33:49 +05:00
thecodrr
49ec85effd ci: add importer deploy action 2021-12-30 09:30:52 +05:00
thecodrr
87e70b2aef chore(tinymce-plugins): bump version to 1.5.3 2021-12-29 12:41:11 +05:00
thecodrr
c6f5276619 fix(tinymce-plugins): remove :not css selector from filters
:not() css selector is only supported in modern browsers
causing crashes in older browsers during saving.
2021-12-29 12:40:58 +05:00
thecodrr
640f03af97 ci(docs): get docs deploy working again 2021-12-28 13:06:18 +05:00
thecodrr
92c2538fbc chore(tinymce-plugins): bump version to 1.5.2 2021-12-28 12:49:28 +05:00
thecodrr
867edbd878 fix(tinymce-plugins): strip data-mce-active attribute 2021-12-28 12:49:14 +05:00
thecodrr
6e2bcdd832 chore(tinymce-plugins): bump version to 1.5.1 2021-12-28 12:45:23 +05:00
thecodrr
25e12564b6 Merge branch 'main' of https://github.com/streetwriters/notesnook 2021-12-28 12:44:54 +05:00
thecodrr
cf0a12bdb9 fix(tinymce-plugins): fire editor change event on check/uncheck 2021-12-28 12:44:34 +05:00
ammarahm-ed
9dce7c737e docs: add retype.yml 2021-12-25 12:56:13 +05:00
ammarahm-ed
0bdb135b7b docs: add version history docs 2021-12-25 12:45:45 +05:00
thecodrr
d9e3798dd1 chore(tinymce-plugins): bump version to 1.5.0 2021-12-24 12:29:17 +05:00
thecodrr
4d9c108144 refactor(tinymce-plugins): use switch stmnt to handle beforeexeccommand 2021-12-24 12:28:51 +05:00
thecodrr
ba19214307 feat(tinymce-plugins): add bettertable plugin 2021-12-24 12:01:03 +05:00
thecodrr
1aee142b59 chore(tinymce-plugins): bump version to 1.4.15 2021-12-24 07:22:15 +05:00
thecodrr
eedf201a61 fix(tinymce-plugins): unlink command doesn't fire event 2021-12-24 07:21:45 +05:00
thecodrr
b7acb75686 chore(tinymce-plugins): bump version to 1.4.14 2021-12-23 12:41:33 +05:00
thecodrr
ee8924c7c5 fix(tinymce-plugins): send inputType with input event 2021-12-23 12:41:16 +05:00
thecodrr
6461fac76e chore(tinymce-plugins): bump version to 1.4.13 2021-12-23 12:09:01 +05:00
thecodrr
3c31fcbe6e fix(tinymce-plugins): editor is not defined 2021-12-23 12:08:49 +05:00
thecodrr
858c92aad5 chore(tinymce-plugins): bump version to 1.4.12 2021-12-23 12:06:59 +05:00
thecodrr
c03e672623 fix(tinymce-plugins): fire input event on att. add/delete 2021-12-23 12:06:36 +05:00
thecodrr
ae8720d69a chore(tinymce-plugins): bump version to 1.4.11 2021-12-23 10:54:18 +05:00
thecodrr
6db218fc06 fix(tinymce-plugins): focus editor after setting content 2021-12-23 10:53:55 +05:00
thecodrr
77e28d25e3 chore(tinymce-plugins): bump version to 1.4.10 2021-12-20 09:59:06 +05:00
thecodrr
309ca061a2 refactor(tinymce-plugins): tox-checklist -> checklist 2021-12-20 09:57:57 +05:00
thecodrr
5268485715 fix(importer): attachment html generation 2021-12-20 09:53:37 +05:00
thecodrr
ee1517e800 fix(importer): make attachment filename mandatory 2021-12-20 09:52:18 +05:00
thecodrr
5770972e88 chore: initialize turborepo & changesets 2021-12-18 11:07:37 +05:00
thecodrr
dc24e629c5 feat: add importer frontend app 2021-12-18 10:06:35 +05:00
thecodrr
9dd125656b refactor: move importer lib to root folder 2021-12-18 10:06:05 +05:00
thecodrr
3f548e1086 chore: compile @notesnook/enex package 2021-12-18 10:04:36 +05:00
thecodrr
919710c069 refactor: seperate importer app & lib 2021-12-18 10:03:26 +05:00
thecodrr
9b4b28741f feat: initialize importer webapp 2021-12-14 09:33:30 +05:00
thecodrr
7d078e9e40 feat: remove old js importer code 2021-12-14 09:08:32 +05:00
thecodrr
bf194ff7d2 feat: finalize importer backend 2021-12-13 10:24:55 +05:00
thecodrr
2e02b57068 chore: bump tinymce-plugins to 1.4.9 2021-12-10 11:52:58 +05:00
thecodrr
5696de8a24 fix: Uncaught ReferenceError: blobCache is not defined (#149) 2021-12-10 11:06:06 +05:00
thecodrr
39b7057bb7 chore: bump tinymce-plugins version to 1.4.8 2021-12-09 09:19:16 +05:00
thecodrr
78f6d18386 fix: do not remove br element in empty p tags 2021-12-09 09:18:40 +05:00
thecodrr
f1c4d5a78d chore: bump tinymce-plugins to 1.4.7 2021-12-06 09:46:23 +05:00
thecodrr
13ab6ca9f7 enex: add isNotebook property 2021-12-06 09:37:35 +05:00
thecodrr
6920147a17 enex: replace querySelector with findChild helper 2021-12-06 09:37:17 +05:00
thecodrr
1ba1c52165 enex: export TaskStatus enum 2021-12-06 09:36:55 +05:00
thecodrr
b7bc1741d6 enex: getElementsByTagName to querySelectorAll 2021-12-06 09:36:38 +05:00
thecodrr
6b4ca9f2ae enex: improve enml to html conversion 2021-12-06 09:31:29 +05:00
thecodrr
6616e87e1d feat: set & clear contents directly 2021-12-06 09:30:31 +05:00
thecodrr
0eb0e4fceb perf: clone node instead of using DOMParser 2021-12-06 09:30:13 +05:00
thecodrr
481a31ab27 fix: allow elementhandler to return undefined 2021-11-27 09:14:46 +05:00
thecodrr
255cb89523 feat: add enex parser 2021-11-27 09:12:38 +05:00
thecodrr
bda96a7d82 chore: bump version to 1.4.6 2021-11-23 20:38:54 +05:00
thecodrr
8ccc7136e2 fix: sanity check for editor.getBody 2021-11-23 20:38:41 +05:00
thecodrr
468498f087 chore: bump tinymce-plugins to 1.4.5 2021-11-20 13:30:13 +05:00
thecodrr
1a57ef5177 fix: sanitze all elements 2021-11-20 13:28:37 +05:00
thecodrr
e3b428a3fb chore: bump tinymce-plugins to version 1.4.4 2021-11-20 12:27:48 +05:00
thecodrr
65e1ced04c feat: add improved dom filtering logic 2021-11-20 12:26:39 +05:00
thecodrr
95d1f17c40 fix: remove data-mce-selected attribute 2021-11-20 12:06:51 +05:00
thecodrr
1fe3b77ba1 chore: bump tinymce-plugins to 1.4.3 2021-11-19 12:02:00 +05:00
thecodrr
0250a86b12 fix: image is not defined 2021-11-19 12:01:37 +05:00
thecodrr
bf64300c68 chore: bump tinymce-plugins to 1.4.2 2021-11-19 11:56:26 +05:00
thecodrr
6280ba31c3 fix: remove tinymce bogus elements 2021-11-19 11:55:52 +05:00
thecodrr
ad4d3c8889 chore: bump tinymce-plugins to 1.4.1 2021-11-19 11:05:04 +05:00
thecodrr
2a96b9c615 fix: use editor.getBody to support iframe editors 2021-11-19 11:04:47 +05:00
thecodrr
5dcc8b3b12 chore: bump tinymce-plugins to 1.4.0 2021-11-19 10:44:53 +05:00
thecodrr
429c6f0e69 feat: add contenthandler plugin 2021-11-19 10:44:05 +05:00
thecodrr
b25f4f3145 fix: evernote output has unnecessary en-note tag 2021-11-05 09:53:09 +05:00
thecodrr
7d33160817 chore: bump tinymce-plugins version to 1.3.11 2021-11-04 20:38:22 +05:00
thecodrr
a73a1b36c8 test: add e2e tests for codeblock 2021-11-04 20:37:07 +05:00
thecodrr
b9860eb21e chore: bump tinymce-plugins version to 1.3.10 2021-11-04 12:07:37 +05:00
thecodrr
b471e44f04 fix: code block is not toggleable (fixes #68) 2021-11-04 11:06:44 +05:00
thecodrr
79f5b30ce4 chore: bump tinymce-plugins to 1.3.9 2021-11-04 10:21:51 +05:00
thecodrr
f858b6ace3 fix: debounce returns a function; call it 2021-11-04 10:21:34 +05:00
thecodrr
c1a700029f chore: bump tinymce-plugins to 1.3.8 2021-11-04 10:14:16 +05:00
thecodrr
34168716fe fix: refresh highlighting on all keys with 500 debounce 2021-11-04 10:13:53 +05:00
thecodrr
164710b56b chore: remove unnecessary console.log 2021-11-04 10:01:40 +05:00
thecodrr
ec5db3f8ea chore: bump tinymce-plugins to 1.3.7 2021-11-04 10:00:26 +05:00
thecodrr
a9f1d12e37 fix: make codeblock compatible with iframe tinymce 2021-11-04 09:59:50 +05:00
thecodrr
8091d5f906 chore: bump tinymce-plugins to v1.3.6 2021-11-04 09:02:57 +05:00
thecodrr
a240e9cdee docs: update roadmap 2021-11-04 09:01:47 +05:00
thecodrr
d5b8b06981 feat: use highlight.js package to load the hljs core 2021-11-04 09:01:03 +05:00
thecodrr
7820b33bce ci: use a specific retypeapp version 2021-11-04 09:00:29 +05:00
421 changed files with 332925 additions and 5776 deletions

8
.changeset/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

10
.changeset/config.json Normal file
View File

@@ -0,0 +1,10 @@
{
"$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}

View File

@@ -1,12 +1,14 @@
# This is a basic workflow to help you get started with Actions
name: CI
name: Docs Deploy
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [main]
paths:
- "docs/**"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -22,7 +24,7 @@ jobs:
- uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: Use Node.js 15.x
uses: actions/setup-node@v2.1.5
with:
@@ -34,7 +36,7 @@ jobs:
- uses: blbecker/rsync-deploy@v1.0
with:
source_dir: ./docs/public_html
destination_path: ${{ secrets.REMOTE_PATH }}
destination_path: ${{ secrets.REMOTE_DOCS_PATH }}
destination_host: ${{ secrets.REMOTE_HOST }}
deployment_user: ${{ secrets.REMOTE_USER }}
deployment_key: ${{ secrets.REMOTE_KEY }}

32
.github/workflows/enex-tests.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
# This is a basic workflow to help you get started with Actions
name: notesnook/enex tests
# Controls when the action will run.
on:
# Triggers the workflow on push events or manually
workflow_dispatch:
push:
branches: [main]
paths:
- "packages/enex/**"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v2.1.5
with:
node-version: 16.x
- run: |
cd packages/enex
npm i
npm run test

41
.github/workflows/importer-deploy.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
# This is a basic workflow to help you get started with Actions
name: Importer Deploy
# Controls when the action will run.
on:
# Triggers the workflow on push events or manually
workflow_dispatch:
push:
branches: [main]
paths:
- "apps/importer/**"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v2.1.5
with:
node-version: 16.x
- run: |
cd apps/importer
npm i
npm run build
mv ./build/ ./public_html/
- uses: blbecker/rsync-deploy@v1.0
with:
source_dir: ./apps/importer/public_html/
destination_path: ${{ secrets.REMOTE_IMPORTER_PATH }}
destination_host: ${{ secrets.REMOTE_HOST }}
deployment_user: ${{ secrets.REMOTE_USER }}
deployment_key: ${{ secrets.REMOTE_KEY }}

32
.github/workflows/importer-tests.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
# This is a basic workflow to help you get started with Actions
name: notesnook/importer tests
# Controls when the action will run.
on:
# Triggers the workflow on push events or manually
workflow_dispatch:
push:
branches: [main]
paths:
- "packages/importer/**"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v2.1.5
with:
node-version: 16.x
- run: |
cd packages/importer
npm i
npm run test

41
.github/workflows/vericrypt-deploy.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
# This is a basic workflow to help you get started with Actions
name: Vericrypt Deploy
# Controls when the action will run.
on:
# Triggers the workflow on push events or manually
workflow_dispatch:
push:
branches: [main]
paths:
- "apps/vericrypt/**"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v2.1.5
with:
node-version: 16.x
- run: |
cd apps/vericrypt
npm i
npm run build
mv ./build/ ./public_html/
- uses: blbecker/rsync-deploy@v1.0
with:
source_dir: ./apps/vericrypt/public_html/
destination_path: ${{ secrets.REMOTE_VERICRYPT_PATH }}
destination_host: ${{ secrets.REMOTE_HOST }}
deployment_user: ${{ secrets.REMOTE_USER }}
deployment_key: ${{ secrets.REMOTE_KEY }}

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.turbo
dist
node_modules

View File

@@ -0,0 +1,19 @@
const { version } = require("./package.json");
const fs = require("fs");
const path = require("path");
const APP_VERSION = version;
const CHANGELOG = fs.readFileSync(path.join(__dirname, "changelog.txt"), {
encoding: "utf8",
});
module.exports = {
all: {
REACT_APP_VERSION: APP_VERSION,
REACT_APP_CHANGELOG: CHANGELOG,
},
release: {
GENERATE_SOURCEMAP: false,
INLINE_RUNTIME_CHUNK: false,
DISABLE_ESLINT_PLUGIN: true,
},
};

23
apps/importer/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -0,0 +1,2 @@
1. 🥳 Added OneNote support! 🥳
2. 🥳 Added Zoho Notebook support! 🥳

34775
apps/importer/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
{
"name": "@notesnook/importer-web",
"version": "1.2.1",
"private": true,
"devDependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/file-saver": "^2.0.4",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-dropzone": "^5.1.0",
"@types/react-modal": "^3.13.1",
"@types/theme-ui": "^0.6.0",
"env-cmd": "^10.1.0",
"react-scripts": "4.0.3",
"typescript": "^4.1.2"
},
"dependencies": {
"@notesnook/importer": "^1.2.3",
"colord": "^2.9.2",
"file-saver": "^2.0.5",
"hash-wasm": "^4.9.0",
"interweave": "^12.9.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-dropzone": "^11.4.2",
"react-icons": "^4.3.1",
"react-modal": "^3.14.4",
"react-select": "^5.2.1",
"theme-ui": "^0.12.1"
},
"scripts": {
"start": "env-cmd -e all react-scripts start",
"build": "env-cmd -e all,release react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@@ -0,0 +1,7 @@
{
"associatedApplications": [
{
"applicationId": "4952c7cf-9c02-4fb7-b867-b87727bb52d8"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Import your notes from any notes app into Notesnook."
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Notesnook Importer</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

71
apps/importer/src/App.css Normal file
View File

@@ -0,0 +1,71 @@
/* open-sans-regular - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 400;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-regular.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 400;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-600 - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 600;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-600.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-600italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 600;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-600italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-600italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-700 - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 700;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-700.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-700italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 700;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-700italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

61
apps/importer/src/App.tsx Normal file
View File

@@ -0,0 +1,61 @@
import { Flex } from "@theme-ui/components";
import { ThemeProvider } from "@theme-ui/theme-provider";
import "./App.css";
import { ThemeFactory } from "./theme";
import { useState } from "react";
import { StepSeperator } from "./components/StepSeperator";
import { ProviderSelector } from "./components/ProviderSelector";
import { FileProviderHandler } from "./components/FileProviderHandler";
import { ImportResult } from "./components/ImportResult";
import { Hero } from "./components/Hero";
import { Footer } from "./components/Footer";
import { IProvider } from "@notesnook/importer";
import { NetworkProviderHandler } from "./components/NetworkProviderHandler";
import { ProviderResult } from "@notesnook/importer/dist/src/providers/provider";
function App() {
const [selectedProvider, setSelectedProvider] = useState<IProvider>();
const [providerResult, setProviderResult] = useState<ProviderResult>();
return (
<ThemeProvider theme={ThemeFactory.construct()}>
<Flex sx={{ flexDirection: "column" }}>
<Hero />
<Flex
sx={{
flexDirection: "column",
alignItems: "center",
}}
>
<ProviderSelector onProviderChanged={setSelectedProvider} />
{selectedProvider ? (
<>
<StepSeperator />
{selectedProvider.type === "file" ? (
<FileProviderHandler
provider={selectedProvider}
onTransformFinished={setProviderResult}
/>
) : selectedProvider.type === "network" ? (
<NetworkProviderHandler
provider={selectedProvider}
onTransformFinished={setProviderResult}
/>
) : null}
</>
) : null}
{providerResult ? (
<>
<StepSeperator />
<ImportResult result={providerResult} />{" "}
</>
) : null}
</Flex>
<Footer />
</Flex>
</ThemeProvider>
);
}
export default App;

View File

@@ -0,0 +1,42 @@
import { Flex, FlexProps, Text } from "@theme-ui/components";
import { PropsWithChildren, useState } from "react";
import { IoChevronDown, IoChevronUp } from "react-icons/io5";
type AccordionProps = FlexProps & {
title: string;
color?: string;
};
export function Accordion({
title,
children,
sx,
color,
...restProps
}: PropsWithChildren<AccordionProps>) {
const [isContentHidden, setIsContentHidden] = useState<boolean>(true);
return (
<Flex sx={{ flexDirection: "column", ...sx }} {...restProps}>
<Flex
sx={{
justifyContent: "space-between",
alignItems: "center",
p: 2,
cursor: "pointer",
}}
onClick={() => {
setIsContentHidden((state) => !state);
}}
>
<Text variant="subtitle" sx={{ color }}>
{title}
</Text>
{isContentHidden ? (
<IoChevronDown size={16} color={color} />
) : (
<IoChevronUp size={16} color={color} />
)}
</Flex>
{!isContentHidden && children}
</Flex>
);
}

View File

@@ -0,0 +1,152 @@
import { Flex, Input, Text } from "@theme-ui/components";
import { useCallback, useEffect, useState } from "react";
import { useDropzone } from "react-dropzone";
import { StepContainer } from "./StepContainer";
import { Accordion } from "./Accordion";
import { IFileProvider, transform } from "@notesnook/importer";
import { xxhash64 } from "hash-wasm";
import {
ProviderResult,
ProviderSettings,
} from "@notesnook/importer/dist/src/providers/provider";
import { IFile } from "@notesnook/importer/dist/src/utils/file";
type FileProviderHandlerProps = {
provider: IFileProvider;
onTransformFinished: (result: ProviderResult) => void;
};
type Progress = {
total: number;
done: number;
};
const settings: ProviderSettings = {
clientType: "browser",
hasher: { type: "xxh64", hash: (data) => xxhash64(data) },
};
export function FileProviderHandler(props: FileProviderHandlerProps) {
const { provider, onTransformFinished } = props;
const [files, setFiles] = useState<File[]>([]);
const [progress, setProgress] = useState<Progress>({ total: 0, done: 0 });
const onDrop = useCallback((acceptedFiles: File[]) => {
setFiles((files) => {
const newFiles = [...acceptedFiles, ...files];
return newFiles;
});
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept: provider?.supportedExtensions?.concat(".zip"),
});
useEffect(() => {
setFiles([]);
}, [provider]);
useEffect(() => {
(async () => {
if (!provider || !files.length) return;
setProgress({ total: 0, done: 0 });
let result: ProviderResult = { notes: [], errors: [] };
for (let file of files) {
const providerFile: IFile = {
name: file.name,
data: await file.arrayBuffer(),
modifiedAt: file.lastModified,
};
const transformResult = await transform(
provider,
[providerFile],
settings
);
result.notes.push(...transformResult.notes);
result.errors.push(...transformResult.errors);
setProgress((p) => ({ total: files.length, done: p.done + 1 }));
}
setProgress({ total: 0, done: 0 });
onTransformFinished(result);
})();
}, [provider, files, onTransformFinished]);
return (
<StepContainer sx={{ flexDirection: "column", alignItems: "stretch" }}>
<Text variant="title">Select {provider?.name} files</Text>
<Flex
{...getRootProps()}
sx={{
justifyContent: "center",
alignItems: "center",
height: 200,
border: "2px dashed var(--theme-ui-colors-border)",
borderRadius: "default",
mt: 2,
}}
>
<Input {...getInputProps()} />
<Text variant="body" sx={{ textAlign: "center" }}>
{isDragActive
? "Drop the files here"
: "Drag & drop files here, or click to select files"}
<br />
<Text variant="subBody">
Only {provider?.supportedExtensions.join(", ")} files are supported.
You can also select .zip files containing{" "}
{provider?.supportedExtensions.join(", ")} files.
</Text>
</Text>
</Flex>
{files.length > 0 ? (
<Accordion
title={`${files.length} ${
files.length > 1 ? "files" : "file"
} selected`}
sx={{
border: "1px solid var(--theme-ui-colors-border)",
mt: 2,
borderRadius: "default",
}}
>
<Flex
sx={{ flexDirection: "column", overflowY: "auto", maxHeight: 400 }}
>
{files.map((file, index) => (
<Flex
key={file.name}
sx={{
flexDirection: "column",
p: 2,
bg: index % 2 ? "transparent" : "bgSecondary",
cursor: "pointer",
":hover": {
bg: "hover",
},
}}
onClick={() => {
setFiles((files) => {
const _files = files.slice();
_files.splice(index, 1);
return _files;
});
}}
title="Click to remove"
>
<Text variant="body">{file.name}</Text>
</Flex>
))}
</Flex>
</Accordion>
) : null}
{progress.total > 0 ? (
<Text variant="body">
Processing files ({progress.done}/{progress.total})
</Text>
) : null}
</StepContainer>
);
}

View File

@@ -0,0 +1,21 @@
import { Flex, Text } from "@theme-ui/components";
import { appVersion } from "../utils/version";
export function Footer() {
return (
<Flex
sx={{
flexDirection: "column",
mt: 100,
pt: 50,
pb: 50,
borderTop: "1px solid var(--theme-ui-colors-border)",
alignItems: "center",
justifyContent: "center",
}}
>
<Text variant="body">Notesnook Importer (v{appVersion})</Text>
<Text variant="subBody">© 2021 Streetwriters LLC</Text>
</Flex>
);
}

View File

@@ -0,0 +1,63 @@
import { Flex, Link, Text } from "@theme-ui/components";
import { appVersion } from "../utils/version";
export function Hero() {
return (
<Flex
sx={{
flexDirection: "column",
mt: 150,
mb: 100,
justifyContent: "center",
alignItems: "center",
}}
>
<Text variant="heading" sx={{ textAlign: "center" }}>
Notesnook Importer
</Text>
<Text
sx={{
fontSize: "title",
textAlign: "center",
color: "fontTertiary",
}}
>
Import your notes from any notes app into Notesnook.
</Text>
<Flex sx={{ mt: 2 }}>
<Text variant="body" sx={{ px: 1 }}>
v{appVersion}
</Text>
<Link
href="https://github.com/streetwriters/notesnook"
variant="text.body"
sx={{ px: 1, borderLeft: "1px solid var(--theme-ui-colors-border)" }}
>
Github
</Link>
<Link
href="https://app.notesnook.com/"
variant="text.body"
sx={{ px: 1, borderLeft: "1px solid var(--theme-ui-colors-border)" }}
>
Notesnook Web
</Link>
</Flex>
<Flex
sx={{
bg: "bgSecondary",
flexDirection: "column",
width: 400,
mt: 4,
p: 2,
borderRadius: "default",
}}
>
<Text variant="subtitle">What's new in v{appVersion}</Text>
<Text variant="body" sx={{ whiteSpace: "pre-wrap" }}>
{process.env.REACT_APP_CHANGELOG}
</Text>
</Flex>
</Flex>
);
}

View File

@@ -0,0 +1,41 @@
import { Button, Flex, Text } from "@theme-ui/components";
import { Accordion } from "./Accordion";
import { TransformError } from "@notesnook/importer/dist/src/utils/transformerror";
type ImportErrorsProps = {
errors: TransformError[];
};
export function ImportErrors(props: ImportErrorsProps) {
return (
<Accordion
title={`${props.errors.length} errors occured`}
sx={{ bg: "errorBg", borderRadius: "default", mt: 2 }}
color="#E53935"
>
<Flex sx={{ flexDirection: "column", px: 2, pb: 2 }}>
{props.errors.map((error, index) => (
<Text
variant="body"
sx={{ color: "error", my: 1, fontFamily: "monospace" }}
>
{index + 1}. {error.message}{" "}
{error.file ? `(${error.file.name})` : ""}
<br />
</Text>
))}
<Button
sx={{ bg: "error", color: "static", alignSelf: "start", mt: 2 }}
onClick={() =>
window.open(
"https://github.com/streetwriters/notesnook/issues/new",
"_blank"
)
}
>
Send us a bug report
</Button>
</Flex>
</Accordion>
);
}

View File

@@ -0,0 +1,47 @@
import { Button, Text } from "@theme-ui/components";
import { Accordion } from "./Accordion";
type ImportHelpProps = {
onDownload: () => void;
};
export function ImportHelp(props: ImportHelpProps) {
return (
<Accordion
title="How to import your notes into Notesnook?"
sx={{ bg: "bgSecondary", mt: 2, borderRadius: "default" }}
>
<Text
as="ol"
variant="body"
sx={{
lineHeight: "24px",
paddingInlineStart: 30,
pb: 2,
}}
>
<Text as="li">
<Button variant="primary" sx={{ py: 0 }} onClick={props.onDownload}>
Download the ZIP file
</Button>{" "}
containing your notes
</Text>
<Text as="li">
<a href="https://app.notesnook.com/">Open Notesnook</a> and make sure
you are logged in.
</Text>
<Text as="li">
Go to <b>Settings</b>
</Text>
<Text as="li">
Expand the section titled <b>Notesnook Importer</b>
</Text>
<Text as="li">
Click on <b>Import from ZIP file</b>
</Text>
<Text as="li">Select the downloaded ZIP file</Text>
<Text as="li">Your notes should appear in the app.</Text>
</Text>
</Accordion>
);
}

View File

@@ -0,0 +1,64 @@
import { Button, Text } from "@theme-ui/components";
import { pack } from "@notesnook/importer";
import { useCallback, useState } from "react";
import { ProviderResult } from "@notesnook/importer/dist/src/providers/provider";
import { Note } from "@notesnook/importer/dist/src/models/note";
import { StepContainer } from "./StepContainer";
import { NotePreview } from "./NotePreview";
import { ImportErrors } from "./ImportErrors";
import { ImportHelp } from "./ImportHelp";
import { saveAs } from "file-saver";
import { NotesList } from "./NotesList";
type ImportResultProps = {
result: ProviderResult;
};
export function ImportResult(props: ImportResultProps) {
const { result } = props;
const [selectedNote, setSelectedNote] = useState<Note | undefined>();
const downloadAsZip = useCallback(() => {
if (!result) return;
const packed = pack(result.notes);
saveAs(
new Blob([packed], { type: "application/zip" }),
`notesnook-importer.zip`
);
}, [result]);
return (
<StepContainer
sx={{
flexDirection: "column",
alignItems: "stretch",
}}
>
<Text variant="title">Your notes are ready for download</Text>
{result ? (
<>
<Text variant="body" sx={{ color: "fontTertiary" }}></Text>
<NotesList
notes={result?.notes}
onNoteSelected={(note) => setSelectedNote(note)}
/>
{result.errors.length > 0 && <ImportErrors errors={result.errors} />}
<ImportHelp onDownload={downloadAsZip} />
<Button
variant="primary"
sx={{ alignSelf: "center", mt: 2 }}
onClick={downloadAsZip}
>
Download ZIP file
</Button>
</>
) : null}
{selectedNote && (
<NotePreview
note={selectedNote}
onClose={() => setSelectedNote(undefined)}
/>
)}
</StepContainer>
);
}

View File

@@ -0,0 +1,88 @@
import { Text, Button } from "@theme-ui/components";
import { StepContainer } from "./StepContainer";
import { INetworkProvider } from "@notesnook/importer";
import {
ProviderResult,
ProviderSettings,
} from "@notesnook/importer/dist/src/providers/provider";
import { xxhash64 } from "hash-wasm";
import { OneNote } from "@notesnook/importer/dist/src/providers/onenote";
import { useCallback, useState } from "react";
type NetworkProviderHandlerProps = {
provider: INetworkProvider<unknown>;
onTransformFinished: (result: ProviderResult) => void;
};
const settings: ProviderSettings = {
clientType: "browser",
hasher: { type: "xxh64", hash: (data) => xxhash64(data) },
};
export function NetworkProviderHandler(props: NetworkProviderHandlerProps) {
const { provider, onTransformFinished } = props;
const [progress, setProgress] = useState<string | null>();
const startImport = useCallback(() => {
(async () => {
if (!provider) return;
setProgress(null);
let result: ProviderResult = { notes: [], errors: [] };
if (provider instanceof OneNote) {
result = await provider.process({
...settings,
clientId: "4952c7cf-9c02-4fb7-b867-b87727bb52d8",
redirectUri:
process.env.NODE_ENV === "development"
? "http://localhost:3000"
: "https://importer.notesnook.com",
report: setProgress,
});
}
setProgress(null);
onTransformFinished(result);
})();
}, [onTransformFinished, provider]);
return (
<StepContainer
sx={{
flexDirection: "column",
alignItems: "stretch",
}}
>
{progress ? (
<>
<Text variant="title">Importing your notes from {provider.name}</Text>
<Text
as="pre"
variant="body"
sx={{
textAlign: "center",
my: 4,
bg: "bgSecondary",
p: 4,
fontFamily: "monospace",
whiteSpace: "pre-wrap",
}}
>
{progress}
</Text>
</>
) : (
<>
<Text variant="title">Connect your {provider.name} account</Text>
<Button
variant="primary"
onClick={startImport}
sx={{ my: 4, alignSelf: "center" }}
>
Start importing
</Button>
</>
)}
</StepContainer>
);
}

View File

@@ -0,0 +1,152 @@
import { Button, Flex, Text } from "@theme-ui/components";
import { IoStarOutline } from "react-icons/io5";
import { GrPin } from "react-icons/gr";
import { MdCircle, MdClose, MdOutlineBook } from "react-icons/md";
import { Markup } from "interweave";
import Modal from "react-modal";
import { Note } from "@notesnook/importer/dist/src/models/note";
Modal.setAppElement("#root");
type NotePreviewProps = {
note: Note;
onClose: () => void;
};
export function NotePreview(props: NotePreviewProps) {
const {
title,
content,
dateEdited,
dateCreated,
favorite,
color,
pinned,
notebooks,
tags,
attachments,
} = props.note;
return (
<Modal
isOpen={true}
contentLabel={title}
style={{
content: {
borderRadius: 10,
border: "1px solid var(--theme-ui-colors-border)",
boxShadow: "0px 0px 20px 0px #00000011",
},
}}
>
<Flex sx={{ flexDirection: "column" }}>
<Flex sx={{ justifyContent: "space-between", alignItems: "center" }}>
<Text variant="subBody">
This preview is not an exact representation of how the note will
appear in Notesnook.
</Text>
<Button
variant="secondary"
sx={{
bg: "transparent",
display: "flex",
alignSelf: "end",
p: 0,
m: 0,
alignItems: "center",
}}
onClick={props.onClose}
>
<MdClose size={24} />
</Button>
</Flex>
<Text as="h1" variant="subheading">
{title}
</Text>
<Flex sx={{ alignItems: "center" }}>
{color && (
<MdCircle color={color} size={14} style={{ marginRight: 5 }} />
)}
{favorite && <IoStarOutline style={{ marginRight: 5 }} />}
{pinned && <GrPin size={12} style={{ marginRight: 5 }} />}
{dateCreated && (
<>
<Text variant="subBody">
Created on: {formatDate(dateCreated)}
</Text>
</>
)}
{dateEdited && (
<>
<MdCircle
color="#5b5b5b"
size={7}
style={{ marginLeft: 3, marginRight: 3 }}
/>
<Text variant="subBody">
Last modified: {formatDate(dateEdited)}
</Text>
</>
)}
{attachments && (
<>
<MdCircle
color="#5b5b5b"
size={7}
style={{ marginLeft: 3, marginRight: 3 }}
/>
<Text variant="subBody">{attachments.length} attachments</Text>
</>
)}
</Flex>
<Flex my={1}>
{notebooks?.map((notebook) => (
<Flex
key={notebook.notebook + notebook.topic}
sx={{
alignItems: "center",
bg: "bgSecondary",
mr: 1,
p: 1,
py: "2px",
border: "1px solid var(--theme-ui-colors-border)",
borderRadius: "default",
color: "fontTertiary",
}}
>
<MdOutlineBook size={11} />
<Text variant="subBody" sx={{ ml: "2px" }}>
{notebook.notebook} &gt; {notebook.topic}
</Text>
</Flex>
))}
{tags?.map((tag) => (
<Text
key={tag}
variant="subBody"
sx={{
bg: "bgSecondary",
mr: 1,
p: 1,
py: "2px",
border: "1px solid var(--theme-ui-colors-border)",
borderRadius: "default",
color: "fontTertiary",
}}
>
#{tag}
</Text>
))}
</Flex>
<Text variant="body">
<Markup content={content?.data} />
</Text>
</Flex>
</Modal>
);
}
function formatDate(date: number) {
return new Date(date).toLocaleString(undefined, {
dateStyle: "short",
timeStyle: "short",
});
}

View File

@@ -0,0 +1,60 @@
import { Flex, Text } from "@theme-ui/components";
import { Note } from "@notesnook/importer/dist/src/models/note";
import { Accordion } from "./Accordion";
type NotesListProps = {
notes: Note[];
onNoteSelected: (note: Note) => void;
};
export function NotesList(props: NotesListProps) {
const { notes, onNoteSelected } = props;
return (
<Accordion
title={`${notes.length} notes found`}
sx={{
border: "1px solid var(--theme-ui-colors-border)",
mt: 2,
borderRadius: "default",
}}
>
<Flex
sx={{
flexDirection: "column",
overflowY: "auto",
maxHeight: 300,
}}
>
{notes.map((note, index) => (
<Flex
key={note.title + note.dateCreated}
sx={{
flexDirection: "column",
p: 2,
bg: index % 2 ? "transparent" : "bgSecondary",
cursor: "pointer",
":hover": {
bg: "hover",
},
}}
onClick={() => {
onNoteSelected(note);
}}
title="Click to preview"
>
<Text variant="body">{note.title}</Text>
{note.dateEdited && (
<Text variant="subBody">
Last modified on:{" "}
{new Date(note.dateEdited).toLocaleString(undefined, {
dateStyle: "short",
timeStyle: "short",
})}
</Text>
)}
</Flex>
))}
</Flex>
</Accordion>
);
}

View File

@@ -0,0 +1,53 @@
import { Flex, Select, Text } from "@theme-ui/components";
import { IProvider, ProviderFactory } from "@notesnook/importer";
import { Providers } from "@notesnook/importer/dist/src/providers/providerfactory";
import { StepContainer } from "./StepContainer";
type ProviderSelectorProps = {
onProviderChanged: (provider: IProvider) => void;
};
export function ProviderSelector(props: ProviderSelectorProps) {
return (
<StepContainer sx={{ flexDirection: "column" }}>
<Flex sx={{ justifyContent: "space-between" }}>
<Text variant="title">Choose a provider to import from</Text>
<Select
sx={{
p: 0,
m: 0,
px: 2,
border: "1px solid var(--theme-ui-colors-border)",
outline: "none",
":hover": {
borderColor: "hover",
},
":active": {
borderColor: "active",
},
fontFamily: "body",
fontSize: "body",
width: 150,
}}
onChange={(e) => {
const providerName: Providers = e.target.value as Providers;
props.onProviderChanged(ProviderFactory.getProvider(providerName));
}}
>
<option value=""></option>
{ProviderFactory.getAvailableProviders().map((provider) => (
<option key={provider} value={provider}>
{ProviderFactory.getProvider(provider as Providers).name}
</option>
))}
</Select>
</Flex>
<Text variant="body" sx={{ color: "fontTertiary" }}>
Can't find your notes app in the list?{" "}
<a href="https://github.com/streetwriters/notesnook/issues/new">
Send us a request.
</a>
</Text>
</StepContainer>
);
}

View File

@@ -0,0 +1,22 @@
import { Flex, FlexProps } from "@theme-ui/components";
export function StepContainer({
children,
sx,
...restProps
}: React.PropsWithChildren<FlexProps>) {
return (
<Flex
sx={{
width: "40%",
boxShadow: "0px 0px 20px 0px #00000011",
p: 4,
borderRadius: "default",
...sx,
}}
{...restProps}
>
{children}
</Flex>
);
}

View File

@@ -0,0 +1,5 @@
import { Box } from "@theme-ui/components";
export function StepSeperator() {
return <Box sx={{ height: 150, width: 2, bg: "bgSecondary" }} />;
}

View File

View File

@@ -0,0 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);

1
apps/importer/src/react-app-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@@ -0,0 +1,28 @@
import { colord } from "colord";
import { StaticColors } from "./static";
export class DarkColorScheme {
static construct(accent: string) {
return {
primary: colord(accent).toHex(),
placeholder: colord("#ffffff")
.alpha(0.6)
.toHex(),
background: "#1f1f1f",
bgTransparent: "#1f1f1f99",
accent: "#000",
bgSecondary: "#2b2b2b",
bgSecondaryText: "#A1A1A1",
border: "#2b2b2b",
hover: "#3b3b3b",
fontSecondary: "#000",
fontTertiary: "#A1A1A1",
text: "#d3d3d3",
overlay: "rgba(53, 53, 53, 0.5)",
secondary: "black",
icon: "#dbdbdb",
disabled: "#5b5b5b",
...StaticColors.construct(accent),
};
}
}

View File

@@ -0,0 +1,14 @@
import { DarkColorScheme } from "./dark";
import { LightColorScheme } from "./light";
const colorSchemes = {
dark: DarkColorScheme,
light: LightColorScheme,
};
class ColorSchemeFactory {
static construct<TTheme extends keyof typeof colorSchemes>(theme: TTheme) {
return colorSchemes[theme].construct("#008837");
}
}
export default ColorSchemeFactory;

View File

@@ -0,0 +1,29 @@
import { colord } from "colord";
import { StaticColors } from "./static";
export class LightColorScheme {
static construct(accent: string) {
return {
primary: colord(accent).toHex(),
background: "white",
bgTransparent: "#ffffff99",
accent: "white",
bgSecondary: "#f7f7f7",
bgSecondaryText: "#5E5E5E",
border: "#e7e7e7",
hover: "#f0f0f0",
active: "#ababab",
fontSecondary: "white",
fontTertiary: "#656565",
text: "#202124",
overlay: "rgba(0, 0, 0, 0.1)",
secondary: "white",
icon: "#3b3b3b",
disabled: "#9b9b9b",
placeholder: colord("#000000")
.alpha(0.6)
.toHex(),
...StaticColors.construct(accent),
};
}
}

View File

@@ -0,0 +1,31 @@
import { colord } from "colord";
export class StaticColors {
static construct(accent: string) {
return {
shade: colord(accent)
.alpha(0.1)
.toRgbString(),
textSelection: colord(accent)
.alpha(0.2)
.toRgbString(),
dimPrimary: colord(accent)
.alpha(0.7)
.toRgbString(),
transparent: "transparent",
static: "white",
error: "#E53935",
errorBg: "#E5393520",
success: "#4F8A10",
warn: "#FF5722",
favorite: "#ffd700",
red: "#f44336",
orange: "#FF9800",
yellow: "#f0c800",
green: "#4CAF50",
blue: "#2196F3",
purple: "#9568ED",
gray: "#9E9E9E",
};
}
}

View File

@@ -0,0 +1,13 @@
export class FontSizeFactory {
static construct() {
return {
heading: "48px",
subheading: "24px",
title: "16px",
subtitle: "14px",
body: "14px",
input: "12px",
subBody: "12px",
};
}
}

View File

@@ -0,0 +1,19 @@
import { FontSizeFactory } from "./fontsize";
export class FontFactory {
static construct() {
return {
fontSizes: FontSizeFactory.construct(),
fontWeights: {
normal: 400,
body: 400,
heading: 600,
bold: 600,
},
fonts: {
body: `Open Sans,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Oxygen-Sans,Ubuntu,Cantarell,sans-serif;`,
heading: `Open Sans,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Oxygen-Sans,Ubuntu,Cantarell,sans-serif;`,
},
};
}
}

View File

@@ -0,0 +1,24 @@
import ColorSchemeFactory from "./colorscheme";
import VariantsFactory from "./variants";
import { FontFactory } from "./font";
import { Theme } from "theme-ui";
export class ThemeFactory {
static construct(): Theme {
return {
breakpoints: ["480px", "1000px", "1000px"],
space: [0, 5, 10, 15, 20, 25, 30, 35],
sizes: { full: "100%", half: "50%" },
radii: { none: 0, default: 10 },
colors: {
modes: {
dark: ColorSchemeFactory.construct("dark"),
light: ColorSchemeFactory.construct("light"),
},
},
rawColors: ColorSchemeFactory.construct("light"),
...FontFactory.construct(),
...new VariantsFactory(),
};
}
}

View File

@@ -0,0 +1,76 @@
class ButtonFactory {
constructor() {
return {
default: new Default(),
primary: new Primary(),
secondary: new Secondary(),
tertiary: new Tertiary(),
};
}
}
export default ButtonFactory;
class Default {
constructor() {
return {
bg: "transparent",
fontFamily: "body",
fontWeight: "body",
fontSize: "body",
borderRadius: "5px",
cursor: "pointer",
p: 1,
px: 2,
transition: "filter 200ms ease-in, box-shadow 200ms ease-out",
":hover:not(:disabled)": {
filter: "brightness(90%)",
},
":active": {
filter: "brightness(98%)",
},
outline: "none",
":focus-visible:not(:active)": {
boxShadow: "0px 0px 0px 2px var(--text)",
},
":disabled": {
opacity: 0.5,
cursor: "not-allowed",
},
};
}
}
class Primary {
constructor() {
return {
variant: "buttons.default",
color: "static",
bg: "primary",
};
}
}
class Secondary {
constructor() {
return {
variant: "buttons.default",
color: "text",
bg: "border",
};
}
}
class Tertiary {
constructor() {
return {
variant: "buttons.default",
color: "text",
bg: "transparent",
border: "2px solid",
borderColor: "border",
":hover": {
borderColor: "primary",
},
};
}
}

View File

@@ -0,0 +1,14 @@
import ButtonFactory from "./button";
import InputFactory from "./input";
import TextFactory from "./text";
class VariantFactory {
constructor() {
return {
buttons: new ButtonFactory(),
forms: new InputFactory(),
text: new TextFactory(),
};
}
}
export default VariantFactory;

View File

@@ -0,0 +1,64 @@
class InputFactory {
constructor() {
return {
input: new Default(),
error: new Error(),
clean: new Clean(),
};
}
}
export default InputFactory;
class Default {
constructor() {
return {
borderRadius: "default",
border: "none",
// borderColor: "border",
boxShadow: "0px 0px 0px 1px var(--border) inset",
fontFamily: "body",
fontWeight: "body",
fontSize: "input",
color: "text",
outline: "none",
":focus": {
boxShadow: "0px 0px 0px 1.5px var(--primary) inset",
},
":hover:not(:focus)": {
boxShadow: "0px 0px 0px 1px var(--dimPrimary) inset",
},
};
}
}
class Clean {
constructor() {
return {
variant: "forms.input",
outline: "none",
boxShadow: "none",
":focus": {
boxShadow: "none",
},
":hover:not(:focus)": {
boxShadow: "none",
},
};
}
}
class Error {
constructor() {
return {
variant: "forms.input",
boxShadow: "0px 0px 0px 1px var(--error) inset",
outline: "none",
":focus": {
boxShadow: "0px 0px 0px 1.5px var(--error) inset",
},
":hover:not(:focus)": {
boxShadow: "0px 0px 0px 1px var(--error) inset",
},
};
}
}

View File

@@ -0,0 +1,85 @@
class TextFactory {
constructor() {
return {
default: new Default(),
heading: new Heading(),
subheading: new Subheading(),
title: new Title(),
subtitle: new Subtitle(),
body: new Body(),
subBody: new SubBody(),
error: new Error(),
};
}
}
export default TextFactory;
class Default {
constructor() {
return {
color: "text",
fontFamily: "body",
};
}
}
class Heading {
constructor() {
return {
variant: "text.default",
fontFamily: "heading",
fontWeight: "bold",
fontSize: "heading",
};
}
}
class Subheading {
constructor() {
return {
variant: "text.heading",
fontSize: "subheading",
};
}
}
class Title {
constructor() {
return {
variant: "text.heading",
fontSize: "title",
fontWeight: "bold",
};
}
}
class Subtitle {
constructor() {
return {
variant: "text.heading",
fontSize: "subtitle",
fontWeight: "bold",
};
}
}
class Body {
constructor() {
return { variant: "text.default", fontSize: "body" };
}
}
class SubBody {
constructor() {
return {
variant: "text.default",
fontSize: "subBody",
color: "fontTertiary",
};
}
}
class Error {
constructor() {
return { variant: "text.default", fontSize: "subBody", color: "error" };
}
}

View File

@@ -0,0 +1 @@
export const appVersion = process.env.REACT_APP_VERSION;

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"exclude": ["node_modules"],
"include": ["src"]
}

View File

@@ -0,0 +1,13 @@
const { version } = require("./package.json");
const APP_VERSION = version;
module.exports = {
all: {
REACT_APP_VERSION: APP_VERSION,
},
release: {
GENERATE_SOURCEMAP: false,
INLINE_RUNTIME_CHUNK: false,
DISABLE_ESLINT_PLUGIN: true,
},
};

23
apps/vericrypt/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

0
apps/vericrypt/README.md Normal file
View File

38562
apps/vericrypt/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
{
"name": "@notesnook/vericrypt",
"version": "1.0.0",
"private": true,
"devDependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/file-saver": "^2.0.4",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/platform": "^1.3.4",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-dropzone": "^5.1.0",
"@types/react-modal": "^3.13.1",
"@types/theme-ui": "^0.6.0",
"env-cmd": "^10.1.0",
"react-scripts": "4.0.3",
"typescript": "^4.1.2"
},
"dependencies": {
"@notesnook/crypto": "^1.0.0",
"clipboard-polyfill": "^3.0.3",
"colord": "^2.9.2",
"platform": "^1.3.6",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"theme-ui": "^0.12.1"
},
"scripts": {
"start": "env-cmd -e all react-scripts start",
"build": "env-cmd -e all,release react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="An open source utility to verify Notesnook data encryption in a safe & reliable way."
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Notesnook Vericrypt</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -0,0 +1,71 @@
/* open-sans-regular - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 400;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-regular.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 400;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-600 - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 600;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-600.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-600italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 600;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-600italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-600italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-700 - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: normal;
font-weight: 700;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-700.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* open-sans-700italic - latin */
@font-face {
font-family: "Open Sans";
font-display: swap;
font-style: italic;
font-weight: 700;
src: local(""),
url("./assets/fonts/open-sans-v20-latin-700italic.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("./assets/fonts/open-sans-v20-latin-700italic.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

142
apps/vericrypt/src/App.tsx Normal file
View File

@@ -0,0 +1,142 @@
import { Image, Flex, Text } from "@theme-ui/components";
import { ThemeProvider } from "@theme-ui/theme-provider";
import "./App.css";
import { MdVpnKey, MdCheck } from "react-icons/md";
import { BiPlus } from "react-icons/all";
import { ThemeFactory } from "./theme";
import { Hero } from "./components/Hero";
import { LoginToNotesnook } from "./components/Step1";
import { GetAccountSalt } from "./components/Step2";
import { EnterAccountPassword } from "./components/Step3";
import { PasteEncryptedData, SyncRequestBody } from "./components/Step4";
import { StepSeperator } from "./components/StepSeperator";
import { Footer } from "./components/Footer";
import { useState } from "react";
import { NNCrypto } from "@notesnook/crypto";
import { Code } from "./components/Code";
import { Accordion } from "./components/Accordion";
import { DecryptedResult } from "./components/DecryptedResult";
import Map from "./assets/images/map.svg";
const instructions = [
"Go to Notesnook",
"Open Settings",
<>
Click on <Code text="Backup data recovery key" />
</>,
"Enter your account password for verification",
"Confirm that your generated encryption key matches",
];
function App() {
const [password, setPassword] = useState<string>();
const [salt, setSalt] = useState<string>();
const [key, setKey] = useState<string>();
const [data, setData] = useState<SyncRequestBody | undefined>();
return (
<ThemeProvider theme={ThemeFactory.construct()}>
<Flex sx={{ flexDirection: "column" }}>
<Image src={Map} sx={{ position: "absolute", opacity: 0.1 }} />
<Hero />
<Flex
sx={{
flexDirection: "column",
alignItems: "center",
}}
>
<LoginToNotesnook />
<StepSeperator />
<GetAccountSalt onSaltSubmitted={setSalt} />
{salt && (
<>
<StepSeperator icon={BiPlus} />
<EnterAccountPassword onPasswordSubmitted={setPassword} />
</>
)}
{salt && password && (
<>
<StepSeperator
icon={MdVpnKey}
tooltip="Click to see derived encryption key"
onShowPopup={async () => {
if (!password) return false;
const { key } = await new NNCrypto().exportKey(
password,
salt
);
setKey(key);
return true;
}}
popup={{
title: "Your data encryption key",
body: key ? (
<>
<Text
as="code"
sx={{
fontFamily: "monospace",
mt: 2,
bg: "bgSecondary",
p: 1,
borderRadius: 5,
}}
>
{key}
</Text>
<Accordion
title="How to verify your encryption key?"
sx={{
border: "1px solid var(--theme-ui-colors-border)",
mt: 2,
borderRadius: "default",
}}
>
<Text variant="body" sx={{ mx: 2 }}>
Now that you have derived your encryption key, you'll
want to verify it to make sure we didn't just make it
up. To do so, follow these steps:
<Text as="ol" variant="body" sx={{ mb: 2 }}>
{instructions?.map((item) => (
<Text as="li" sx={{ mt: 1 }}>
{item}
</Text>
))}
</Text>
</Text>
</Accordion>
</>
) : (
undefined
),
}}
/>
<PasteEncryptedData onEncryptedDataPasted={setData} />
</>
)}
{password && salt && data && (
<>
<StepSeperator icon={MdCheck} />
<DecryptedResult
password={password}
salt={salt}
data={data}
onRestartProcess={() => {
setSalt(undefined);
setPassword(undefined);
setKey(undefined);
setData(undefined);
}}
/>
</>
)}
</Flex>
<Footer />
</Flex>
</ThemeProvider>
);
}
export default App;

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,43 @@
import { Flex, FlexProps, Text } from "@theme-ui/components";
import { PropsWithChildren, useState } from "react";
import { IoChevronDown, IoChevronUp } from "react-icons/io5";
type AccordionProps = FlexProps & {
title: string;
color?: string;
};
export function Accordion({
title,
children,
sx,
color = "icon",
...restProps
}: PropsWithChildren<AccordionProps>) {
const [isContentHidden, setIsContentHidden] = useState<boolean>(true);
return (
<Flex sx={{ flexDirection: "column", ...sx }} {...restProps}>
<Flex
sx={{
justifyContent: "space-between",
alignItems: "center",
p: 2,
cursor: "pointer",
color: color,
}}
onClick={() => {
setIsContentHidden((state) => !state);
}}
>
<Text variant="subtitle" sx={{ color }}>
{title}
</Text>
{isContentHidden ? (
<IoChevronDown size={16} color={color} />
) : (
<IoChevronUp size={16} color={color} />
)}
</Flex>
{!isContentHidden && children}
</Flex>
);
}

View File

@@ -0,0 +1,26 @@
import { Text, Link } from "@theme-ui/components";
type CodeProps = { text: string; href?: string };
export function Code(props: CodeProps) {
return (
<Text
as="code"
sx={{
bg: "bgSecondary",
px: 1,
borderRadius: 5,
fontFamily: "monospace",
border: "1px solid var(--theme-ui-colors-border)",
cursor: props.href ? "pointer" : "unset",
}}
>
{props.href ? (
<Link href={props.href} color="primary">
{props.text}
</Link>
) : (
props.text
)}
</Text>
);
}

View File

@@ -0,0 +1,166 @@
import { Flex, Button, Text, Link } from "@theme-ui/components";
import { StepContainer } from "./StepContainer";
import { SyncRequestBody } from "./Step4";
import { NNCrypto } from "@notesnook/crypto";
import { useEffect, useState } from "react";
import { FcDataEncryption } from "react-icons/fc";
import { Code } from "./Code";
import { getSourceUrl } from "../utils/links";
import * as clipboard from "clipboard-polyfill/text";
import { Accordion } from "./Accordion";
import { ErrorsList } from "./ErrorsList";
type DecryptedResultProps = {
password: string;
salt: string;
data: SyncRequestBody;
onRestartProcess: () => void;
};
export function DecryptedResult(props: DecryptedResultProps) {
const [isDecrypting, setIsDecrypting] = useState(true);
const [decryptedData, setDecryptedData] = useState<string>();
const [error, setError] = useState<string | undefined>();
useEffect(() => {
(async function() {
try {
const data: any = {
notes: [],
notebooks: [],
content: [],
attachments: [],
};
const crypto = new NNCrypto();
const key = await crypto.exportKey(props.password, props.salt);
for (let arrayKey in data) {
const array = data[arrayKey];
for (let encryptedItem of (props.data as any)[arrayKey]) {
const { data } = await crypto.decrypt(key, encryptedItem, "text");
array.push(JSON.parse(data as string));
}
}
setDecryptedData(JSON.stringify(data, undefined, " "));
} catch (e) {
const error = e as Error;
setError(error.message);
} finally {
setIsDecrypting(false);
}
})();
}, [props]);
if (error)
return (
<StepContainer
as="form"
sx={{
flexDirection: "column",
}}
>
<Text variant="title">Decryption failed</Text>
<ErrorsList errors={[error]} />
</StepContainer>
);
if (isDecrypting)
return (
<StepContainer
as="form"
sx={{
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}
>
<FcDataEncryption size={50} />
<Text variant="title" sx={{ mt: 2 }}>
Decrypting your data...
</Text>
</StepContainer>
);
return (
<StepContainer
sx={{
flexDirection: "column",
border: "2px solid var(--theme-ui-colors-primary)",
}}
>
<Flex sx={{ justifyContent: "space-between", alignItems: "center" }}>
<Text variant="title">Your data has been decrypted</Text>
<Code
text="src/components/DecryptedResult.tsx"
href={getSourceUrl("src/components/DecryptedResult.tsx")}
/>
</Flex>
<Text variant="body">
This is your data in it's raw decrypted format. Feel free to scroll
through and see what it contains.
</Text>
<Text
as="pre"
variant="body"
sx={{
maxHeight: 400,
overflowY: "auto",
fontFamily: "monospace",
whiteSpace: "pre-wrap",
color: "icon",
mt: 2,
}}
>
{decryptedData}
</Text>
<Accordion
title="What happens now?"
sx={{
border: "1px solid var(--theme-ui-colors-border)",
mt: 2,
borderRadius: "default",
}}
>
<Text as="p" variant="body" sx={{ mx: 2 }}>
Congratulations! You successfully verified Notesnook's data encryption
claims.
</Text>
<Text as="p" variant="body" sx={{ mx: 2, mt: 2 }}>
Of course, this is just one part (a very crucial one) of proving that
you can trust Notesnook with your data. If you have any other
preservations, let us know by reaching out to us at{" "}
<Link href="mailto:support@streetwriters.co">
support@streetwriters.co
</Link>{" "}
or{" "}
<Link href="https://discord.gg/">joining our Discord community</Link>.
We'll do our best to alleviate all your worries.
</Text>
<Text as="p" variant="body" sx={{ mx: 2, mt: 2, fontWeight: "bold" }}>
What about open sourcing Notesnook?
</Text>
<Text as="p" variant="body" sx={{ mx: 2, my: 2 }}>
Open sourcing is another part of garnering our users' trust. We have{" "}
<Link href="https://notesnook.com/roadmap">plans</Link> to begin open
sourcing in May but open sourcing will not make this tool obsolete.
Verifying the integrity of encrypted data at any point in time is very
important even if the software is open source.
</Text>
</Accordion>
<Flex sx={{ alignSelf: "center", mt: 4 }}>
<Button
variant="secondary"
sx={{ mr: 2 }}
onClick={async () => {
if (!decryptedData) return;
await clipboard.writeText(decryptedData);
}}
>
Copy data as JSON
</Button>
<Button variant="primary" onClick={props.onRestartProcess}>
Start again
</Button>
</Flex>
</StepContainer>
);
}

View File

@@ -0,0 +1,38 @@
import { Button, Flex, Text } from "@theme-ui/components";
import { Accordion } from "./Accordion";
type ErrorsListProps = {
errors: string[];
};
export function ErrorsList(props: ErrorsListProps) {
return (
<Accordion
title={`${props.errors.length} errors occured`}
sx={{ bg: "errorBg", borderRadius: "default", mt: 2 }}
color="#E53935"
>
<Flex sx={{ flexDirection: "column", px: 2, pb: 2 }}>
<Text variant="body" sx={{ color: "error" }}>
{props.errors.map((error, index) => (
<>
{error}
<br />
</>
))}
</Text>
<Button
sx={{ bg: "error", color: "static", alignSelf: "start", mt: 2 }}
onClick={() =>
window.open(
"https://github.com/streetwriters/notesnook/issues/new",
"_blank"
)
}
>
Send us a bug report
</Button>
</Flex>
</Accordion>
);
}

Some files were not shown because too many files have changed in this diff Show More