1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-29 22:37:44 +02:00

Compare commits

...

65 Commits

Author SHA1 Message Date
377b8e91a6 chore(release): 1.3.5 [skip ci] 2021-09-01 22:17:55 +00:00
fce29c9d4a build(deps): update latest 2021-09-02 00:13:20 +02:00
c198f47aa9 build(deps-dev): eslint-config-standard-with-typescript to 21.0.1 (#195) 2021-09-01 16:38:44 +02:00
8e051332cd build(deps-dev): bump @typescript-eslint/eslint-plugin to 4.30.0 (#197) 2021-09-01 16:37:39 +02:00
9f3436e1df build(deps-dev): bump tailwindcss from 2.2.8 to 2.2.9 (#196) 2021-09-01 16:37:17 +02:00
2f2373e62f build(deps-dev): bump cypress from 8.3.0 to 8.3.1 (#187) 2021-09-01 16:36:12 +02:00
c6b455dd10 build(deps-dev): bump eslint-plugin-prettier from 3.4.1 to 4.0.0 (#189) 2021-09-01 16:35:35 +02:00
4e089b41f2 build(deps-dev): bump @types/node from 16.7.2 to 16.7.10 (#193) 2021-09-01 16:35:19 +02:00
6c102b1b35 build(deps-dev): bump eslint-config-next from 11.1.0 to 11.1.2 (#194) 2021-09-01 16:35:03 +02:00
52b10944b7 build(deps): bump next from 11.1.0 to 11.1.2 (#192) 2021-09-01 16:34:50 +02:00
db36eb3e7a build(deps-dev): bump jest from 27.0.6 to 27.1.0 (#185) 2021-08-27 12:45:18 +02:00
c739ad951d build(deps-dev): bump babel-jest from 27.0.6 to 27.1.0 (#184) 2021-08-27 12:45:07 +02:00
2802ff029f build(deps-dev): bump tailwindcss from 2.2.7 to 2.2.8 (#182) 2021-08-27 12:43:05 +02:00
1a7457b44b build(deps-dev): bump @types/node from 16.7.1 to 16.7.2 (#183) 2021-08-27 12:41:56 +02:00
ff210f879d build(deps-dev): bump semantic-release from 17.4.6 to 17.4.7 (#178) 2021-08-27 12:41:43 +02:00
607454b360 build(deps-dev): bump eslint-plugin-import from 2.24.1 to 2.24.2 (#176) 2021-08-27 12:41:29 +02:00
d1522fbf44 build(deps): bump node from 16.7.0 to 16.8.0 (#179) 2021-08-27 12:41:06 +02:00
b82eae7499 build(deps-dev): bump autoprefixer from 10.3.2 to 10.3.3 (#181) 2021-08-27 12:40:52 +02:00
73527ce8fe build(deps-dev): bump husky from 7.0.1 to 7.0.2 (#177) 2021-08-27 12:40:30 +02:00
0cd885ee70 build(deps-dev): bump typescript from 4.3.5 to 4.4.2 (#180) 2021-08-27 12:40:16 +02:00
2cb2df975f build(deps-dev): bump @typescript-eslint/eslint-plugin to 4.29.3 (#175) 2021-08-24 02:30:24 +02:00
37f5843adb build(deps-dev): bump semantic-release from 17.4.5 to 17.4.6 (#174) 2021-08-24 02:30:06 +02:00
d794d38f14 test(e2e): visible instead of exist 2021-08-23 19:48:15 +02:00
fc5ba28b8a perf: remove unnecessary fonts weight 2021-08-23 19:41:39 +02:00
b5945150b8 fix: remove Hyper Terminal from tools used 2021-08-23 19:25:17 +02:00
aa12d626d2 perf: uses-responsive-images 2021-08-23 19:17:30 +02:00
6ac4782b7d build(deps-dev): bump @types/node from 16.6.2 to 16.7.1 (#171) 2021-08-23 12:00:52 +02:00
0aa998d593 build(deps-dev): bump eslint-plugin-prettier from 3.4.0 to 3.4.1 (#172) 2021-08-23 12:00:39 +02:00
56f975e53c build(deps-dev): bump autoprefixer from 10.3.1 to 10.3.2 (#173) 2021-08-23 12:00:26 +02:00
5a16d24ea1 build(deps-dev): bump eslint-plugin-import from 2.24.0 to 2.24.1 (#170) 2021-08-20 10:37:53 +02:00
52267005ec build(deps-dev): bump @types/react from 17.0.18 to 17.0.19 (#169) 2021-08-20 10:37:38 +02:00
99b9b12ac9 build(deps-dev): bump @types/node from 16.6.1 to 16.6.2 (#168) 2021-08-19 10:56:35 +02:00
2cae77481f build(deps): bump node from 16.6.2 to 16.7.0 (#167) 2021-08-19 10:55:46 +02:00
e98b47a459 build(deps): bump sharp from 0.28.3 to 0.29.0 (#166) 2021-08-18 11:26:24 +02:00
4cc87758c1 build(deps): bump next-pwa from 5.2.24 to 5.3.1 (#164) 2021-08-17 20:49:12 +02:00
1bb0f31223 build(deps-dev): bump @typescript-eslint/eslint-plugin (#165) 2021-08-17 20:48:56 +02:00
af2dd0bd60 build(deps-dev): bump cypress from 8.2.0 to 8.3.0 (#163) 2021-08-17 20:48:39 +02:00
63d7485c8d build(deps): bump next-pwa from 5.3.0 to 5.2.24 2021-08-16 15:38:56 +02:00
74fde0ea40 build(deps): update latest version 2021-08-16 15:31:35 +02:00
0d2b318818 build(deps): bump node from 16.6.1 to 16.6.2 (#155) 2021-08-13 15:50:10 +02:00
266b3f8589 test: add cypress e2e (#159) 2021-08-13 15:48:29 +02:00
f7d304ca80 build(deps): bump read-pkg from 5.2.0 to 6.0.0 (#136) 2021-08-12 11:03:37 +02:00
63017953d7 chore(release): 1.3.4 [skip ci] 2021-08-11 23:29:15 +00:00
20600eb976 build(deps): bump crazy-max/ghaction-import-gpg from 3.1.0 to 3.2.0 (#154) 2021-08-12 01:21:54 +02:00
7f920b77aa build(deps): bump actions/setup-node from 2.3.1 to 2.4.0 (#152) 2021-08-12 01:21:40 +02:00
4f5dfc63ea perf: reduce build size + add next-secure-headers 2021-08-12 01:19:11 +02:00
712805df93 build(deps): bump actions/setup-node from 2.3.0 to 2.3.1 (#144) 2021-08-04 10:39:56 +02:00
cd68f597c9 build(deps-dev): bump @typescript-eslint/eslint-plugin (#143) 2021-08-04 10:39:35 +02:00
7ec3fe8ced build(deps-dev): bump eslint from 7.31.0 to 7.32.0 (#141) 2021-08-04 10:39:12 +02:00
90d22b2c7f build(deps-dev): bump @types/node from 16.4.7 to 16.4.10 (#142) 2021-08-04 10:38:47 +02:00
4b06fd0522 build(deps): bump node from 16.5.0 to 16.6.1 (#145) 2021-08-04 10:38:28 +02:00
b4427f36c2 build(deps): bump @fortawesome/react-fontawesome to 0.1.15 (#146) 2021-08-04 10:38:07 +02:00
b758c64e02 build(deps-dev): bump @types/node from 16.4.6 to 16.4.7 (#139) 2021-07-30 07:21:41 +02:00
04469b83ea build(deps-dev): bump @types/node from 16.4.4 to 16.4.6 (#138) 2021-07-29 08:16:05 +02:00
36d54666a0 build(deps-dev): bump @types/node from 16.4.3 to 16.4.4 (#137) 2021-07-28 08:17:45 +02:00
a34cefec6e chore(release): set correctly env [skip ci] 2021-07-27 21:34:08 +02:00
5c343395df chore(release): 1.3.3 [skip ci] 2021-07-27 19:06:15 +00:00
028815a7b6 fix: sign release commit and backmerge to develop 2021-07-27 21:01:33 +02:00
a2ad591d6d chore(release): 1.3.2 [skip ci] 2021-07-27 18:04:31 +00:00
7087911756 ci(release): add GH_TOKEN 2021-07-27 20:01:21 +02:00
35b1c4169f ci(release): persist-credentials: false 2021-07-27 19:52:24 +02:00
4c351b8179 chore: update message of release commit 2021-07-27 19:35:08 +02:00
701dccc018 fix: include version in release 2021-07-27 19:26:08 +02:00
5133765f94 chore: add Vercel CLI 2021-07-27 19:00:21 +02:00
3b208c6614 fix: disable hover:underline on link of Respository (open source) 2021-07-27 18:31:41 +02:00
46 changed files with 8955 additions and 5020 deletions

View File

@ -1,3 +1,14 @@
{
"presets": ["next/babel"]
"presets": [
[
"next/babel",
{
"preset-env": {
"targets": {
"browsers": ">1%, not ie 11, not dead"
}
}
}
]
]
}

View File

@ -9,3 +9,4 @@ tmp
temp
.DS_Store
.lighthouseci
.vercel

View File

@ -4,3 +4,4 @@ node_modules
next-env.d.ts
**/workbox-*.js
**/sw.js
.vercel

View File

@ -5,7 +5,7 @@
"next/core-web-vitals",
"prettier"
],
"plugins": ["prettier"],
"plugins": ["unicorn", "prettier"],
"parserOptions": {
"project": "./tsconfig.json"
},
@ -15,6 +15,17 @@
"jest": true
},
"rules": {
"prettier/prettier": "error"
"prettier/prettier": "error",
"unicorn/prefer-node-protocol": "error",
"unicorn/prevent-abbreviations": [
"error",
{
"replacements": {
"props": {
"properties": false
}
}
}
]
}
}

View File

@ -32,7 +32,7 @@ jobs:
- uses: 'actions/checkout@v2.3.4'
- name: 'Use Node.js'
uses: 'actions/setup-node@v2.3.0'
uses: 'actions/setup-node@v2.4.0'
with:
node-version: '16.x'
cache: 'npm'
@ -46,13 +46,30 @@ jobs:
- run: 'npm run lint:markdown'
- run: 'npm run lint:typescript'
build:
test-unit:
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@v2.3.4'
- name: 'Use Node.js'
uses: 'actions/setup-node@v2.3.0'
uses: 'actions/setup-node@v2.4.0'
with:
node-version: '16.x'
cache: 'npm'
- name: 'Install'
run: 'npm install'
- name: 'Unit Test'
run: 'npm run test:unit'
test-lighthouse:
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@v2.3.4'
- name: 'Use Node.js'
uses: 'actions/setup-node@v2.4.0'
with:
node-version: '16.x'
cache: 'npm'
@ -64,17 +81,17 @@ jobs:
run: 'npm run build'
- name: 'Lighthouse'
run: 'npm run lighthouse'
run: 'npm run test:lighthouse'
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
test:
test-e2e:
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@v2.3.4'
- name: 'Use Node.js'
uses: 'actions/setup-node@v2.3.0'
uses: 'actions/setup-node@v2.4.0'
with:
node-version: '16.x'
cache: 'npm'
@ -82,18 +99,31 @@ jobs:
- name: 'Install'
run: 'npm install'
- name: 'Test'
run: 'npm run test'
- name: 'Build'
run: 'npm run build'
- name: 'End To End (e2e) Test'
run: 'npm run test:e2e'
release:
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
needs: [analyze, lint, build, test]
needs: [analyze, lint, test-unit, test-e2e, test-lighthouse]
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@v2.3.4'
with:
fetch-depth: 0
persist-credentials: false
- name: 'Import GPG key'
uses: 'crazy-max/ghaction-import-gpg@v3.2.0'
with:
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
git-user-signingkey: true
git-commit-gpgsign: true
- name: 'Use Node.js'
uses: 'actions/setup-node@v2.3.0'
uses: 'actions/setup-node@v2.4.0'
with:
node-version: '16.x'
cache: 'npm'
@ -104,4 +134,13 @@ jobs:
- name: 'Release'
run: 'npm run release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GIT_COMMITTER_NAME: ${{ secrets.GIT_NAME }}
GIT_COMMITTER_EMAIL: ${{ secrets.GIT_EMAIL }}
- name: 'Deploy to Vercel'
run: 'npm run deploy -- --token="${VERCEL_TOKEN}" --prod'
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}

4
.gitignore vendored
View File

@ -14,6 +14,9 @@ dist
# testing
coverage
cypress/screenshots
cypress/videos
cypress/downloads
# PWA
**/workbox-*.js
@ -45,3 +48,4 @@ npm-debug.log*
# misc
.DS_Store
.lighthouseci
.vercel

View File

@ -10,9 +10,7 @@
"assert": {
"preset": "lighthouse:recommended",
"assertions": {
"csp-xss": "warning",
"non-composited-animations": "warning",
"uses-responsive-images": "warning"
"csp-xss": "warning"
}
},
"upload": {

View File

@ -6,3 +6,4 @@ package.json
package-lock.json
**/workbox-*.js
**/sw.js
.vercel

View File

@ -13,7 +13,25 @@
"preset": "conventionalcommits"
}
],
[
"@semantic-release/npm",
"@semantic-release/github"
{
"npmPublish": false
}
],
[
"@semantic-release/git",
{
"assets": ["package.json", "package-lock.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]"
}
],
"@semantic-release/github",
[
"@saithodev/semantic-release-backmerge",
{
"backmergeStrategy": "merge"
}
]
]
}

41
.vscode/settings.json vendored
View File

@ -1,9 +1,48 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.configPath": ".prettierrc.json",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"[css]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[sass]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View File

@ -1,15 +1,15 @@
FROM node:16.5.0 AS dependencies
FROM node:16.8.0 AS dependencies
WORKDIR /usr/src/app
COPY ./package*.json ./
RUN npm clean-install
FROM node:16.5.0 AS builder
FROM node:16.8.0 AS builder
WORKDIR /usr/src/app
COPY ./ ./
COPY --from=dependencies /usr/src/app/node_modules ./node_modules
RUN npm run build
FROM node:16.5.0 AS runner
FROM node:16.8.0 AS runner
WORKDIR /usr/src/app
ENV NODE_ENV=production
COPY --from=builder /usr/src/app/next.config.js ./next.config.js

View File

@ -23,7 +23,7 @@
```json
{
"name": "Divlo",
"pronouns": "He' | 'Him",
"pronouns": "He/Him",
"birthDate": "31/03/2003",
"nationality": "Alsace, France",
"interests": [
@ -35,7 +35,7 @@
"programmingLanguages": ["JavaScript", "TypeScript", "Python"],
"frontEnd": ["HTML", "CSS", "Tailwind CSS", "React.js (+ Next.js)"],
"backEnd": ["Node.js", "Fastify", "Prisma", "PostgreSQL", "MySQL"],
"tools": ["Ubuntu", "Hyper Terminal", "VSCode", "Git", "Docker"]
"tools": ["Ubuntu", "Visual Studio Code", "Git", "Docker"]
}
}
```

View File

@ -1,10 +0,0 @@
import { render } from '@testing-library/react'
import Error404 from 'pages/404'
describe('GET /404', () => {
it('should render', async () => {
const { getByText } = render(<Error404 />)
expect(getByText('404')).toBeInTheDocument()
})
})

View File

@ -1,10 +0,0 @@
import { render } from '@testing-library/react'
import Error500 from 'pages/500'
describe('GET /500', () => {
it('should render', async () => {
const { getByText } = render(<Error500 />)
expect(getByText('500')).toBeInTheDocument()
})
})

View File

@ -14,7 +14,12 @@ export const ErrorPage: React.FC<ErrorPageProps> = (props) => {
<>
<h1 className='my-6 font-semibold text-4xl'>
{t('errors:error')}{' '}
<span className='text-yellow dark:text-yellow-dark'>{statusCode}</span>
<span
className='text-yellow dark:text-yellow-dark'
data-cy='status-code'
>
{statusCode}
</span>
</h1>
<p className='text-center text-lg'>
{message}{' '}

View File

@ -11,10 +11,7 @@ export const Footer: React.FC<FooterProps> = (props) => {
const { version } = props
const versionLink = useMemo(() => {
if (version !== '0.0.0-development') {
return `https://github.com/Divlo/Divlo/releases/tag/v${version}`
}
return 'https://github.com/Divlo/Divlo/tree/develop'
}, [version])
return (

View File

@ -15,7 +15,9 @@ export const LanguageFlag: React.FC<LanguageFlagProps> = (props) => {
src={`/images/languages/${language}.svg`}
alt={language}
/>
<p className='mx-2 text-base'>{language.toUpperCase()}</p>
<p data-cy='language-flag-text' className='mx-2 text-base'>
{language.toUpperCase()}
</p>
</>
)
}

View File

@ -1,6 +1,7 @@
import { useCallback, useEffect, useState } from 'react'
import useTranslation from 'next-translate/useTranslation'
import setLanguage from 'next-translate/setLanguage'
import classNames from 'classnames'
import { Arrow } from './Arrow'
import { LanguageFlag } from './LanguageFlag'
@ -33,12 +34,22 @@ export const Language: React.FC = () => {
return (
<div className='flex flex-col justify-center items-center cursor-pointer'>
<div className='flex items-center mr-5' onClick={handleHiddenMenu}>
<div
data-cy='language-click'
className='flex items-center mr-5'
onClick={handleHiddenMenu}
>
<LanguageFlag language={currentLanguage} />
<Arrow />
</div>
{!hiddenMenu && (
<ul className='flex flex-col justify-center items-center absolute p-0 top-14 z-10 w-24 mt-3 mr-4 rounded-lg list-none shadow-light dark:shadow-dark bg-white dark:bg-black'>
<ul
data-cy='languages-list'
className={classNames(
'flex flex-col justify-center items-center absolute p-0 top-14 z-10 w-24 mt-3 mr-4 rounded-lg list-none shadow-light dark:shadow-dark bg-white dark:bg-black',
{ hidden: hiddenMenu }
)}
>
{i18n.locales.map((language, index) => {
if (language === currentLanguage) {
return null
@ -54,7 +65,6 @@ export const Language: React.FC = () => {
)
})}
</ul>
)}
</div>
)
}

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { useTheme } from 'next-themes'
export const SwitchTheme: React.FC = () => {
@ -13,23 +13,29 @@ export const SwitchTheme: React.FC = () => {
return null
}
const handleClick = (): void => {
setTheme(theme === 'dark' ? 'light' : 'dark')
}
return (
<>
<div
className='toggle-button'
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
data-cy='switch-theme-click'
onClick={handleClick}
>
<div className='toggle-theme-button'>
<div className='toggle-track'>
<div className='toggle-track-check'>
<div data-cy='switch-theme-dark' className='toggle-track-check'>
<span className='toggle_Dark'>🌜</span>
</div>
<div className='toggle-track-x'>
<div data-cy='switch-theme-light' className='toggle-track-x'>
<span className='toggle_Light'>🌞</span>
</div>
</div>
<div className='toggle-thumb' />
<input
data-cy='switch-theme-input'
type='checkbox'
aria-label='Dark mode toggle'
className='toggle-screenreader-only'

View File

@ -11,7 +11,7 @@ export const InterestParagraph: React.FC<InterestParagraphProps> = (props) => {
return (
<>
<p className='text-center my-6 text-gray dark:text-gray-dark'>
<strong className='text-yellow font-medium text-lg dark:text-yellow-dark'>
<strong className='text-yellow font-semibold text-lg dark:text-yellow-dark'>
{title}
</strong>
<br />

View File

@ -15,9 +15,7 @@ export const Repository: React.FC<RepositoryProps> = (props) => {
<a href={href} target='_blank' rel='noopener noreferrer'>
<div className='flex'>
<GitHubIcon className='h-6 mr-2' />
<span className='text-yellow dark:text-yellow-dark hover:underline'>
{name}
</span>
<span className='text-yellow dark:text-yellow-dark'>{name}</span>
</div>
<p className='my-4'>{description}</p>
</a>

View File

@ -1,10 +1,9 @@
import useTranslation from 'next-translate/useTranslation'
export const ProfileInfo: React.FC = () => {
export const ProfileInformation: React.FC = () => {
const { t } = useTranslation()
return (
<>
<div className='pb-2 mb-6 border-b-2 font-headline border-gray-600 dark:border-gray-400'>
<h1 className='text-4xl mb-2'>
{t('home:about.IAm')}{' '}
@ -14,31 +13,5 @@ export const ProfileInfo: React.FC = () => {
</h1>
<h2 className='text-base mb-3'>{t('home:about.description')}</h2>
</div>
<style jsx>
{`
.profile-info {
padding-bottom: 25px;
margin-bottom: 25px;
border-bottom: 1px solid #dedede;
}
.profile-title {
font-size: 36px;
line-height: 1.1;
font-weight: 300;
margin-bottom: 10px;
}
.profile-title > strong {
font-weight: 600;
}
.profile-description {
font-size: 17.4px;
font-weight: 400;
line-height: 1.1;
margin: 0;
}
`}
</style>
</>
)
}

View File

@ -1,14 +1,11 @@
import Image from 'next/image'
import DivloLogo from 'public/images/divlo_logo.png'
export const ProfileLogo: React.FC = () => {
return (
<div className='px-2 py-6'>
<Image
width={370}
height={370}
src='/images/divlo_logo.png'
alt='Divlo'
/>
<div className='px-2 py-6 max-w-[370px] max-h-[370px]'>
<Image src={DivloLogo} alt='Divlo' priority />
</div>
)
}

View File

@ -1,14 +1,14 @@
import { ProfileDescriptionBottom } from './ProfileDescriptionBottom'
import { ProfileInfo } from './ProfileInfo'
import { ProfileInformation } from './ProfileInfo'
import { ProfileList } from './ProfileList'
import { ProfileLogo } from './ProfileLogo'
export const Profile: React.FC = () => {
return (
<div className='flex flex-col justify-center items-center px-10 pt-2 md:pt-10 xl:pt-0 md:flex-row'>
<div className='flex flex-col justify-center items-center px-10 pt-2 md:pt-10 md:flex-row'>
<ProfileLogo />
<div>
<ProfileInfo />
<ProfileInformation />
<ProfileList />
<ProfileDescriptionBottom />
</div>

View File

@ -31,7 +31,6 @@ export const Skills: React.FC = () => {
<SkillsSection title={t('home:skills.softwareTools')}>
<SkillComponent skill='Ubuntu' />
<SkillComponent skill='Hyper' />
<SkillComponent skill='Visual Studio Code' />
<SkillComponent skill='Git' />
<SkillComponent skill='Docker' />

View File

@ -3,7 +3,7 @@ import { render } from '@testing-library/react'
import { Footer } from '../Footer'
describe('<Footer />', () => {
it('should render the version link pointing to the GitHub release', async () => {
it('should render with appropriate link tag version', async () => {
const version = '1.0.0'
const { getByText } = render(<Footer version={version} />)
const versionLink = getByText(version) as HTMLAnchorElement
@ -13,15 +13,4 @@ describe('<Footer />', () => {
`https://github.com/Divlo/Divlo/releases/tag/v${version}`
)
})
it('should render the version link pointing to the `develop` branch', async () => {
const version = '0.0.0-development'
const { getByText } = render(<Footer version={version} />)
const versionLink = getByText(version) as HTMLAnchorElement
expect(getByText('Divlo')).toBeInTheDocument()
expect(versionLink).toBeInTheDocument()
expect(versionLink.href).toEqual(
'https://github.com/Divlo/Divlo/tree/develop'
)
})
})

8
cypress.json Normal file
View File

@ -0,0 +1,8 @@
{
"baseUrl": "http://localhost:3000",
"pluginsFile": false,
"supportFile": false,
"fixturesFolder": false,
"video": false,
"screenshotOnRunFailure": false
}

View File

@ -0,0 +1,47 @@
describe('Common > Header', () => {
beforeEach(() => cy.visit('/'))
describe('Switch theme color (dark/light)', () => {
it('should switch theme from `dark` (default) to `light`', () => {
cy.get('[data-cy=switch-theme-dark]').should('be.visible')
cy.get('[data-cy=switch-theme-light]').should('not.be.visible')
cy.get('body').should(
'not.have.css',
'background-color',
'rgb(255, 255, 255)'
)
cy.get('[data-cy=switch-theme-click]').click()
cy.get('[data-cy=switch-theme-dark]').should('not.be.visible')
cy.get('[data-cy=switch-theme-light]').should('be.visible')
cy.get('body').should(
'have.css',
'background-color',
'rgb(255, 255, 255)'
)
})
})
describe('Switch Language', () => {
it('should switch language from EN (default) to FR', () => {
cy.get('h1').contains('I am Divlo')
cy.get('[data-cy=language-flag-text]').contains('EN')
cy.get('[data-cy=languages-list]').should('not.be.visible')
cy.get('[data-cy=language-click]').click()
cy.get('[data-cy=languages-list]').should('be.visible')
cy.get('[data-cy=languages-list] > li:first-child').contains('FR').click()
cy.get('[data-cy=languages-list]').should('not.be.visible')
cy.get('[data-cy=language-flag-text]').contains('FR')
cy.get('h1').contains('Je suis Divlo')
})
it('should close the language list menu when clicking outside', () => {
cy.get('[data-cy=languages-list]').should('not.be.visible')
cy.get('[data-cy=language-click]').click()
cy.get('[data-cy=languages-list]').should('be.visible')
cy.get('h1').click()
cy.get('[data-cy=languages-list]').should('not.be.visible')
})
})
})

View File

@ -0,0 +1,7 @@
describe('Page /404', () => {
beforeEach(() => cy.visit('/404', { failOnStatusCode: false }))
it('should display the statusCode of 404', () => {
cy.get('[data-cy=status-code]').contains('404')
})
})

View File

@ -0,0 +1,7 @@
describe('Page /500', () => {
beforeEach(() => cy.visit('/500', { failOnStatusCode: false }))
it('should display the statusCode of 500', () => {
cy.get('[data-cy=status-code]').contains('500')
})
})

View File

@ -0,0 +1,19 @@
describe('Page /', () => {
beforeEach(() => cy.visit('/'))
it('should reveals the sections while scrolling except the about section', () => {
const sectionsReveals = [
'#interests',
'#skills',
'#portfolio',
'#open-source'
]
cy.get('#about').should('be.visible')
for (const section of sectionsReveals) {
cy.get(section)
.should('not.be.visible')
.scrollIntoView()
.should('be.visible')
}
})
})

9
cypress/tsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"noEmit": true,
"types": ["cypress"],
"isolatedModules": false
},
"include": ["../node_modules/cypress", "./**/*.ts"]
}

View File

@ -1,16 +0,0 @@
module.exports = {
roots: ['<rootDir>'],
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest'
},
moduleDirectories: ['node_modules', './'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
testEnvironment: 'jsdom',
setupFilesAfterEnv: [
'@testing-library/jest-dom/extend-expect',
'@testing-library/react'
],
collectCoverage: true,
coverageDirectory: './coverage',
coverageReporters: ['text', 'cobertura']
}

14
jest.config.json Normal file
View File

@ -0,0 +1,14 @@
{
"roots": ["<rootDir>"],
"transform": {
"^.+\\.(js|jsx|ts|tsx)$": "babel-jest"
},
"moduleDirectories": ["node_modules", "./"],
"modulePathIgnorePatterns": ["<rootDir>/cypress"],
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
"testEnvironment": "jsdom",
"setupFilesAfterEnv": [
"@testing-library/jest-dom/extend-expect",
"@testing-library/react"
]
}

3
next-env.d.ts vendored
View File

@ -1,3 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@ -1,11 +1,35 @@
const nextPWA = require('next-pwa')
const nextTranslate = require('next-translate')
const { createSecureHeaders } = require('next-secure-headers')
/** @type {import("next").NextConfig} */
module.exports = nextTranslate(
nextPWA({
pwa: {
disable: process.env.NODE_ENV !== 'production',
dest: 'public'
},
async headers() {
return [
{
source: '/:path*',
headers: createSecureHeaders({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-eval'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ['*', 'data:', 'blob:'],
mediaSrc: "'none'",
connectSrc: '*',
objectSrc: "'none'",
fontSrc: "'self'",
baseURI: "'none'"
}
}
})
}
]
}
})
)

13354
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "divlo",
"version": "0.0.0-development",
"version": "1.3.5",
"private": true,
"repository": {
"type": "git",
@ -21,59 +21,69 @@
"lint:markdown": "markdownlint '**/*.md' --dot --ignore node_modules",
"lint:typescript": "eslint '**/*.{js,ts,jsx,tsx}'",
"lint:staged": "lint-staged",
"lighthouse": "lhci autorun",
"test": "jest",
"test:unit": "jest",
"test:lighthouse": "lhci autorun",
"test:e2e": "start-server-and-test 'start' 'http://localhost:3000' 'cypress run'",
"test:e2e:dev": "start-server-and-test 'dev' 'http://localhost:3000' 'cypress open'",
"release": "semantic-release",
"deploy": "vercel",
"postinstall": "husky install"
},
"dependencies": {
"@fontsource/montserrat": "4.5.0",
"@fortawesome/fontawesome-svg-core": "1.2.35",
"@fortawesome/free-brands-svg-icons": "5.15.3",
"@fortawesome/free-solid-svg-icons": "5.15.3",
"@fortawesome/react-fontawesome": "0.1.14",
"@fontsource/montserrat": "4.5.1",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@fortawesome/free-brands-svg-icons": "5.15.4",
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/react-fontawesome": "0.1.15",
"classnames": "2.3.1",
"html-react-parser": "1.2.7",
"next": "11.0.1",
"next-pwa": "5.2.24",
"html-react-parser": "1.2.8",
"next": "11.1.2",
"next-pwa": "5.3.1",
"next-themes": "0.0.15",
"next-translate": "1.0.7",
"react": "17.0.2",
"react-dom": "17.0.2",
"read-pkg": "5.2.0",
"read-pkg": "7.0.0",
"sharp": "0.29.0",
"universal-cookie": "4.0.4"
},
"devDependencies": {
"@commitlint/cli": "13.1.0",
"@commitlint/config-conventional": "13.1.0",
"@lhci/cli": "0.8.0",
"@lhci/cli": "0.8.1",
"@saithodev/semantic-release-backmerge": "1.5.3",
"@semantic-release/git": "9.0.0",
"@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "12.0.0",
"@types/jest": "26.0.24",
"@types/node": "16.4.3",
"@types/react": "17.0.15",
"@types/styled-jsx": "2.2.9",
"@typescript-eslint/eslint-plugin": "4.28.5",
"autoprefixer": "10.3.1",
"babel-jest": "27.0.6",
"@types/jest": "27.0.1",
"@types/node": "16.7.10",
"@types/react": "17.0.19",
"@typescript-eslint/eslint-plugin": "4.30.0",
"autoprefixer": "10.3.3",
"babel-jest": "27.1.0",
"cypress": "8.3.1",
"dockerfilelint": "1.8.0",
"editorconfig-checker": "4.0.2",
"eslint": "7.31.0",
"eslint-config-next": "11.0.1",
"eslint": "7.32.0",
"eslint-config-next": "11.1.2",
"eslint-config-prettier": "8.3.0",
"eslint-config-standard-with-typescript": "20.0.0",
"eslint-plugin-import": "2.23.4",
"eslint-config-standard-with-typescript": "21.0.1",
"eslint-plugin-import": "2.24.2",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "3.4.0",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-promise": "5.1.0",
"husky": "7.0.1",
"jest": "27.0.6",
"lint-staged": "11.1.1",
"eslint-plugin-unicorn": "35.0.0",
"husky": "7.0.2",
"jest": "27.1.0",
"lint-staged": "11.1.2",
"markdownlint-cli": "0.28.1",
"next-secure-headers": "2.2.0",
"postcss": "8.3.6",
"prettier": "2.3.2",
"semantic-release": "17.4.4",
"tailwindcss": "2.2.7",
"typescript": "4.3.5"
"semantic-release": "17.4.7",
"start-server-and-test": "1.13.1",
"tailwindcss": "2.2.9",
"typescript": "4.4.2",
"vercel": "23.1.2"
}
}

View File

@ -1,6 +1,5 @@
import { GetStaticProps } from 'next'
import useTranslation from 'next-translate/useTranslation'
import readPackageJSON from 'read-pkg'
import { ErrorPage } from 'components/ErrorPage'
import { Head } from 'components/Head'
@ -25,7 +24,8 @@ const Error404: React.FC<FooterProps> = (props) => {
}
export const getStaticProps: GetStaticProps<FooterProps> = async () => {
const { version } = await readPackageJSON()
const { readPackage } = await import('read-pkg')
const { version } = await readPackage()
return { props: { version } }
}

View File

@ -1,6 +1,5 @@
import { GetStaticProps } from 'next'
import useTranslation from 'next-translate/useTranslation'
import readPackageJSON from 'read-pkg'
import { ErrorPage } from 'components/ErrorPage'
import { Head } from 'components/Head'
@ -25,7 +24,8 @@ const Error500: React.FC<FooterProps> = (props) => {
}
export const getStaticProps: GetStaticProps<FooterProps> = async () => {
const { version } = await readPackageJSON()
const { readPackage } = await import('read-pkg')
const { version } = await readPackage()
return { props: { version } }
}

View File

@ -6,9 +6,7 @@ import UniversalCookie from 'universal-cookie'
import 'tailwindcss/tailwind.css'
import '@fontsource/montserrat/400.css'
import '@fontsource/montserrat/500.css'
import '@fontsource/montserrat/600.css'
import '@fontsource/montserrat/700.css'
const universalCookie = new UniversalCookie()

View File

@ -9,9 +9,9 @@ import Document, {
class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
context: DocumentContext
): Promise<DocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx)
const initialProps = await Document.getInitialProps(context)
return initialProps
}

View File

@ -1,6 +1,5 @@
import { GetStaticProps } from 'next'
import useTranslation from 'next-translate/useTranslation'
import readPackageJSON from 'read-pkg'
import { RevealFade } from 'components/design/RevealFade'
import { Section } from 'components/design/Section'
@ -71,7 +70,8 @@ const Home: React.FC<FooterProps> = (props) => {
}
export const getStaticProps: GetStaticProps<FooterProps> = async () => {
const { version } = await readPackageJSON()
const { readPackage } = await import('read-pkg')
const { version } = await readPackage()
return { props: { version } }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -10,6 +10,7 @@
"removeComments": true,
"noEmit": true,
"strict": true,
"types": ["jest", "@testing-library/jest-dom", "@testing-library/react"],
"baseUrl": ".",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,

5
vercel.json Normal file
View File

@ -0,0 +1,5 @@
{
"github": {
"enabled": false
}
}