diff --git a/components/ChecklistItem/App.js b/components/ChecklistItem/App.js index ec9abc2..7d1bd59 100644 --- a/components/ChecklistItem/App.js +++ b/components/ChecklistItem/App.js @@ -17,7 +17,7 @@ type Props = { }; export const AppRow = ({ app }: Props) => { - const sourcesKeys = Object.keys(app.sources); + const sourcesKeys = app.sources && Object.keys(app.sources); const renderSourceIcon = (key: string) => { const sourceUrl = app.sources[key]; @@ -72,10 +72,12 @@ export const AppRow = ({ app }: Props) => { return ( - + {app.image && } {app.name} - {sourcesKeys.map(renderSourceIcon)} + {sourcesKeys && ( + {sourcesKeys.map(renderSourceIcon)} + )} ); }; diff --git a/components/ChecklistItem/Heading.js b/components/ChecklistItem/Heading.js index 7e3add0..2e9936e 100644 --- a/components/ChecklistItem/Heading.js +++ b/components/ChecklistItem/Heading.js @@ -5,12 +5,11 @@ import type { ChecklistResource } from '../../types'; type Props = { resource: ChecklistResource, - isChecked: boolean, }; -export const Heading = ({ resource, isChecked }: Props) => ( +export const Heading = ({ resource }: Props) => ( {resource.title} - {resource.description} + ); diff --git a/components/ChecklistItem/Resources.js b/components/ChecklistItem/Resources.js index bd9f42b..d55f9cf 100644 --- a/components/ChecklistItem/Resources.js +++ b/components/ChecklistItem/Resources.js @@ -12,7 +12,7 @@ export const Resources = ({ resource }: Props) => { if (!resource.resources) return null; return ( - More Resources + Resources {resource.resources.map(r => ( ))} diff --git a/components/ChecklistItem/index.js b/components/ChecklistItem/index.js index a176e78..5c74a60 100644 --- a/components/ChecklistItem/index.js +++ b/components/ChecklistItem/index.js @@ -56,11 +56,20 @@ class ChecklistItem extends React.Component { - - - - - + + {resource.apps && ( + + + + + )} + + {resource.resources && ( + + + + + )} diff --git a/components/ChecklistItem/style.js b/components/ChecklistItem/style.js index 2dd16da..e576e96 100644 --- a/components/ChecklistItem/style.js +++ b/components/ChecklistItem/style.js @@ -1,5 +1,6 @@ // @flow import styled, { css } from 'styled-components'; +import Markdown from 'react-markdown'; import { theme } from '../theme'; import { Shadows, tint } from '../globals'; @@ -23,11 +24,19 @@ export const Title = styled.h3` color: ${theme.text.default}; `; -export const Description = styled.h4` +export const Description = styled(Markdown)` font-size: 16px; font-weight: 400; color: ${theme.text.secondary}; margin-top: 8px; + + p:first-of-type { + margin-top: 0; + } + + p { + margin-top: 12px; + } `; export const SectionHeading = styled.h5` @@ -181,8 +190,7 @@ export const AppSourcesListItem = styled.li` align-items: center; justify-content: center; color: ${theme.text.tertiary}; - margin-left: 4px; - padding: 4px 8px; + padding: 4px 10px; border-radius: 4px; min-width: 56px; transition: all 0.1s ease-in-out; diff --git a/config/appPermissions.js b/config/appPermissions.js new file mode 100644 index 0000000..60df71f --- /dev/null +++ b/config/appPermissions.js @@ -0,0 +1,33 @@ +export default { + id: 'appPermissions', + title: 'Review app permissions on your devices', + description: `You should review all applications that have access to your photos, camera, location, and microphone. Ensure that any app with permission is made by someone you trust. + `, + resources: [ + { + name: + 'iOS camera permissions allow rogue apps to surreptitiously photograph & video users', + url: 'https://9to5mac.com/2017/10/26/ios-camera-permissions-abuse/', + }, + { + name: 'How to manage app permissions on iOS', + url: + 'https://www.howtogeek.com/211623/how-to-manage-app-permissions-on-your-iphone-or-ipad/', + }, + { + name: 'How to manage app permissions on Android', + url: + 'https://www.howtogeek.com/230683/how-to-manage-app-permissions-on-android-6.0/', + }, + { + name: 'How to manage app permissions on macOS', + url: + 'https://www.idownloadblog.com/2018/08/16/howto-mac-camera-microphone-permission/', + }, + { + name: 'How to manage app permissions on Windows', + url: + 'https://www.intowindows.com/how-to-change-app-permissions-in-windows-10/', + }, + ], +}; diff --git a/config/browsers.js b/config/browsers.js new file mode 100644 index 0000000..9f5d6ac --- /dev/null +++ b/config/browsers.js @@ -0,0 +1,64 @@ +export default { + id: 'browsers', + title: 'Use a privacy-first web browser', + description: `You should use a web browser that protects you from tracking, fingerprinting, and unwanted advertisements. + `, + apps: [ + { + name: 'Brave', + image: '/static/img/brave.jpg', + url: 'https://brave.com/', + sources: { + windows: 'https://laptop-updates.brave.com/latest/winx64', + macos: 'https://laptop-updates.brave.com/latest/osx', + ios: + 'https://geo.itunes.apple.com/us/app/brave-web-browser/id1052879175?mt=8', + android: + 'https://play.google.com/store/apps/details?id=com.brave.browser&hl=en', + }, + }, + { + name: 'Firefox', + image: '/static/img/firefox.jpg', + url: 'https://www.mozilla.org/en-US/firefox/', + sources: { + windows: 'https://www.mozilla.org/en-US/firefox/', + macos: 'https://www.mozilla.org/en-US/firefox/', + ios: 'https://www.mozilla.org/en-US/firefox/mobile/', + android: 'https://www.mozilla.org/en-US/firefox/mobile/', + }, + }, + { + name: 'Tor', + image: '/static/img/tor.png', + url: 'https://www.torproject.org/', + sources: { + windows: + 'https://www.torproject.org/projects/torbrowser.html.en#windows', + macos: 'https://www.torproject.org/projects/torbrowser.html.en#macosx', + }, + }, + ], + resources: [ + { + name: 'Don’t expect privacy from Chrome', + url: + 'https://www.digitaltrends.com/computing/google-chrome-incognito-mode-tracking/', + }, + { + name: 'Google Chrome‘s users take a back seat to its bottom line', + url: + 'https://www.eff.org/deeplinks/2018/11/google-chromes-users-take-back-seat-its-bottom-line', + }, + { + name: 'What data of mine does Chrome send to Google?', + url: + 'https://lifehacker.com/5763452/what-data-does-chrome-send-to-google-about-me', + }, + { + name: 'Firefox multi-account containers', + url: + 'https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/', + }, + ], +}; diff --git a/config/creditFreeze.js b/config/creditFreeze.js new file mode 100644 index 0000000..28f559f --- /dev/null +++ b/config/creditFreeze.js @@ -0,0 +1,37 @@ +export default { + id: 'creditFreeze', + title: 'Freeze Your Credit', + description: `If you live in the United States, you should safely assume that hackers have access to your credit report, social security number, address history, and personal contact information. It is important that hackers with this knowledge are not able to impersonate you in order to open new lines of credit or make large purchases. + + \n\nYou should enable a freeze on all credit report checks at the three major credit bureaus. Any time you want to open your own line of credit or make a credit-backed purchase (for example, the iPhone Upgrade Program), you can add a time-blocked "credit thaw" that will allow legitimate credit checks to be processed. + + \n\n**Ensure that you enable a freeze at all three credit bureaus**`, + resources: [ + { + name: 'FTC Credit Freeze FAQs', + url: 'https://www.consumer.ftc.gov/articles/0497-credit-freeze-faqs', + }, + { + name: 'Freezing credit will now be free; here’s why you should go for it', + url: + 'https://www.nytimes.com/2018/09/14/your-money/credit-freeze-free.html', + }, + { + name: '7 things you should know before freezing your credit', + url: + 'https://www.experian.com/blogs/ask-experian/7-things-you-need-to-know-before-freezing-your-credit/', + }, + { + name: 'Experian Freeze', + url: 'https://www.experian.com/freeze/center.html', + }, + { + name: 'Equifax Freeze', + url: 'https://www.equifax.com/personal/credit-report-services/', + }, + { + name: 'TransUnion Freeze', + url: 'https://www.transunion.com/credit-freeze', + }, + ], +}; diff --git a/config/data.js b/config/data.js index afb4ce4..976b9b9 100644 --- a/config/data.js +++ b/config/data.js @@ -1,5 +1,31 @@ import passwordManager from './passwordManager'; +import strongDevicePasscode from './strongDevicePasscode'; +import twoFactor from './twoFactor'; +import simPin from './simPin'; +import creditFreeze from './creditFreeze'; +import encryptedHardware from './encryptedHardware'; +import dns from './dns'; +import vpn from './vpn'; +import browsers from './browsers'; +import searchEngine from './searchEngine'; +import email from './email'; +import appPermissions from './appPermissions'; +import socialMedia from './socialMedia'; +import phishing from './phishing'; export default { passwordManager, + strongDevicePasscode, + twoFactor, + simPin, + creditFreeze, + encryptedHardware, + dns, + vpn, + browsers, + searchEngine, + email, + appPermissions, + socialMedia, + phishing, }; diff --git a/config/dns.js b/config/dns.js new file mode 100644 index 0000000..57ef56c --- /dev/null +++ b/config/dns.js @@ -0,0 +1,40 @@ +export default { + id: 'dns', + title: 'Use 1.1.1.1 for DNS resolution', + description: `DNS (Domain Name Servers) are the internet's equivalent of a phone book. They translate a name like 'google.com' into an IP address. By default DNS is slow and insecure. + + \n\nCloudflare has released a privacy and performace-focused DNS tool that protects your internet traffif from prying eyes. It's faster than an average DNS service as well, making it faster to use the internet. + `, + apps: [ + { + name: '1.1.1.1', + image: '/static/img/1111.jpg', + url: 'https://www.cloudflare.com/learning/dns/what-is-1.1.1.1/', + sources: { + windows: 'https://1.1.1.1/', + macos: 'https://1.1.1.1/', + ios: + 'https://itunes.apple.com/app/1-1-1-1-faster-internet/id1423538627?mt=8', + android: + 'https://play.google.com/store/apps/details?id=com.cloudflare.onedotonedotonedotone', + }, + }, + ], + resources: [ + { + name: 'What is 1.1.1.1?', + url: 'https://www.cloudflare.com/learning/dns/what-is-1.1.1.1/', + }, + { + name: + 'Cloudflare launches 1.1.1.1 DNS service that will speed up your internet', + url: + 'https://www.theverge.com/2018/4/1/17185732/cloudflare-dns-service-1-1-1-1', + }, + { + name: 'Cloudflare’s privacy-focused 1.1.1.1 is available on phones', + url: + 'https://www.engadget.com/2018/11/11/cloudflare-1-1-1-1-privacy-service-on-phones/', + }, + ], +}; diff --git a/config/email.js b/config/email.js new file mode 100644 index 0000000..553645a --- /dev/null +++ b/config/email.js @@ -0,0 +1,49 @@ +export default { + id: 'email', + title: 'Use a privacy-first email provider', + description: `You should use an email provider that doesn’t read your email or gather data about your conversations to target you with ads. + `, + apps: [ + { + name: 'FastMail', + image: '/static/img/fastmail.jpg', + url: 'https://www.fastmail.com/', + sources: { + windows: 'https://www.fastmail.com/', + macos: 'https://www.fastmail.com/', + ios: + 'https://itunes.apple.com/us/app/fastmail-email-calendar/id931370077', + android: + 'https://play.google.com/store/apps/details?id=com.fastmail.app', + }, + }, + { + name: 'ProtonMail', + image: '/static/img/protonmail.jpg', + url: 'https://protonmail.com//', + sources: { + windows: 'https://protonmail.com//', + macos: 'https://protonmail.com//', + ios: + 'https://itunes.apple.com/app/protonmail-encrypted-email/id979659905', + android: + 'https://play.google.com/store/apps/details?id=ch.protonmail.android', + }, + }, + ], + resources: [ + { + name: 'Gmail vs FastMail', + url: 'https://hiverhq.com/blog/gmail-vs-fastmail-a-blunt-comparison/', + }, + { + name: 'Stop the paranoia: it doesn’t matter if Google reads our email', + url: 'https://www.maxmasnick.com/2012/02/12/gmail_paranoia/', + }, + { + name: 'How Google is destroying privacy and collecting your data', + url: + 'https://www.salon.com/2014/02/05/4_ways_google_is_destroying_privacy_and_collecting_your_data_partner/', + }, + ], +}; diff --git a/config/encryptedHardware.js b/config/encryptedHardware.js new file mode 100644 index 0000000..7447272 --- /dev/null +++ b/config/encryptedHardware.js @@ -0,0 +1,38 @@ +export default { + id: 'encryptedHardware', + title: 'Encrypt Your Phones and Computers', + description: `If your phone or computer is ever stolen, hackers can attempt to read the data directly off of the hard drive or storage mechanism. If your device is unencrypted, hackers will have access to all of your stored data. + + \n\nYou should enable encryption on every phone and computer you use.`, + resources: [ + { + name: 'Why you should encrypt your computer', + url: + 'https://www.aheliotech.com/tutorials/why-you-should-encrypt-your-computer/', + }, + { + name: + 'Why you should be encrypting your devices, and how to easily do it', + url: + 'https://gizmodo.com/why-you-should-be-encrypting-your-devices-and-how-to-ea-1798698901', + }, + { + name: 'Encrypt your iOS backups', + url: 'https://support.apple.com/en-us/HT205220', + }, + { + name: 'Encrypt your Android devices', + url: + 'https://www.howtogeek.com/141953/how-to-encrypt-your-android-phone-and-why-you-might-want-to/', + }, + { + name: 'Enable full-disk encryption on Windows PCs', + url: + 'https://www.howtogeek.com/234826/how-to-enable-full-disk-encryption-on-windows-10/', + }, + { + name: 'Encrypt your Mac', + url: 'https://support.apple.com/en-us/HT204837', + }, + ], +}; diff --git a/config/passwordManager.js b/config/passwordManager.js index 7eff762..26659c2 100644 --- a/config/passwordManager.js +++ b/config/passwordManager.js @@ -1,8 +1,10 @@ export default { id: 'passwordManager', title: 'Password Manager', - description: - 'A password manager helps you set unique passwords for each service you use. Having a unique password ensures that if one service you use is hacked, the leaked password won’t allow access to all of your accounts.', + description: `A password manager helps you set unique passwords for each service you use. Having a unique password ensures that if one service you use is hacked, the leaked password won’t allow access to all of your accounts. + + \n\nAt the very minimum you should have a unique password for high-value accounts like a Google account, email applications, an Apple ID, and financial accounts. + `, apps: [ { name: '1Password', diff --git a/config/phishing.js b/config/phishing.js new file mode 100644 index 0000000..274707a --- /dev/null +++ b/config/phishing.js @@ -0,0 +1,26 @@ +export default { + id: 'phishing', + title: 'Educate yourself about phishing attacks', + description: `asdf`, + resources: [ + { + name: 'Podcast: What kind of idiot gets phished?', + url: + 'https://www.gimletmedia.com/reply-all/97-what-kind-of-idiot-gets-phished', + }, + { + name: 'Common phishing attacks and how to protect against them', + url: + 'https://www.tripwire.com/state-of-security/security-awareness/6-common-phishing-attacks-and-how-to-protect-against-them/', + }, + { + name: 'Resisting phishing attacks with three golden rules', + url: 'https://www.wired.com/story/resist-phishing-attacks/', + }, + { + name: 'Google Password Alert Chrome extension', + url: + 'https://chrome.google.com/webstore/detail/password-alert/noondiphcddnnabmjcihcjfbhfklnnep?hl=en', + }, + ], +}; diff --git a/config/searchEngine.js b/config/searchEngine.js new file mode 100644 index 0000000..ace5d02 --- /dev/null +++ b/config/searchEngine.js @@ -0,0 +1,31 @@ +export default { + id: 'searchEngine', + title: 'Use a privacy-first search engine', + description: `You should use a search engine that protects you from tracking, fingerprinting, and unwanted advertisements. + `, + apps: [ + { + name: 'DuckDuckGo', + image: '/static/img/duckduckgo.jpg', + url: 'https://duckduckgo.com/', + sources: { + windows: 'https://duckduckgo.com', + macos: 'https://duckduckgo.com', + ios: + 'https://itunes.apple.com/us/app/duckduckgo-search-stories/id663592361?mt=8', + android: + 'https://play.google.com/store/apps/details?id=com.duckduckgo.mobile.android', + }, + }, + ], + resources: [ + { + name: 'DuckDuckGo Privacy', + url: 'https://duckduckgo.com/privacy', + }, + { + name: 'Everything Google knows about you', + url: 'https://myactivity.google.com/myactivity', + }, + ], +}; diff --git a/config/simPin.js b/config/simPin.js new file mode 100644 index 0000000..0f4c4e4 --- /dev/null +++ b/config/simPin.js @@ -0,0 +1,32 @@ +export default { + id: 'simPin', + title: 'Set up a carrier SIM PIN', + description: `SIM hijacking is a method where a hacker can socially engineer or bribe a mobile carrier to transfer your phone number to a SIM card the hacker owns. + + \n\nIf you use text messages as a two-factor authentication method, this gives hackers the ability to bypass 2FA and in most cases reset your passwords completely. + + \n\nYou should enable a carrier security PIN that is required before any SIM transfers can be processed.`, + resources: [ + { + name: 'SIM swap attacks and what you need to know', + url: 'https://www.dailydot.com/debug/sim-swap-attacks/', + }, + { + name: 'SIM hijacking explained', + url: + 'https://www.pandasecurity.com/mediacenter/security/sim-hijacking-explained/', + }, + { + name: 'Verizon FAQ', + url: 'https://www.verizonwireless.com/support/account-pin-faqs/', + }, + { + name: 'AT&T FAQ', + url: 'https://www.att.com/esupport/article.html#!/wireless/KM1049472', + }, + { + name: 'T-Mobile FAQ', + url: 'https://support.t-mobile.com/docs/DOC-37477', + }, + ], +}; diff --git a/config/socialMedia.js b/config/socialMedia.js new file mode 100644 index 0000000..cd85493 --- /dev/null +++ b/config/socialMedia.js @@ -0,0 +1,69 @@ +export default { + id: 'socialMedia', + title: 'Review your social media privacy settings', + description: `Over the years social media companies are able to gather staggering amounts of data about you, your interests, who you talk to, where you go, what you buy, and so much more. + + \n\nIf you‘re not ready to give up social media quite yet, you should take time to review your security and privacy settings. Visualizing the amount of information that social media companies may be enough to curb that unhealthy newsfeed obsession.`, + resources: [ + { + name: 'Facebook privacy settings', + url: 'https://www.facebook.com/settings?tab=privacy', + }, + { + name: 'Facebook ad personalization settings', + url: + 'https://www.facebook.com/ads/preferences/?entry_product=ad_settings_screen', + }, + { + name: 'Facebook location history', + url: 'https://www.facebook.com/settings?tab=location', + }, + { + name: 'Facebook face recognition', + url: 'https://www.facebook.com/settings?tab=facerec', + }, + { + name: 'Your Facebook data', + url: 'https://www.facebook.com/settings?tab=your_facebook_information', + }, + { + name: 'Facebook security settings', + url: 'https://www.facebook.com/settings?tab=security', + }, + { + name: 'Twitter personalization settings', + url: 'https://twitter.com/settings/account/personalization', + }, + { + name: 'Twitter privacy and safety settings', + url: 'https://twitter.com/settings/safety', + }, + { + name: 'Google activity', + url: 'https://myactivity.google.com/myactivity', + }, + { + name: 'Google location history', + url: 'https://www.google.com/maps/timeline?authuser=0&pb', + }, + { + name: 'Google ad personalization settings', + url: 'https://adssettings.google.com/authenticated', + }, + { + name: 'Google purchase history', + url: + 'https://myaccount.google.com/purchases?utm_source=google-account&utm_medium=web', + }, + { + name: 'Google subscription history', + url: + 'https://myaccount.google.com/subscriptions?utm_source=google-account&utm_medium=web', + }, + { + name: 'Google reservation history', + url: + 'https://myaccount.google.com/reservations?utm_source=google-account&utm_medium=web&continue=https%3A%2F%2Fmyaccount.google.com%2Fpayments-and-subscriptions', + }, + ], +}; diff --git a/config/strongDevicePasscode.js b/config/strongDevicePasscode.js new file mode 100644 index 0000000..2a35646 --- /dev/null +++ b/config/strongDevicePasscode.js @@ -0,0 +1,19 @@ +export default { + id: 'strongDevicePasscode', + title: 'Create a strong device passcode', + description: `A four-digit passcode for your phone or other devices is no longer an acceptable security practice. You should be using a 6+ digit passcode at the very minimum, and for extra security use a 6+ character passcode containing both numbers and letters.`, + resources: [ + { + name: 'How long it takes to break a passcode', + url: 'http://fortune.com/2016/03/18/apple-fbi-iphone-passcode-hack/', + }, + { + name: 'Changing your iOS passcode', + url: 'https://support.apple.com/en-us/HT204060', + }, + { + name: 'Setting up an Android passcode', + url: 'https://phandroid.com/2014/03/20/android-101-lock-screen/', + }, + ], +}; diff --git a/config/twoFactor.js b/config/twoFactor.js new file mode 100644 index 0000000..83a9e8e --- /dev/null +++ b/config/twoFactor.js @@ -0,0 +1,82 @@ +export default { + id: 'twoFactor', + title: 'Two-Factor Authentication (2FA)', + description: `Two-factor authentication is an extra layer of security on top of passwords. It ensures that someone logging into an account is who they say they are by requiring an extra piece of information besides the account password. + + \n\nThis extra information is usually either something you know, something you have, or something you are - for example, a biometric signal like FaceID. + + \n\n**You should not use your phone number as a two-factor method.** + + \n\n2FA should be installed on accounts that can lock you out of other accounts: e.g. a Google account, email applications, an Apple ID, and financial accounts. + `, + apps: [ + { + name: '1Password', + image: '/static/img/1password.jpg', + url: 'https://1password.com/', + sources: { + windows: 'https://1password.com/downloads/windows/', + macos: 'https://1password.com/downloads/mac/', + ios: 'https://1password.com/downloads/ios/', + android: 'https://1password.com/downloads/android/', + }, + }, + { + name: 'LastPass', + image: '/static/img/lastpass.jpg', + url: 'https://www.lastpass.com/', + sources: { + windows: + 'https://download.cloud.lastpass.com/windows_installer/lastpass.exe', + macos: + 'https://itunes.apple.com/us/app/lastpass/id926036361?ls=1&mt=12', + ios: + 'https://itunes.apple.com/us/app/lastpass-password-manager/id324613447', + android: 'https://lastpass.com/android_market.php', + }, + }, + { + name: 'Authy', + image: '/static/img/authy.jpg', + url: 'https://authy.com/', + sources: { + windows: 'https://authy.com/download/', + macos: 'https://authy.com/download/', + ios: 'https://itunes.apple.com/us/app/authy/id494168017', + android: + 'https://play.google.com/store/apps/details?id=com.authy.authy', + }, + }, + { + name: 'Google Authenticator', + image: '/static/img/google-authenticator.jpg', + url: 'https://www.google.com/landing/2step/', + sources: { + ios: 'https://itunes.apple.com/us/app/google-authenticator/id388497605', + android: + 'https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en_us', + }, + }, + { + name: 'YubiKey', + image: '/static/img/yubico.jpg', + url: 'https://www.yubico.com/', + }, + ], + resources: [ + { + name: 'What is two-factor authentication?', + url: 'https://authy.com/what-is-2fa/', + }, + { + name: 'Two-factor authentication: a little goes a long way', + url: + 'https://securityintelligence.com/two-factor-authentication-a-little-goes-a-long-way/', + }, + { + name: 'So hey, you should stop using texts for two-factor authentication', + url: + 'https://www.wired.com/2016/06/hey-stop-using-texts-two-factor-authentication/', + }, + ], +}; diff --git a/config/vpn.js b/config/vpn.js new file mode 100644 index 0000000..d3a36a5 --- /dev/null +++ b/config/vpn.js @@ -0,0 +1,61 @@ +export default { + id: 'vpn', + title: 'Use a VPN', + description: `A VPN, or virtual private network, is a useful tool to secure an internet connection. It guarantees that that data you are sending and receiving is encrypted, preventing people from snooping on your traffic. + + \n\nYou should use a VPN provider that you trust to not harvest and re-sell your data. The best VPNs often charge a monthly subscription - this is a good thing, because it means their business model is not reliant upon aggregating and reselling data. + `, + apps: [ + { + name: 'Encrypt.me', + image: '/static/img/encrypt-me.jpg', + url: 'https://encrypt.me/', + sources: { + windows: 'https://app.encrypt.me/transition/download/windows/latest/', + macos: 'https://app.encrypt.me/transition/download/osx/latest/', + ios: 'https://itunes.apple.com/us/app/encrypt-me/id473835722?ls=1&mt=8', + android: + 'https://play.google.com/store/apps/details?id=com.stackpath.cloak', + }, + }, + { + name: 'IVPN', + image: '/static/img/ivpn.jpg', + url: 'https://www.ivpn.net/', + sources: { + windows: 'https://www.ivpn.net/apps-windows', + macos: 'https://www.ivpn.net/apps-macos', + ios: 'https://www.ivpn.net/apps-ios', + android: 'https://www.ivpn.net/apps-android', + }, + }, + { + name: 'ExpressVPN', + image: '/static/img/expressvpn.jpg', + url: 'https://www.expressvpn.com/', + sources: { + windows: 'https://www.expressvpn.com/vpn-software/vpn-windows', + macos: 'https://www.expressvpn.com/vpn-software/vpn-mac', + ios: 'https://www.expressvpn.com/vpn-software/vpn-ios', + android: 'https://www.expressvpn.com/vpn-software/vpn-android', + }, + }, + ], + resources: [ + { + name: 'Why you should be using a VPN', + url: + 'https://lifehacker.com/5940565/why-you-should-start-using-a-vpn-and-how-to-choose-the-best-one-for-your-needs', + }, + { + name: 'What is a VPN and why you need one', + url: + 'https://www.theverge.com/2018/4/1/17185732/cloudflare-dns-service-1-1-1-1', + }, + { + name: 'Why you should use a VPN on a public Wi-Fi network', + url: + 'https://www.macworld.com/article/3322951/security/why-you-should-use-a-vpn-on-a-public-wi-fi-network.html', + }, + ], +}; diff --git a/package-lock.json b/package-lock.json index ce9f9ea..8e923d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2086,6 +2086,11 @@ "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", "dev": true }, + "bail": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -2588,6 +2593,21 @@ "supports-color": "^5.3.0" } }, + "character-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" + }, + "character-entities-legacy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" + }, + "character-reference-invalid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -2786,6 +2806,11 @@ "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", "dev": true }, + "collapse-white-space": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -3398,11 +3423,49 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" + } + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -3510,6 +3573,11 @@ "tapable": "^1.0.0" } }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -4165,8 +4233,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -5395,11 +5462,55 @@ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" }, + "html-to-react": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.3.4.tgz", + "integrity": "sha512-/tWDdb/8Koi/QEP5YUY1653PcDpBnnMblXRhotnTuhFDjI1Fc6Wzox5d4sw73Xk5rM2OdM5np4AYjT/US/Wj7Q==", + "requires": { + "domhandler": "^2.4.2", + "escape-string-regexp": "^1.0.5", + "htmlparser2": "^3.10.0", + "lodash.camelcase": "^4.3.0", + "ramda": "^0.26" + }, + "dependencies": { + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==" + } + } + }, "htmlescape": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" }, + "htmlparser2": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz", + "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==", + "requires": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -5605,6 +5716,20 @@ } } }, + "is-alphabetical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==" + }, + "is-alphanumerical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5667,6 +5792,11 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, + "is-decimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -5737,6 +5867,11 @@ "is-extglob": "^2.1.1" } }, + "is-hexadecimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" + }, "is-installed-globally": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", @@ -5809,6 +5944,11 @@ "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5874,11 +6014,21 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-whitespace-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, + "is-word-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", + "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6645,6 +6795,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -6774,6 +6929,11 @@ "object-visit": "^1.0.0" } }, + "markdown-escapes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==" + }, "matcher": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", @@ -6810,6 +6970,14 @@ "safe-buffer": "^5.1.2" } }, + "mdast-add-list-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz", + "integrity": "sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==", + "requires": { + "unist-util-visit-parents": "1.1.2" + } + }, "memoize-one": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz", @@ -7574,6 +7742,19 @@ "pbkdf2": "^3.0.3" } }, + "parse-entities": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.0.tgz", + "integrity": "sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g==", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -8249,6 +8430,20 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.7.0.tgz", "integrity": "sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g==" }, + "react-markdown": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-4.0.6.tgz", + "integrity": "sha512-E1d/q+OBk5eumId42oYqVrJRB/+whrZdk+YHqUBCCNeWxqeV+Qzt+yLTsft9+4HRDj89Od7eAbUPQBYq8ZwShQ==", + "requires": { + "html-to-react": "^1.3.4", + "mdast-add-list-metadata": "1.0.1", + "prop-types": "^15.6.1", + "remark-parse": "^5.0.0", + "unified": "^6.1.5", + "unist-util-visit": "^1.3.0", + "xtend": "^4.0.1" + } + }, "read-only-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", @@ -8441,6 +8636,28 @@ } } }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -8465,6 +8682,11 @@ "is-finite": "^1.0.0" } }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", @@ -9079,6 +9301,11 @@ "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", "dev": true }, + "state-toggle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -9576,11 +9803,26 @@ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, + "trim-trailing-lines": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==" + }, + "trough": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==" + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -9778,6 +10020,15 @@ "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-3.0.0.tgz", "integrity": "sha1-jR4FE6Ts0OX/LUGmund3Gq6LZII=" }, + "unherit": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", + "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + } + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -9802,6 +10053,19 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==" }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -9850,6 +10114,47 @@ "imurmurhash": "^0.1.4" } }, + "unist-util-is": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", + "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==" + }, + "unist-util-remove-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", + "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + }, + "unist-util-visit": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.0.tgz", + "integrity": "sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + }, + "dependencies": { + "unist-util-visit-parents": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz", + "integrity": "sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA==", + "requires": { + "unist-util-is": "^2.1.2" + } + } + } + }, + "unist-util-visit-parents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz", + "integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -9978,6 +10283,30 @@ "extsprintf": "^1.2.0" } }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "vfile-location": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.4.tgz", + "integrity": "sha512-KRL5uXQPoUKu+NGvQVL4XLORw45W62v4U4gxJ3vRlDfI9QsT4ZN1PNXn/zQpKUulqGDpYuT0XDfp5q9O87/y/w==" + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -10404,6 +10733,11 @@ "moment": "^2.22.1" } }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index ae5f4e8..57f8f5c 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "react": "^16.8.0-alpha.0", "react-clipboard.js": "^2.0.2", "react-dom": "^16.8.0-alpha.0", + "react-markdown": "^4.0.6", "styled-components": "^4.1.3", "throttle-debounce": "^2.0.1" }, diff --git a/static/img/1111.jpg b/static/img/1111.jpg new file mode 100644 index 0000000..4531d74 Binary files /dev/null and b/static/img/1111.jpg differ diff --git a/static/img/authy.jpg b/static/img/authy.jpg new file mode 100644 index 0000000..1037bcd Binary files /dev/null and b/static/img/authy.jpg differ diff --git a/static/img/brave.jpg b/static/img/brave.jpg new file mode 100644 index 0000000..48f397f Binary files /dev/null and b/static/img/brave.jpg differ diff --git a/static/img/duckduckgo.jpg b/static/img/duckduckgo.jpg new file mode 100644 index 0000000..b0d2665 Binary files /dev/null and b/static/img/duckduckgo.jpg differ diff --git a/static/img/encrypt-me.jpg b/static/img/encrypt-me.jpg new file mode 100644 index 0000000..6accbbf Binary files /dev/null and b/static/img/encrypt-me.jpg differ diff --git a/static/img/expressvpn.jpg b/static/img/expressvpn.jpg new file mode 100644 index 0000000..5a66c5a Binary files /dev/null and b/static/img/expressvpn.jpg differ diff --git a/static/img/fastmail.jpg b/static/img/fastmail.jpg new file mode 100644 index 0000000..85eb144 Binary files /dev/null and b/static/img/fastmail.jpg differ diff --git a/static/img/firefox.jpg b/static/img/firefox.jpg new file mode 100644 index 0000000..93309ae Binary files /dev/null and b/static/img/firefox.jpg differ diff --git a/static/img/google-authenticator.jpg b/static/img/google-authenticator.jpg new file mode 100644 index 0000000..687db19 Binary files /dev/null and b/static/img/google-authenticator.jpg differ diff --git a/static/img/ivpn.jpg b/static/img/ivpn.jpg new file mode 100644 index 0000000..4c449b2 Binary files /dev/null and b/static/img/ivpn.jpg differ diff --git a/static/img/protonmail.jpg b/static/img/protonmail.jpg new file mode 100644 index 0000000..6f81c4c Binary files /dev/null and b/static/img/protonmail.jpg differ diff --git a/static/img/tor.png b/static/img/tor.png new file mode 100644 index 0000000..7ce938b Binary files /dev/null and b/static/img/tor.png differ diff --git a/static/img/yubico.jpg b/static/img/yubico.jpg new file mode 100644 index 0000000..753938c Binary files /dev/null and b/static/img/yubico.jpg differ