diff --git a/apps/landing/index.html b/apps/landing/index.html index 7737c221d..7aba5deec 100644 --- a/apps/landing/index.html +++ b/apps/landing/index.html @@ -7,7 +7,17 @@ - + + + + + @@ -16,5 +26,6 @@
+ diff --git a/apps/landing/package.json b/apps/landing/package.json index 5fc9a9bd3..038f462a3 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -11,6 +11,8 @@ "dependencies": { "@heroicons/vue": "^1.0.6", "iconoir": "^5.3.2", + "sass": "^1.69.1", + "snarkdown": "^2.0.0", "vue": "^3.2.25", "vue-router": "^4.0.15" }, diff --git a/apps/landing/public/action.png b/apps/landing/public/action.png new file mode 100644 index 000000000..d4395de79 Binary files /dev/null and b/apps/landing/public/action.png differ diff --git a/apps/landing/public/arrow.svg b/apps/landing/public/arrow.svg new file mode 100644 index 000000000..19514c52c --- /dev/null +++ b/apps/landing/public/arrow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/landing/public/credit-card.svg b/apps/landing/public/credit-card.svg new file mode 100644 index 000000000..1b7fd029d --- /dev/null +++ b/apps/landing/public/credit-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/decentralized_nodes.svg b/apps/landing/public/decentralized_nodes.svg deleted file mode 100644 index 356faae9b..000000000 --- a/apps/landing/public/decentralized_nodes.svg +++ /dev/null @@ -1,504 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/landing/public/disc.svg b/apps/landing/public/disc.svg new file mode 100644 index 000000000..2595b4446 --- /dev/null +++ b/apps/landing/public/disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/discord.svg b/apps/landing/public/discord.svg deleted file mode 100644 index 4b7477340..000000000 --- a/apps/landing/public/discord.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/landing/public/flash.svg b/apps/landing/public/flash.svg new file mode 100644 index 000000000..2233cf6ba --- /dev/null +++ b/apps/landing/public/flash.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/landing/public/future_casimir.svg b/apps/landing/public/future_casimir.svg deleted file mode 100644 index 8a78fa7d1..000000000 --- a/apps/landing/public/future_casimir.svg +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/landing/public/gg.svg b/apps/landing/public/gg.svg new file mode 100644 index 000000000..e2cd14c59 --- /dev/null +++ b/apps/landing/public/gg.svg @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/landing/public/hero.png b/apps/landing/public/hero.png new file mode 100644 index 000000000..8921d67a5 Binary files /dev/null and b/apps/landing/public/hero.png differ diff --git a/apps/landing/public/key.svg b/apps/landing/public/key.svg new file mode 100644 index 000000000..e778e74eb --- /dev/null +++ b/apps/landing/public/key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/lock.svg b/apps/landing/public/lock.svg new file mode 100644 index 000000000..de09d9db3 --- /dev/null +++ b/apps/landing/public/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/logo.png b/apps/landing/public/logo.png new file mode 100644 index 000000000..61a9dc5ad Binary files /dev/null and b/apps/landing/public/logo.png differ diff --git a/apps/landing/public/logo.svg b/apps/landing/public/logo.svg new file mode 100644 index 000000000..8b965cdc7 --- /dev/null +++ b/apps/landing/public/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/landing/public/metamask.svg b/apps/landing/public/metamask.svg deleted file mode 100644 index 1357bb525..000000000 --- a/apps/landing/public/metamask.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/apps/landing/public/minimal_trust.svg b/apps/landing/public/minimal_trust.svg deleted file mode 100644 index 47bfb7e00..000000000 --- a/apps/landing/public/minimal_trust.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/landing/public/stake.png b/apps/landing/public/stake.png new file mode 100644 index 000000000..f446979aa Binary files /dev/null and b/apps/landing/public/stake.png differ diff --git a/apps/landing/public/staking.png b/apps/landing/public/staking.png new file mode 100644 index 000000000..877ecfae9 Binary files /dev/null and b/apps/landing/public/staking.png differ diff --git a/apps/landing/public/twitter_x_logo.png b/apps/landing/public/twitter_x_logo.png deleted file mode 100644 index 2c2d7e863..000000000 Binary files a/apps/landing/public/twitter_x_logo.png and /dev/null differ diff --git a/apps/landing/public/tx.png b/apps/landing/public/tx.png new file mode 100644 index 000000000..8382b346f Binary files /dev/null and b/apps/landing/public/tx.png differ diff --git a/apps/landing/public/txx.png b/apps/landing/public/txx.png new file mode 100644 index 000000000..758b6cecd Binary files /dev/null and b/apps/landing/public/txx.png differ diff --git a/apps/landing/public/txx2.png b/apps/landing/public/txx2.png new file mode 100644 index 000000000..26b7f4472 Binary files /dev/null and b/apps/landing/public/txx2.png differ diff --git a/apps/landing/public/users.svg b/apps/landing/public/users.svg new file mode 100644 index 000000000..aacf6b08e --- /dev/null +++ b/apps/landing/public/users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/landing/public/walletIcon.svg b/apps/landing/public/walletIcon.svg deleted file mode 100644 index 76983bbb2..000000000 --- a/apps/landing/public/walletIcon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/apps/landing/src/App.vue b/apps/landing/src/App.vue index bd7e61e66..e632401dc 100644 --- a/apps/landing/src/App.vue +++ b/apps/landing/src/App.vue @@ -1,34 +1,19 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/apps/landing/src/blogs/blog.md b/apps/landing/src/blogs/blog.md new file mode 100644 index 000000000..3e59d5260 --- /dev/null +++ b/apps/landing/src/blogs/blog.md @@ -0,0 +1,11 @@ +# Casimir is Live on Goerli! + +10/2/2023 + +We're proud to announce that our distributed, self custody ETH staking platform, Casimir, is live on the ETH Goerli Testnet. Casimir is powered by distributed key generation and distributed validator technology. The Casimir SelfStake manager offers an approach where stakers can directly deposit any amount of ETH to high-performing Ethereum operators. This approach minimizes counterparty risk for users and enhances the decentralization of Ethereum staking: +* Validators duties are performed by openly registered (and collateralized) operators running distributed validator technology (DVT) +* Keys are trustlessly managed using zero-coordination distributed key generation (DKG) +* Automated actions (like compounding stake or handling a slash) are carried out by a decentralized oracle network (DON) +* The staking user experience is improved by wrapping staking contract actions using account abstraction. + +By creating a smart contract primitive that trustlessly connects stakers and node operators, we create a customizable staking process that allows users to access new staking features, such as restaking. Over the next few weeks we'll be introducing some of these additional features, such as restaking, to our platform. diff --git a/apps/landing/src/components/Footer.vue b/apps/landing/src/components/Footer.vue deleted file mode 100644 index 016232a18..000000000 --- a/apps/landing/src/components/Footer.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/components/LoaderSpinner.vue b/apps/landing/src/components/LoaderSpinner.vue new file mode 100644 index 000000000..011a03661 --- /dev/null +++ b/apps/landing/src/components/LoaderSpinner.vue @@ -0,0 +1,117 @@ + + + + + + \ No newline at end of file diff --git a/apps/landing/src/components/NavBar.vue b/apps/landing/src/components/NavBar.vue deleted file mode 100644 index e74e332e9..000000000 --- a/apps/landing/src/components/NavBar.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/components/Scrambler.vue b/apps/landing/src/components/Scrambler.vue deleted file mode 100644 index a4c642cf2..000000000 --- a/apps/landing/src/components/Scrambler.vue +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/apps/landing/src/components/TermsOfService.vue b/apps/landing/src/components/TermsOfService.vue deleted file mode 100644 index 581040e98..000000000 --- a/apps/landing/src/components/TermsOfService.vue +++ /dev/null @@ -1,221 +0,0 @@ - - - - - \ No newline at end of file diff --git a/apps/landing/src/components/charts/LineChartJS.vue b/apps/landing/src/components/charts/LineChartJS.vue deleted file mode 100644 index cefa9f12a..000000000 --- a/apps/landing/src/components/charts/LineChartJS.vue +++ /dev/null @@ -1,147 +0,0 @@ - - - \ No newline at end of file diff --git a/apps/landing/src/composables/blogs.ts b/apps/landing/src/composables/blogs.ts new file mode 100644 index 000000000..cd106b039 --- /dev/null +++ b/apps/landing/src/composables/blogs.ts @@ -0,0 +1,67 @@ +import { onMounted, onUnmounted, readonly, ref } from 'vue' +import snarkdown from 'snarkdown' + +const initializeComposable = ref(false) + +type blog = { + title: string; + content: string; + timestamp: string; + type: string; + id: string; +}; + +const allBlogs = ref([] as blog[]) +const loadingBlogs = ref(true) + +export default function useBlogs() { + async function getContentOfBlog(itemId: string) { + const response = await fetch(`http://localhost:3003/api/hackmd/${itemId}`) + const json = await response.json() + const md = snarkdown(json.content) + + return md + } + + onMounted(async () => { + if (!initializeComposable.value) { + loadingBlogs.value = true + try { + const response = await fetch('http://localhost:3003/api/hackmd') + const jsonList = await response.json() + const blogList = [] + + for (let i = 0; i < jsonList.length; i++) { + const title = jsonList[i].title + const content = await getContentOfBlog(jsonList[i].id) + const timestamp = jsonList[i].publishedAt + const id = jsonList[i].id + blogList.push({ + title: title, + content: content, + timestamp: timestamp, + type: 'Blog', + id: id, + }) + } + + allBlogs.value = blogList + loadingBlogs.value = false + } catch (error) { + console.error('Error trying to fetch:', error) + loadingBlogs.value = false + } + + initializeComposable.value = true + } + }) + + onUnmounted(() => { + initializeComposable.value = false + }) + + return { + allBlogs: readonly(allBlogs), + loadingBlogs: readonly(loadingBlogs), + } +} diff --git a/apps/landing/src/composables/router.ts b/apps/landing/src/composables/router.ts index 5e3f4439a..6a5268415 100644 --- a/apps/landing/src/composables/router.ts +++ b/apps/landing/src/composables/router.ts @@ -1,19 +1,36 @@ -import Landing from '@/pages/landing/Landing.vue' import { createWebHistory, createRouter } from 'vue-router' - -const routes = [ - { - path: '/', - name: Landing, - component: Landing, - }, +import Landing from '@/pages/landing/Landing.vue' +import Changelog from '@/pages/changelog/Changelog.vue' +import Blog from '@/pages/blog/Blog.vue' +import SingleBlog from '@/pages/blog/components/SingleBlog.vue' +const routes = [ + { + path: '/', + name: Landing, + component: Landing, + }, + { + path: '/blogs', + name: Blog, + component: Blog, + }, + { + path: '/blog/:id', + component: SingleBlog, + children: [{ path: '', name: SingleBlog, component: SingleBlog }], + }, + { + path: '/changelog', + name: Changelog, + component: Changelog, + }, ] const router = createRouter({ - history: createWebHistory(), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - routes + history: createWebHistory(), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + routes, }) -export default router \ No newline at end of file +export default router diff --git a/apps/landing/src/composables/screenDimenstions.ts b/apps/landing/src/composables/screenDimenstions.ts deleted file mode 100644 index f8192fe95..000000000 --- a/apps/landing/src/composables/screenDimenstions.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { onMounted, onUnmounted, readonly, ref } from 'vue' - -const initializeComposable = ref(false) - -const screenWidth = ref(0) -const screenHeight = ref(0) - -export default function useScreenDimentions() { - - const findScreenDimenstions = () => { - try { - screenWidth.value = window.innerWidth - screenHeight.value = window.innerHeight - } catch (error) { - console.log('Listening to screen dimentions error', error) - } - } - - onMounted(() => { - if(!initializeComposable.value){ - console.log('listening to screen dimentions') - findScreenDimenstions() - window.addEventListener('resize', findScreenDimenstions) - initializeComposable.value = true - } - - }) - - onUnmounted(() =>{ - window.removeEventListener('resize', findScreenDimenstions) - initializeComposable.value = false - }) - - return { - screenWidth: readonly(screenWidth), - screenHeight: readonly(screenHeight) - } -} \ No newline at end of file diff --git a/apps/landing/src/index.css b/apps/landing/src/index.css index 65ff61589..88ca7820b 100644 --- a/apps/landing/src/index.css +++ b/apps/landing/src/index.css @@ -3,35 +3,1099 @@ @tailwind utilities; :root { -font-family: 'IBM Plex Sans', sans-serif; -font-synthesis: none; -text-rendering: optimizeLegibility; --webkit-font-smoothing: antialiased; --moz-osx-font-smoothing: grayscale; --webkit-text-size-adjust: 100%; -} - -.tooltip_container{ - position: relative; -} - -.tooltip_container:hover .tooltip { - visibility: visible; - opacity: 1; -} - -.tooltip { - position: absolute; - top: 110%; - border-radius: 3px; - background-color: rgba(0,0,0,0.75); - color: white; - font-size: 12px; - line-height: 14px; - padding: 6px 8px; - visibility: hidden; - white-space: normal; - opacity: 0; - transition: opacity 0.4s ease-in-out; - z-index: 5; -} \ No newline at end of file + font-family: "IBM Plex Sans", sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +.skeleton_box { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: shimmer 2.5s infinite forwards; + backdrop-filter: blur(10px); +} + +@keyframes shimmer { + 0% { + background-position: +200% 0; + } + 100% { + background-position: -200% 0; + } +} + +.changelog { + max-width: 960px; + margin: 60px auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 40px; +} + +.changelog__header { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 15px; +} + +.changelog__container { + width: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 0; + background-color: rgba(251, 251, 253, 0.8); + border: 1px solid rgb(216, 222, 228); + border-radius: 8px; + box-shadow: 8px -15px 54px 32px rgba(0, 0, 0, 0.023); +} + +.vupdate__container { + display: flex; + flex-direction: column; + justify-content: flex-start; +} + +.vupdate { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + border-bottom: 1px solid rgba(231, 231, 231, 0.8); + gap: 5px; + padding: 35px 45px; +} + +.vupdate:last-child { + border-bottom: none; + /* padding-bottom: 0; */ +} + +.vupdate__read { + font-size: 15px; + font-weight: 500; + letter-spacing: -0.2px; + margin: 0; + font-weight: 400; + padding-top: 20px; +} + +.vupdate__tag { + display: inline-block; + width: auto; + font-weight: 500; + font-size: 13px; + padding: 1px 6px; + color: white; + background-color: #0d5fff; +} + +.vupdate__body { + font-weight: 400; + font-size: 15px; + letter-spacing: -0.2px; + color: #080808; +} + +.vupdate__body ul { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 10px; + padding: 0; + margin: 0; + margin-top: 20px; +} + +.vupdate__body li { + list-style: none; + font-weight: 400; + font-size: 15px; + letter-spacing: -0.2px; + color: #080808; +} + +.vupdate__body li::before { + content: "-"; + color: #51555f; + font-weight: bold; + display: inline-block; + width: 1em; + margin-left: -1em; +} + +.bento { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 60px; + + max-width: 960px; + margin: 120px auto 0 auto; +} + +.bento__container { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 25px; + width: 100%; +} + +.bento__base__card { + display: flex; + flex-direction: column; + padding: 30px 30px 0 30px; + gap: 30px; + overflow: hidden; + cursor: pointer; + border-radius: 8px; +} + +.bento__base__card img { + transition: all 0.19s ease-out; +} + +.bento__base__card img:hover { + padding: 0; + margin: 0; + transform: translate(0, -20px); +} + +.bento__card__1 { + grid-area: 1 / 1 / 2 / 4; + background-color: rgb(242, 242, 245); + border: 1px solid hsl(236, 10.6%, 87.9%); + width: 100%; + height: 420px; +} + +.bento__card__2 { + grid-area: 2 / 1 / 3 / 3; + background-color: rgb(242, 242, 245); + border: 1px solid hsl(236, 10.6%, 87.9%); + width: 100%; + height: 420px; +} + +.bento__card__3 { + grid-area: 2 / 3 / 3 / 6; + background-color: rgb(242, 242, 245); + border: 1px solid hsl(236, 10.6%, 87.9%); + width: 100%; + height: 420px; +} + +.bento__card__4 { + grid-area: 1 / 4 / 2 / 6; + background-color: rgb(242, 242, 245); + border: 1px solid hsl(236, 10.6%, 87.9%); + width: 100%; + height: 420px; +} + +.pill { + box-shadow: inset 0px 1px 0px rgba(0, 0, 0, 0.1), + inset 0px -1px 0px 1px rgba(0, 0, 0, 0.1); + color: rgb(11, 121, 175); + background-color: hsl(209, 95%, 90.1%); + text-transform: uppercase; + padding: 0.125rem 0.5rem; + border-radius: 0.25rem; + width: fit-content; + font-size: 0.694rem; + font-weight: 500; + letter-spacing: 0.5px; +} + +.footer { + margin: 120px auto 0 auto; + background-color: rgba(255, 255, 255, 0.85); + border-top: 1px solid hsl(234, 10.4%, 84.4%); +} +.footer__container { + max-width: 960px; + margin: 0 auto; + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + color: black; + padding: 8px 0; +} + +.c { + font-size: 14px; + font-weight: 400; + margin: 0; +} + +ul { + display: flex; + flex-direction: row; + gap: 2.2rem; +} + +body { + font-family: "IBM Plex Sans", sans-serif; + font-size: 16px; + line-height: 1.5; + color: hsl(210, 12%, 12.5%); +} + +body, +h1, +h2, +h3, +h4, +h5, +h6, +p, +span, +a, +.text-1, +.text-2, +.text-3, +.text-4, +.text-5, +.text-6, +.text-7, +.text-8, +.text-9, +.text-10, +.text-11, +.text-12, +.text-13, +.text-r, +.bold, +.highlight, +.link-color { + padding: 0; + margin: 0; + transition: all 0.22s ease; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Mixin typography */ +h1 { + font-size: 2.488rem; + font-weight: 400; + letter-spacing: -1.2px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +h2 { + font-size: 1.728rem; + font-weight: 400; + letter-spacing: -0.41px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +h3 { + font-size: 1.44rem; + font-weight: 400; + letter-spacing: -0.21px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +h4 { + font-size: 1.2rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +h5 { + font-size: 1rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +h6 { + font-size: 0.92rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +p { + font-size: 1rem; + font-weight: 400; + letter-spacing: -0.04px; + line-height: 1.38; + max-width: 520px; + word-wrap: break-word; +} + +span { + font-size: 1rem; + font-weight: 400; +} + +a { + padding: 0; + margin: 0; + transition: all 0.22s ease; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 0.833rem; + text-decoration: none; + color: hsl(227, 5.2%, 51.8%); +} + +a:hover { + color: hsl(210, 12%, 12.5%); +} + +a.active { + color: hsl(210, 12%, 12.5%); +} + +.text-1 { + font-size: 2.986rem; + font-weight: 400; + letter-spacing: -2px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-2 { + font-size: 2.488rem; + font-weight: 400; + letter-spacing: -1.2px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-3 { + font-size: 2.074rem; + font-weight: 400; + letter-spacing: -0.8px; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-4 { + font-size: 1.728rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-5 { + font-size: 1.44rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-6 { + font-size: 1.2rem; + font-weight: 400; + line-height: 1.38; + color: hsl(210, 12%, 12.5%); +} + +.text-7 { + font-size: 1rem; + font-weight: 400; + letter-spacing: -0.04px; + line-height: 1.38; +} + +.text-8 { + font-size: 0.92rem; + font-weight: 500; +} + +.text-9 { + font-size: 0.833rem; + font-weight: 400; +} + +.text-9:hover { + background-color: hsl(210, 98.8%, 94%); +} + +.text-10 { + font-size: 0.694rem; + font-weight: 500; +} + +.text-11 { + font-size: 0.579rem; + font-weight: 400; +} + +.text-12 { + font-size: 0.482rem; + font-weight: 400; +} + +.text-13 { + font-size: 0.252rem; + font-weight: 400; +} + +.text-r { + font-size: 0.92rem; + font-weight: 400; + line-height: 1.6; + color: rgb(91, 91, 91); +} + +.bold { + font-weight: 500; +} + +.highlight { + color: #0d5fff; +} + +.link-color { + color: hsl(209, 100%, 96.5%); +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + line-height: 1.5; + padding: 0; + -webkit-font-smoothing: antialiased; +} + +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; +} + +input, +button, +textarea, +select { + font: inherit; +} + +p, +h1, +h2, +h3, +h4, +h5, +h6 { + overflow-wrap: break-word; +} + +a { + color: inherit; + cursor: pointer; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +ul li { + list-style: none; +} + +.container-md { + max-width: 960px; + margin: 0 auto; +} + +/* base { + position: relative; + display: inline-block; + cursor: pointer; + border-radius: 5px; + font-weight: 500; + text-decoration: none; + transition: all 0.22s ease; + -webkit-box-align: center; + -webkit-font-smoothing: antialiased; + font-size: $text-9-font-size; +} */ + +.btn-primary { + position: relative; + display: inline-block; + cursor: pointer; + border-radius: 5px; + font-weight: 500; + text-decoration: none; + transition: all 0.22s ease; + -webkit-box-align: center; + -webkit-font-smoothing: antialiased; + font-size: 0.833rem; + background-color: hsl(211, 90%, 42%); + border-radius: 5px; + border: 1px solid hsl(211, 90%, 42%); + color: hsl(240, 20%, 98%); + cursor: pointer; + display: inline-flex; + flex-wrap: nowrap; + padding: 8px 18px; + font-size: 13px; + transition: all 0.22s ease; +} + +.btn-primary:hover { + color: rgb(252, 252, 253); + background-color: darken(hsl(220, 6%, 40%), 5%); +} + +.btn-primary-sm { + position: relative; + display: inline-block; + cursor: pointer; + border-radius: 5px; + font-weight: 500; + text-decoration: none; + transition: all 0.22s ease; + -webkit-box-align: center; + -webkit-font-smoothing: antialiased; + font-size: 0.833rem; + background-color: hsl(211, 90%, 42%); + border-radius: 5px; + border: 1px solid hsl(211, 90%, 42%); + color: hsl(240, 20%, 98%); + cursor: pointer; + display: inline-flex; + flex-wrap: nowrap; + padding: 8px 18px; + font-size: 13px; + transition: all 0.22s ease; + padding: 2px 14px; + font-size: 12px; +} + +.btn-secondary { + position: relative; + display: inline-block; + cursor: pointer; + border-radius: 5px; + font-weight: 500; + text-decoration: none; + transition: all 0.22s ease; + -webkit-box-align: center; + -webkit-font-smoothing: antialiased; + font-size: 0.833rem; + background-color: hsl(240, 20%, 98%); + border: 1px solid hsl(236, 10.6%, 87.9%); + padding: 8px 18px; + color: hsl(227, 5.2%, 51.8%); +} + +.btn-secondary:hover { + background-color: darken(hsl(240, 20%, 98%), 2%); + color: hsl(220, 6%, 40%); + border: 1px solid hsl(234, 10.4%, 84.4%); +} + +.nav { + width: 100%; + position: sticky; + top: 0; + z-index: 4; + background-color: rgba(255, 255, 255, 0.85); + border-bottom: 1px solid hsl(234, 10.4%, 84.4%); + backdrop-filter: saturate(180%) blur(6px); + transition: background-color 0.3s ease; +} + +.nav__container { + max-width: 960px; + display: flex; + justify-content: space-between; + align-items: center; + margin: 0 auto; + padding: 8px 0; +} + +.logo { + cursor: pointer; + width: 16px; +} +.logo:hover { + opacity: 0.9; +} + +.nav__links { + display: flex; + flex-direction: row; + gap: 2.2rem; +} + +.hero { + max-width: 960px; + margin: 40px auto 0 auto; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + padding: 0; + gap: 50px; + text-align: left; +} + +.hero__container { + min-width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: left; + gap: 30px; +} + +.text__container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.cta__container { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 40px; + text-decoration: none; +} + +.mockup { + background-color: hsl(234, 10.4%, 84.4%); + border: 1px solid hsl(231, 10.2%, 75.1%); + overflow: hidden; + border-radius: 8px; + width: 100%; + /* height: 520px; */ +} + +.mockup img { + border-radius: 8px; + -webkit-box-shadow: 10px 10px 131px 0px rgba(0, 0, 0, 0.07); + -moz-box-shadow: 10px 10px 131px 0px rgba(0, 0, 0, 0.07); + box-shadow: 10px 10px 131px 0px rgba(0, 0, 0, 0.07); +} + +.features { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + display: flex; + flex-direction: column; + gap: 60px; +} + +.features__item { + border: 1px solid hsl(236, 10.6%, 87.9%); + border-radius: 8px; + padding: 30px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + cursor: default; +} + +.features__item__text { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + gap: 10px; +} + +.features__item__text span { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-weight: 500; + width: 26px; + height: 26px; + font-size: 14px; + background-color: hsl(234, 10.4%, 84.4%); + border-radius: 100px; +} + +.features__item:hover span { + background-color: hsl(208, 77.5%, 76.9%); +} + +.features__item__card { + width: 120px; + height: 120px; + border: 1px solid hsl(236, 10.6%, 87.9%); + background-color: rgb(242, 242, 245); + border-radius: 8px; + display: flex; + flex-direction: column; +} + +.events { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; +} + +.events__text { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + gap: 30px; +} + +.slots { + margin-top: 40px; + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + display: flex; +} + +.slot { + display: flex; + flex-direction: column; + gap: 20px; + align-items: flex-start; + width: 200px; + height: 260px; + background: rgb(252, 252, 253); + border-radius: 10px; + border: 1px solid hsl(236, 10.6%, 87.9%); + padding: 20px; + box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05); + transform: translate(0, 0); + transition: transform 0.245s ease-out; + cursor: default; +} + +.slot__obj { + display: flex; + flex-direction: column; + gap: 8px; +} + +.slot:not(:first-child) { + margin-left: -135px; +} + +.slot:hover:not(:last-child) { + transform: translate(-50px, -45px) rotate(-2deg); +} + +.overview { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-center; +} + +.overview__header { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + gap: 10px; +} + +.overview__container { + margin-top: 55px; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 40px; +} + +.overview__item { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 20px; + text-align: left; +} + +.overview__item__header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 15px; +} + +.mock { + margin-top: 55px; + height: 520px; + background-color: rgb(139, 141, 152); + border-radius: 10px; + width: 100%; +} + +.overview__header { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 20px; +} + +.overview__container { + margin-top: 55px; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 40px; +} + +.overview__item { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 20px; + text-align: left; +} + +.overview__item__header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 15px; +} + +.features { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + display: grid; + flex-direction: column; + justify-content: space-between; + text-align: center; +} + +.features__container { + margin: 0 auto; + width: 100%; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 60px; +} + +.card { + background-color: #ffffff; + border: 1px solid rgb(216, 222, 228); + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: flex-start; +} + +.top__rect { + background-color: hsl(210, 98.8%, 94%); + height: 100%; + width: 100%; +} + +.bottom__text { + padding: 20px 30px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 8px; + border-top: 1px solid rgb(216, 222, 228); + text-align: left; +} + +.faq { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; +} + +.faq__container { + margin-top: 60px; + text-align: left; + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: flex-start; + gap: 20px; +} + +.faq__item { + border-bottom: 1px solid hsl(238, 11.8%, 92.9%); + padding-bottom: 8px; + display: flex; + flex-direction: column; + justify-content: flex-start; + padding-bottom: 20px; + gap: 20px; +} + +.faq__item .text-7 { + font-weight: 500; +} + +.faq__item__q { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + cursor: pointer; +} + +.faq__item__q span:nth-child(2) { + font-weight: 300; +} + +.faq__item__a { + /* display: none; */ +} + +.faq__item__a:active { + /* display: block; */ +} + +.roadmap { + max-width: 960px; + margin: 120px auto 0 auto; + width: 100%; + text-align: center; +} + +.roadmap__container { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + margin-top: 45px; + border: 1px solid rgb(229, 229, 229); + border-radius: 8px; + padding: 30px; +} + +.roadmap__header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + text-align: left; + gap: 20px; +} + +.roadmap__header span { + width: 45%; +} + +.roadmap__item__container { + border-radius: 8px; + padding-top: 40px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: first baseline; + gap: 40px; + margin-top: -1px; +} + +.roadmap__item { + padding: 1rem; + color: black; + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-direction: column; + text-align: left; +} + +.roadmap__item .highlight, +.roadmap__item .text-8 { + color: gray; +} + +.newsletter { + max-width: 960px; + margin: 160px auto 0px auto; + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + color: black; + background-color: rgba(251, 251, 253, 0.8); + border: 1px solid rgb(216, 222, 228); + border-radius: 8px; + padding: 2rem; +} + +.newsletter div { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 1rem; +} + +.newsletter input { + font-size: 14px; + height: 38px; + min-width: 240px; + border-radius: 5px; + border: 1px solid #eaecf0; + background: #fff; + box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05); + padding: 0 1rem; + margin: 1rem 0; +} + +.newsletter input:focus { + outline: none; + border: 1px solid #eaecf0; +} diff --git a/apps/landing/src/mockData/mock_transaction_data.ts b/apps/landing/src/mockData/mock_transaction_data.ts deleted file mode 100644 index 7e1bd27ef..000000000 --- a/apps/landing/src/mockData/mock_transaction_data.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ref, onMounted } from 'vue' -const txData = ref(null as any) - -export default function useTxData () { - - function generateRandomBalance() { - // Generate a random balance between 0 and 100 - return Math.floor(Math.random() * 101) - } - - function generateRandomDate() { - // Generate a random date within the last two years - const startDate = new Date() - startDate.setFullYear(startDate.getFullYear() - 2) - const endDate = new Date() - const randomDate = new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime())) - - const year = randomDate.getFullYear() - const month = String(randomDate.getMonth() + 1).padStart(2, '0') - const day = String(randomDate.getDate()).padStart(2, '0') - const hours = String(randomDate.getHours()).padStart(2, '0') - const minutes = String(randomDate.getMinutes()).padStart(2, '0') - const seconds = String(randomDate.getSeconds()).padStart(2, '0') - const milliseconds = String(randomDate.getMilliseconds()).padStart(3, '0') - - return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}:${milliseconds}` - } - - function generateMockTransactionData(numTransactions: number, walletAddresses: string[]) { - // const walletAddresses = [ - // '0xd557a5745d4560B24D36A68b52351ffF9c86A212', - // '0x728474D29c2F81eb17a669a7582A2C17f1042b57', - // // '0x84725c8f954f18709aDcA150a0635D2fBE94fDfF', - // '0x2EFD9900b748EbFfe658662c1ED853982Bf86ED9', - // // '0x9347155C4586f25306462EbA8BB8df7f06Bb5247', - // // '0x79AE48EF1b199C586A05D1e3bC0f83fBe576d1ae', - // // '0xBE5F02D2d08994288aCF53ddC47d8150d41fb3A8', - // // '0xd3260De619cc58a6A61Dfa1DDDb52d760384f9a8', - // // '0xFcB0d31595fB9bB641DeEE0E4E50050D613337C0', - // // '0xc3178D118c54954b4811958916ca7B3b5D2cEDc5' - // ] - - const data = [] - - for (let i = 0; i < numTransactions; i++) { - const transaction = { - walletAddress: walletAddresses[i % walletAddresses.length], - walletBalance: String(generateRandomBalance()), - txDirection: Math.random() < 0.5? 'incoming': 'outgoing', - txId: '0xf46d39ca96e489fb0eb2097f073bfde2dc7960bf8358e0692fa79cc8597d283e', - receivedAt: generateRandomDate(), - amount: (Math.random() * 20.00).toFixed(2), - price: (Math.random() * 2000.00).toFixed(2), - gasFee: (Math.random() * 10.00).toFixed(2), - stakeFee: (Math.random() * 10.00).toFixed(2), - rewards:(Math.random() * 10.00).toFixed(2), - status: Math.random() > 0.5? 'Pending' : 'Active', - type: Math.random() > 0.5? null : Math.random() > 0.5? 'Stake SSV' : 'Withdraw', - } - data.push(transaction) - } - - return data - } - - const mockData = (walletAddresses: string[]) => { - const numTransactions = 400 // Number of transactions to generate - const data = generateMockTransactionData(numTransactions, walletAddresses) - // const jsonData = JSON.stringify(data, null, 2) - - txData.value = data - } - return { - txData, - mockData - } -} \ No newline at end of file diff --git a/apps/landing/src/pages/blog/Blog.vue b/apps/landing/src/pages/blog/Blog.vue new file mode 100644 index 000000000..379880d6c --- /dev/null +++ b/apps/landing/src/pages/blog/Blog.vue @@ -0,0 +1,157 @@ + + + + + + \ No newline at end of file diff --git a/apps/landing/src/pages/blog/components/SingleBlog.vue b/apps/landing/src/pages/blog/components/SingleBlog.vue new file mode 100644 index 000000000..0b104cf12 --- /dev/null +++ b/apps/landing/src/pages/blog/components/SingleBlog.vue @@ -0,0 +1,191 @@ + + + + + + \ No newline at end of file diff --git a/apps/landing/src/pages/changelog/Changelog.vue b/apps/landing/src/pages/changelog/Changelog.vue new file mode 100644 index 000000000..09edf5ff0 --- /dev/null +++ b/apps/landing/src/pages/changelog/Changelog.vue @@ -0,0 +1,161 @@ + + + + + + \ No newline at end of file diff --git a/apps/landing/src/pages/landing/Landing.vue b/apps/landing/src/pages/landing/Landing.vue index 45ca04abe..91ba28ed8 100644 --- a/apps/landing/src/pages/landing/Landing.vue +++ b/apps/landing/src/pages/landing/Landing.vue @@ -1,162 +1,363 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/Content.vue b/apps/landing/src/pages/landing/comoponents/Content.vue deleted file mode 100644 index a75a0f9ed..000000000 --- a/apps/landing/src/pages/landing/comoponents/Content.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/DummyBreakdown.vue b/apps/landing/src/pages/landing/comoponents/DummyBreakdown.vue deleted file mode 100644 index bff10d10b..000000000 --- a/apps/landing/src/pages/landing/comoponents/DummyBreakdown.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/DummyChart.vue b/apps/landing/src/pages/landing/comoponents/DummyChart.vue deleted file mode 100644 index 2795176f1..000000000 --- a/apps/landing/src/pages/landing/comoponents/DummyChart.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/DummyStaking.vue b/apps/landing/src/pages/landing/comoponents/DummyStaking.vue deleted file mode 100644 index 7fdf30166..000000000 --- a/apps/landing/src/pages/landing/comoponents/DummyStaking.vue +++ /dev/null @@ -1,267 +0,0 @@ - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/Features.vue b/apps/landing/src/pages/landing/comoponents/Features.vue deleted file mode 100644 index 028bf4ab7..000000000 --- a/apps/landing/src/pages/landing/comoponents/Features.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/Footer.vue b/apps/landing/src/pages/landing/comoponents/Footer.vue deleted file mode 100644 index c6e4f3716..000000000 --- a/apps/landing/src/pages/landing/comoponents/Footer.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/QuestionsAndAnswers.vue b/apps/landing/src/pages/landing/comoponents/QuestionsAndAnswers.vue deleted file mode 100644 index 399b6773a..000000000 --- a/apps/landing/src/pages/landing/comoponents/QuestionsAndAnswers.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/src/pages/landing/comoponents/Roadmap.vue b/apps/landing/src/pages/landing/comoponents/Roadmap.vue deleted file mode 100644 index 4366fd451..000000000 --- a/apps/landing/src/pages/landing/comoponents/Roadmap.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/apps/landing/vite.config.ts b/apps/landing/vite.config.ts index c59bb6cae..b5198d675 100644 --- a/apps/landing/vite.config.ts +++ b/apps/landing/vite.config.ts @@ -2,29 +2,25 @@ import vue from '@vitejs/plugin-vue' import { defineConfig } from 'vite' import { fileURLToPath } from 'url' import * as path from 'path' +import Markdown from 'vite-plugin-vue-markdown' export default defineConfig({ server: { port: 3002 }, plugins: [ - vue() + vue({ + include: [/\.vue$/, /\.md$/], + }), + Markdown(), ], define: { - 'global': 'globalThis', + global: 'globalThis', }, resolve: { alias: { '@': path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'src'), './runtimeConfig': './runtimeConfig.browser', }, - extensions: [ - '.js', - '.json', - '.jsx', - '.mjs', - '.ts', - '.tsx', - '.vue', - ] + extensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx', '.vue'], }, - envPrefix: 'PUBLIC_' + envPrefix: 'PUBLIC_', }) diff --git a/apps/web/package.json b/apps/web/package.json index ca0616ad5..760881e94 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,7 @@ "d3": "^7.8.1", "ethers": "^5.7.2", "feather-icons": "^4.29.0", + "sass": "^1.69.1", "supertokens-web-js": "^0.5.0", "util": "^0.12.5", "vue": "^3.2.25", diff --git a/apps/web/src/pages/overview/Overview.vue b/apps/web/src/pages/overview/Overview.vue index f337bf03c..5cb59524c 100644 --- a/apps/web/src/pages/overview/Overview.vue +++ b/apps/web/src/pages/overview/Overview.vue @@ -11,16 +11,16 @@ import useBreakdownMetrics from '@/composables/breakdownMetrics' import useAnalytics from '@/composables/analytics' import useOperators from '@/composables/operators' -const {loadingSessionLogin} = useUser() -const {loadingInitializeBreakdownMetrics} = useBreakdownMetrics() -const {loadingInitializeAnalytics} = useAnalytics() -const {loadingInitializeOperators} = useOperators() +const { loadingSessionLogin } = useUser() +const { loadingInitializeBreakdownMetrics } = useBreakdownMetrics() +const { loadingInitializeAnalytics } = useAnalytics() +const { loadingInitializeOperators } = useOperators() const showSkeleton = ref(true) -watch([loadingSessionLogin, loadingInitializeBreakdownMetrics, loadingInitializeAnalytics, loadingInitializeOperators], () =>{ +watch([loadingSessionLogin, loadingInitializeBreakdownMetrics, loadingInitializeAnalytics, loadingInitializeOperators], () => { setTimeout(() => { - if(loadingSessionLogin || loadingInitializeBreakdownMetrics || loadingInitializeAnalytics || loadingInitializeOperators){ + if (loadingSessionLogin || loadingInitializeBreakdownMetrics || loadingInitializeAnalytics || loadingInitializeOperators) { showSkeleton.value = false } }, 500) @@ -62,13 +62,13 @@ watch([loadingSessionLogin, loadingInitializeBreakdownMetrics, loadingInitialize
-
- +
@@ -88,9 +88,9 @@ watch([loadingSessionLogin, loadingInitializeBreakdownMetrics, loadingInitialize
- +
@@ -103,20 +103,23 @@ watch([loadingSessionLogin, loadingInitializeBreakdownMetrics, loadingInitialize \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6d8d53fde..c349bc62f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,11 +28,12 @@ "eslint-plugin-vue": "^8.7.1", "esno": "^0.16.3", "ethers": "^5.7.2", - "express": "^4.18.1", "http-proxy-middleware": "^2.0.6", "husky": "^8.0.1", "lint-staged": "^13.0.0", "release-it": "^15.6.0", + "vite-plugin-md": "^0.22.5", + "vite-plugin-vue-markdown": "^0.23.8", "zx": "^7.1.1" } }, @@ -42,6 +43,8 @@ "dependencies": { "@heroicons/vue": "^1.0.6", "iconoir": "^5.3.2", + "sass": "^1.69.1", + "snarkdown": "^2.0.0", "vue": "^3.2.25", "vue-router": "^4.0.15" }, @@ -68,6 +71,7 @@ "d3": "^7.8.1", "ethers": "^5.7.2", "feather-icons": "^4.29.0", + "sass": "^1.69.1", "supertokens-web-js": "^0.5.0", "util": "^0.12.5", "vue": "^3.2.25", @@ -364,6 +368,15 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/utils": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.6.tgz", + "integrity": "sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@aws-cdk/asset-awscli-v1": { "version": "2.2.200", "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz", @@ -1746,6 +1759,10 @@ "resolved": "common/aws", "link": true }, + "node_modules/@casimir/blogs": { + "resolved": "services/blogs", + "link": true + }, "node_modules/@casimir/cdk": { "resolved": "infrastructure/cdk", "link": true @@ -3560,6 +3577,21 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdevtools/ez-spawn": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz", + "integrity": "sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "cross-spawn": "^7.0.3", + "string-argv": "^0.3.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", @@ -3697,6 +3729,54 @@ "@lit-labs/ssr-dom-shim": "^1.0.0" } }, + "node_modules/@mdit-vue/plugin-component": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-component/-/plugin-component-0.12.1.tgz", + "integrity": "sha512-L3elbvuKUufXwPLHrmJGd/ijd/QKxfcHXy3kRy4O+P7UIV7HSWePpfB0k+wWee+by3MviYYxjVAi392z+DGy3Q==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^13.0.0", + "markdown-it": "^13.0.1" + } + }, + "node_modules/@mdit-vue/plugin-component/node_modules/@types/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-Tla7hH9oeXHOlJyBFdoqV61xWE9FZf/y2g+gFVwQ2vE1/eBzjUno5JCd3Hdb5oATve5OF6xNjZ/4VIZhVVx+hA==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@mdit-vue/plugin-frontmatter": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-frontmatter/-/plugin-frontmatter-0.12.1.tgz", + "integrity": "sha512-C6ycNjrJ+T4JgbVxwo9cUkfLacOO841Yl8ogqd5PJmAVpc5cM2OLBkqqkZxNRXos3g9xM1VvIQ7gK/047UNADg==", + "dev": true, + "dependencies": { + "@mdit-vue/types": "0.12.0", + "@types/markdown-it": "^13.0.0", + "gray-matter": "^4.0.3", + "markdown-it": "^13.0.1" + } + }, + "node_modules/@mdit-vue/plugin-frontmatter/node_modules/@types/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-Tla7hH9oeXHOlJyBFdoqV61xWE9FZf/y2g+gFVwQ2vE1/eBzjUno5JCd3Hdb5oATve5OF6xNjZ/4VIZhVVx+hA==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@mdit-vue/types": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit-vue/types/-/types-0.12.0.tgz", + "integrity": "sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==", + "dev": true + }, "node_modules/@metamask/eth-sig-util": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", @@ -6218,6 +6298,15 @@ "@types/chai": "*" } }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/concat-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", @@ -6397,6 +6486,12 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==", + "dev": true + }, "node_modules/@types/localtunnel": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/localtunnel/-/localtunnel-2.0.2.tgz", @@ -6417,6 +6512,22 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.3.tgz", + "integrity": "sha512-T5k6kTXak79gwmIOaDF2UUQXFbnBE0zBUzF20pz7wDYu0RQMzWg+Ml/Pz50214NsFHBITkoi5VtdjFZnJ2ijjA==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", @@ -6442,9 +6553,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz", - "integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==" + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz", + "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==" }, "node_modules/@types/pbkdf2": { "version": "3.1.0", @@ -7491,6 +7602,60 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/@yankeeinlondon/builder-api": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@yankeeinlondon/builder-api/-/builder-api-1.4.1.tgz", + "integrity": "sha512-qc6HyfqtuS06FvA5rK0L62Nmc1LnarVOt8/V/mTX2DBZlpTfIDpudpbE/7/kxjme9pP4PFMCk7cPSrprLEorjw==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^12.2.3", + "@yankeeinlondon/happy-wrapper": "^2.10.1", + "fp-ts": "^2.13.1", + "inferred-types": "^0.37.6", + "markdown-it": "^13.0.1", + "vite-plugin-md": ">=0.22.5" + } + }, + "node_modules/@yankeeinlondon/builder-api/node_modules/fp-ts": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.1.tgz", + "integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==", + "dev": true + }, + "node_modules/@yankeeinlondon/gray-matter": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@yankeeinlondon/gray-matter/-/gray-matter-6.1.1.tgz", + "integrity": "sha512-TLtRc/mxI74ahP3s+fJpIi+lBFAhuJuVjiQhmyi/xEwJ2pDepuWMRXT6UfJOA1cGkZ5/XGa9NFw/SQR6M5jfoQ==", + "dev": true, + "dependencies": { + "inferred-types": "^0.37.6", + "js-yaml": "^4.1.0", + "kind-of": "^6.0.3", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0", + "vitest": "^0.25.8" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/@yankeeinlondon/happy-wrapper": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@yankeeinlondon/happy-wrapper/-/happy-wrapper-2.10.1.tgz", + "integrity": "sha512-kS3HT26QSQqcZa8Me2yrb6oc/j0BTmTRR76ITRGcYlO8G1snz9wii1eCrBTx+gAo58P+e3UkxB8PTVrmjTowVA==", + "dev": true, + "dependencies": { + "fp-ts": "^2.13.1", + "happy-dom": "^8.1.0", + "native-dash": "^1.24.0" + } + }, + "node_modules/@yankeeinlondon/happy-wrapper/node_modules/fp-ts": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.1.tgz", + "integrity": "sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==", + "dev": true + }, "node_modules/abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -7815,7 +7980,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -8757,7 +8921,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } @@ -9112,7 +9275,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -9120,6 +9282,33 @@ "node": ">=8" } }, + "node_modules/brilliant-errors": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/brilliant-errors/-/brilliant-errors-0.7.3.tgz", + "integrity": "sha512-WT9BkAze4SUOJfr7LUwJWNDAvynEAvUMvMPuFKu8QQKnRq+WMx3DAtHfOBJjHmHRxf748JY3CNVytSk6HH2yGg==", + "dev": true, + "dependencies": { + "bumpp": "^8.2.1", + "callsites": "^4.0.0", + "inferred-types": "^0.37.2", + "vitest": "^0.25.6" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/brilliant-errors/node_modules/callsites": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", + "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -9307,6 +9496,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bumpp": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/bumpp/-/bumpp-8.2.1.tgz", + "integrity": "sha512-4tHKsWC2mqHQvdjZ4AXgVhS2xMsz8qQ4zYt87vGRXW5tqAjrYa/UJqy7s/dGYI2OIe9ghBdiFhKpyKEX9SXffg==", + "dev": true, + "dependencies": { + "@jsdevtools/ez-spawn": "^3.0.4", + "cac": "^6.7.12", + "fast-glob": "^3.2.11", + "kleur": "^4.1.4", + "prompts": "^2.4.1", + "semver": "^7.3.5" + }, + "bin": { + "bumpp": "bin/bumpp.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/bumpp/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/bundle-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", @@ -9361,6 +9579,15 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -9400,6 +9627,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -9605,7 +9838,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -9632,7 +9864,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -10501,6 +10732,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -11663,6 +11900,18 @@ "node": ">=8.6" } }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -13716,6 +13965,18 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -13940,7 +14201,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -14209,7 +14469,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -14714,6 +14973,43 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -14746,6 +15042,30 @@ "uglify-js": "^3.1.4" } }, + "node_modules/happy-dom": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-8.9.0.tgz", + "integrity": "sha512-JZwJuGdR7ko8L61136YzmrLv7LgTh5b8XaEM3P709mLjyQuXJ3zHTDXvUtBBahRjGlcYW0zGjIiEWizoTUGKfA==", + "dev": true, + "dependencies": { + "css.escape": "^1.5.1", + "he": "^1.2.0", + "iconv-lite": "^0.6.3", + "node-fetch": "^2.x.x", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0" + } + }, + "node_modules/happy-dom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -15492,8 +15812,7 @@ "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -15566,6 +15885,15 @@ "node": ">=8" } }, + "node_modules/inferred-types": { + "version": "0.37.6", + "resolved": "https://registry.npmjs.org/inferred-types/-/inferred-types-0.37.6.tgz", + "integrity": "sha512-CfL5g1wR5rVwX2K5S6wSL+h9eODScum/LBwlhGRrcBIvfYppvUQM0aeRJ1BZS+QE38kGzd3v+U526+nQR7ZUkg==", + "dev": true, + "dependencies": { + "brilliant-errors": "^0.7.3" + } + }, "node_modules/inflation": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", @@ -15816,7 +16144,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -15963,11 +16290,19 @@ "resolved": "https://registry.npmjs.org/is-domain-name/-/is-domain-name-1.0.1.tgz", "integrity": "sha512-52ToNggHmkZGPl8yLFNrk+cKHUUnkhS0l2jh+yMLq6kj9C5IMLSztvJsW5WO5eMy0OS0jdu4o2tptT9dN0hAFg==" }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -16016,7 +16351,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -16141,7 +16475,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -17361,7 +17694,6 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -17509,6 +17841,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/lint-staged": { "version": "13.3.0", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz", @@ -17726,6 +18067,18 @@ "@types/trusted-types": "^2.0.2" } }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/localtunnel": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz", @@ -18168,6 +18521,22 @@ "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", "dev": true }, + "node_modules/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", @@ -18194,6 +18563,12 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -18760,6 +19135,16 @@ "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", "dev": true }, + "node_modules/native-dash": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/native-dash/-/native-dash-1.25.0.tgz", + "integrity": "sha512-vJy1ZEfR/9jpAtuvsbPE/PuaeaJLIS+p7tl/bKEMHutRzMHnmgLv1fSmbyVvL04s2qzg0rCKZX5yfX74uiPLyA==", + "dev": true, + "dependencies": { + "brilliant-errors": "^0.7.3", + "inferred-types": "^0.37.6" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -18958,7 +19343,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -19750,7 +20134,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -20762,7 +21145,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -21843,6 +22225,22 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sass": { + "version": "1.69.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.1.tgz", + "integrity": "sha512-nc969GvTVz38oqKgYYVHM/Iq7Yl33IILy5uqaH2CWSiSUmRCvw+UR7tA3845Sp4BD5ykCUimvrT3k1EjTwpVUA==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/sc-istanbul": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", @@ -22114,6 +22512,19 @@ "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", "dev": true }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -22449,6 +22860,11 @@ "npm": ">= 3.0.0" } }, + "node_modules/snarkdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/snarkdown/-/snarkdown-2.0.0.tgz", + "integrity": "sha512-MgL/7k/AZdXCTJiNgrO7chgDqaB9FGM/1Tvlcenenb7div6obaDATzs16JhFyHHBGodHT3B7RzRc5qk8pFhg3A==" + }, "node_modules/socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -23149,6 +23565,15 @@ "node": ">=8" } }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -23182,6 +23607,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -23836,6 +24273,30 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, + "node_modules/tinybench": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.1.tgz", + "integrity": "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.1.1.tgz", + "integrity": "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/titleize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", @@ -23879,7 +24340,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -24470,6 +24930,12 @@ "node": "*" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -24935,6 +25401,58 @@ } } }, + "node_modules/vite-plugin-md": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/vite-plugin-md/-/vite-plugin-md-0.22.5.tgz", + "integrity": "sha512-ex6yQfan2teBT2uMzoIlDHRhKTOsNiyvblA9eLU/+uygpg4KikJPFeyBX300LqQ3pZ9qGHz35qoGJ0oLw47eZg==", + "dev": true, + "dependencies": { + "@yankeeinlondon/builder-api": "^1.3.4", + "@yankeeinlondon/gray-matter": "^6.1.1", + "@yankeeinlondon/happy-wrapper": "^2.10.1", + "markdown-it": "^13.0.1", + "source-map-js": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vitejs/plugin-vue": ">=2.3.4", + "vite": "^4.0.0 || ^3.0.0" + } + }, + "node_modules/vite-plugin-vue-markdown": { + "version": "0.23.8", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-markdown/-/vite-plugin-vue-markdown-0.23.8.tgz", + "integrity": "sha512-8G/PmndrdPfsnnUMvlJWHTCtoi/LLA+pKbePkZoZni21zy+mTX/mmdZCqO95e0OOn83W2okNHu9QriQFzmGU3A==", + "deprecated": "`vite-plugin-vue-markdown` is renamed to `unplugin-vue-markdown`. For usages in Vite, you also need to change the import path to `unplugin-vue-markdown/vite`.", + "dev": true, + "dependencies": { + "@antfu/utils": "^0.7.5", + "@mdit-vue/plugin-component": "^0.12.0", + "@mdit-vue/plugin-frontmatter": "^0.12.0", + "@mdit-vue/types": "^0.12.0", + "@rollup/pluginutils": "^5.0.3", + "@types/markdown-it": "^13.0.0", + "markdown-it": "^13.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0-0 || ^4.0.0" + } + }, + "node_modules/vite-plugin-vue-markdown/node_modules/@types/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-Tla7hH9oeXHOlJyBFdoqV61xWE9FZf/y2g+gFVwQ2vE1/eBzjUno5JCd3Hdb5oATve5OF6xNjZ/4VIZhVVx+hA==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, "node_modules/vite/node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -25004,6 +25522,61 @@ "@esbuild/win32-x64": "0.18.20" } }, + "node_modules/vitest": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.25.8.tgz", + "integrity": "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "source-map": "^0.6.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "node_modules/vm2": { "version": "3.9.19", "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.19.tgz", @@ -25730,6 +26303,27 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -26484,6 +27078,21 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "services/blogs": { + "name": "@casimir/blogs", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "cors": "^2.8.5", + "express": "^4.18.2" + }, + "devDependencies": { + "@types/cors": "^2.8.14", + "@types/express": "^4.17.18", + "@types/node": "^20.8.2", + "dotenv": "^16.3.1" + } + }, "services/functions": { "name": "@casimir/functions", "dependencies": { diff --git a/package.json b/package.json index 0f7b57921..fc0bccf6b 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "dev": "npx esno -r dotenv/config scripts/root/dev.ts", "dev:ethereum": "npx esno -r dotenv/config scripts/ethereum/dev.ts", "dev:landing": "npm run dev --workspace @casimir/landing", + "dev:blogs": "npm run dev --workspace @casimir/blogs", "docgen": "npm run docgen --workspace @casimir/ethereum", "lint": "eslint --ext .vue,.ts ./ --fix", "migrations:users": "npx esno -r dotenv/config scripts/migrations/users.ts", @@ -54,11 +55,12 @@ "eslint-plugin-vue": "^8.7.1", "esno": "^0.16.3", "ethers": "^5.7.2", - "express": "^4.18.1", "http-proxy-middleware": "^2.0.6", "husky": "^8.0.1", "lint-staged": "^13.0.0", "release-it": "^15.6.0", + "vite-plugin-md": "^0.22.5", + "vite-plugin-vue-markdown": "^0.23.8", "zx": "^7.1.1" }, "lint-staged": { @@ -80,5 +82,6 @@ "hooks": { "after:bump": "npx auto-changelog -p" } - } -} + }, + "dependencies": {} +} \ No newline at end of file diff --git a/scripts/root/dev.ts b/scripts/root/dev.ts index 92e776fe4..696be382e 100644 --- a/scripts/root/dev.ts +++ b/scripts/root/dev.ts @@ -1,166 +1,218 @@ import { ethers } from 'ethers' import { loadCredentials, getSecret } from '@casimir/aws' -import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env' +import { + ETHEREUM_CONTRACTS, + ETHEREUM_NETWORK_NAME, + ETHEREUM_RPC_URL, +} from '@casimir/env' import { run, runSync } from '@casimir/shell' /** * Run an integrated development environment */ -void async function () { +void (async function () { + const services = { + users: { + port: 4000, + }, + blogs: { + port: 3003, + }, + } + + if (process.env.USE_SECRETS !== 'false') { + await loadCredentials() + process.env.BIP39_SEED = + process.env.BIP39_SEED || + ((await getSecret('consensus-networks-bip39-seed')) as string) + } else { + process.env.BIP39_SEED = + process.env.BIP39_SEED || + 'inflict ball claim confirm cereal cost note dad mix donate traffic patient' + } + + process.env.PROJECT = process.env.PROJECT || 'casimir' + process.env.STAGE = process.env.STAGE || 'local' + process.env.CRYPTO_COMPARE_API_KEY = + process.env.USE_SECRETS !== 'false' + ? process.env.CRYPTO_COMPARE_API_KEY || + (await getSecret('casimir-crypto-compare-api-key')) + : process.env.CRYPTO_COMPARE_API_KEY || '' + process.env.WALLET_CONNECT_PROJECT_ID = + process.env.USE_SECRETS !== 'false' + ? await getSecret('casimir-wallet-connect-project-id') + : '8e6877b49198d7a9f9561b8712805726' + process.env.FORK = process.env.FORK || 'testnet' + process.env.MOCK_SERVICES = process.env.MOCK_SERVICES || 'true' + process.env.BUILD_PREVIEW = process.env.BUILD_PREVIEW || 'false' + + if (process.env.BUILD_PREVIEW === 'true') { + process.env.WEB_URL = process.env.WEB_URL || 'http://localhost:4173' + } else { + process.env.WEB_URL = process.env.WEB_URL || 'http://localhost:3001' + } + + if (process.env.MOCK_SERVICES === 'true') { + for (const service of Object.keys(services)) { + const existingProcess = await run( + `lsof -i :${services[service].port} | grep LISTEN | awk '{print $2}'` + ) + if (existingProcess) { + throw new Error( + `Port ${services[service].port} is already in use by process ${existingProcess}, but is required by ${service}.` + ) + } + + process.env[ + `${service.toUpperCase()}_URL` + ] = `http://localhost:${services[service].port}` + run(`npm run dev --workspace @casimir/${service}`) + } + } + + const networkKey = + process.env.NETWORK?.toUpperCase() || + process.env.FORK?.toUpperCase() || + 'TESTNET' + process.env.SSV_NETWORK_ADDRESS = + ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS + process.env.SSV_VIEWS_ADDRESS = + ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS + process.env.SWAP_FACTORY_ADDRESS = + ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS + if (process.env.NETWORK) { + process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey] + const networkName = ETHEREUM_NETWORK_NAME[networkKey] + + console.log( + `Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}` + ) + + if (!process.env.ETHEREUM_RPC_URL) { + throw new Error(`Ethereum ${process.env.NETWORK} is not supported`) + } + + process.env.MANAGER_ADDRESS = + ETHEREUM_CONTRACTS[networkKey]?.MANAGER_ADDRESS + if (!process.env.MANAGER_ADDRESS) { + throw new Error( + `No manager address provided for ${process.env.NETWORK} ethereum network.` + ) + } - const services = { - users: { - port: 4000 - } + process.env.REGISTRY_ADDRESS = + ETHEREUM_CONTRACTS[networkKey]?.REGISTRY_ADDRESS + if (!process.env.REGISTRY_ADDRESS) { + throw new Error( + `No registry address provided for ${process.env.NETWORK} ethereum network.` + ) } - if (process.env.USE_SECRETS !== 'false') { - await loadCredentials() - process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string - } else { - process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient' + process.env.UPKEEP_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.UPKEEP_ADDRESS + if (!process.env.UPKEEP_ADDRESS) { + throw new Error( + `No upkeep address provided for ${process.env.NETWORK} ethereum network.` + ) } - process.env.PROJECT = process.env.PROJECT || 'casimir' - process.env.STAGE = process.env.STAGE || 'local' - process.env.CRYPTO_COMPARE_API_KEY = process.env.USE_SECRETS !== 'false' ? process.env.CRYPTO_COMPARE_API_KEY || await getSecret('casimir-crypto-compare-api-key') : process.env.CRYPTO_COMPARE_API_KEY || '' - process.env.WALLET_CONNECT_PROJECT_ID = process.env.USE_SECRETS !== 'false' ? await getSecret('casimir-wallet-connect-project-id') : '8e6877b49198d7a9f9561b8712805726' - process.env.FORK = process.env.FORK || 'testnet' - process.env.MOCK_SERVICES = process.env.MOCK_SERVICES || 'true' - process.env.BUILD_PREVIEW = process.env.BUILD_PREVIEW || 'false' - - if (process.env.BUILD_PREVIEW === 'true') { - process.env.WEB_URL = process.env.WEB_URL || 'http://localhost:4173' - } else { - process.env.WEB_URL = process.env.WEB_URL || 'http://localhost:3001' + process.env.VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.VIEWS_ADDRESS + if (!process.env.VIEWS_ADDRESS) { + throw new Error( + `No views address provided for ${process.env.NETWORK} ethereum network.` + ) } + } else { + process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey] + if (!process.env.ETHEREUM_FORK_RPC_URL) { + throw new Error(`Ethereum ${process.env.FORK} is not supported`) + } + + process.env.ETHEREUM_RPC_URL = 'http://127.0.0.1:8545' - if (process.env.MOCK_SERVICES === 'true') { - for (const service of Object.keys(services)) { + const provider = new ethers.providers.JsonRpcProvider( + process.env.ETHEREUM_FORK_RPC_URL + ) + process.env.ETHEREUM_FORK_BLOCK = + process.env.ETHEREUM_FORK_BLOCK || + `${(await provider.getBlockNumber()) - 5}` - const existingProcess = await run(`lsof -i :${services[service].port} | grep LISTEN | awk '{print $2}'`) - if (existingProcess) { - throw new Error(`Port ${services[service].port} is already in use by process ${existingProcess}, but is required by ${service}.`) - } + const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED) - process.env[`${service.toUpperCase()}_URL`] = `http://localhost:${services[service].port}` - run(`npm run dev --workspace @casimir/${service}`) - } + // Account for the mock, beacon, and library deployments + const walletNonce = + (await provider.getTransactionCount(wallet.address)) + 11 + + if (!process.env.MANAGER_ADDRESS) { + process.env.MANAGER_ADDRESS = ethers.utils.getContractAddress({ + from: wallet.address, + nonce: walletNonce, + }) } - const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET' - process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS - process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS - process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS - if (process.env.NETWORK) { - process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey] - const networkName = ETHEREUM_NETWORK_NAME[networkKey] - - console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`) - - if (!process.env.ETHEREUM_RPC_URL) { - throw new Error(`Ethereum ${process.env.NETWORK} is not supported`) - } - - process.env.MANAGER_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.MANAGER_ADDRESS - if (!process.env.MANAGER_ADDRESS) { - throw new Error(`No manager address provided for ${process.env.NETWORK} ethereum network.`) - } - - process.env.REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.REGISTRY_ADDRESS - if (!process.env.REGISTRY_ADDRESS) { - throw new Error(`No registry address provided for ${process.env.NETWORK} ethereum network.`) - } - - process.env.UPKEEP_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.UPKEEP_ADDRESS - if (!process.env.UPKEEP_ADDRESS) { - throw new Error(`No upkeep address provided for ${process.env.NETWORK} ethereum network.`) - } - - process.env.VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.VIEWS_ADDRESS - if (!process.env.VIEWS_ADDRESS) { - throw new Error(`No views address provided for ${process.env.NETWORK} ethereum network.`) - } - - } else { - - process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey] - if (!process.env.ETHEREUM_FORK_RPC_URL) { - throw new Error(`Ethereum ${process.env.FORK} is not supported`) - } - - process.env.ETHEREUM_RPC_URL = 'http://127.0.0.1:8545' - - const provider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL) - process.env.ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK || `${await provider.getBlockNumber() - 5}` - - const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED) - - // Account for the mock, beacon, and library deployments - const walletNonce = await provider.getTransactionCount(wallet.address) + 11 - - if (!process.env.MANAGER_ADDRESS) { - process.env.MANAGER_ADDRESS = ethers.utils.getContractAddress({ - from: wallet.address, - nonce: walletNonce - }) - } - - if (!process.env.REGISTRY_ADDRESS) { - process.env.REGISTRY_ADDRESS = ethers.utils.getContractAddress({ - from: process.env.MANAGER_ADDRESS, - nonce: 1 - }) - } - - if (!process.env.UPKEEP_ADDRESS) { - process.env.UPKEEP_ADDRESS = ethers.utils.getContractAddress({ - from: process.env.MANAGER_ADDRESS, - nonce: 2 - }) - } - - if (!process.env.VIEWS_ADDRESS) { - process.env.VIEWS_ADDRESS = ethers.utils.getContractAddress({ - from: wallet.address, - nonce: walletNonce + 1 - }) - } - - run('npm run dev:ethereum') + if (!process.env.REGISTRY_ADDRESS) { + process.env.REGISTRY_ADDRESS = ethers.utils.getContractAddress({ + from: process.env.MANAGER_ADDRESS, + nonce: 1, + }) } - process.env.PUBLIC_STAGE = process.env.STAGE - process.env.PUBLIC_USERS_URL = process.env.USERS_URL - process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL - process.env.PUBLIC_MANAGER_ADDRESS = process.env.MANAGER_ADDRESS - process.env.PUBLIC_VIEWS_ADDRESS = process.env.VIEWS_ADDRESS - process.env.PUBLIC_REGISTRY_ADDRESS = process.env.REGISTRY_ADDRESS - process.env.PUBLIC_UPKEEP_ADDRESS = process.env.UPKEEP_ADDRESS - process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS - process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS - process.env.PUBLIC_SWAP_FACTORY_ADDRESS = process.env.SWAP_FACTORY_ADDRESS - process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY - process.env.PUBLIC_ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK - process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID - - if (process.env.BUILD_PREVIEW === 'true') { - await run('npm run build --workspace @casimir/web') - run('npm run preview --workspace @casimir/web') - } else { - run('npm run dev --workspace @casimir/web') + if (!process.env.UPKEEP_ADDRESS) { + process.env.UPKEEP_ADDRESS = ethers.utils.getContractAddress({ + from: process.env.MANAGER_ADDRESS, + nonce: 2, + }) } - if (process.env.MOCK_SERVICES === 'true') { - process.on('SIGINT', () => { - const mocked: string[] = [] - if (process.env.MOCK_SERVICES === 'true') mocked.push(...Object.keys(services)) - const cleaners = mocked.map(mock => `npm run clean --workspace @casimir/${mock}`).join(' & ') - if (cleaners.length) { - console.log(`\n🧹 Cleaning up: ${mocked.map(mock => `@casimir/${mock}`).join(', ')}`) - runSync(`${cleaners}`) - } - process.exit() - }) + if (!process.env.VIEWS_ADDRESS) { + process.env.VIEWS_ADDRESS = ethers.utils.getContractAddress({ + from: wallet.address, + nonce: walletNonce + 1, + }) } -}() \ No newline at end of file + + run('npm run dev:ethereum') + } + + process.env.PUBLIC_STAGE = process.env.STAGE + process.env.PUBLIC_USERS_URL = process.env.USERS_URL + process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL + process.env.PUBLIC_MANAGER_ADDRESS = process.env.MANAGER_ADDRESS + process.env.PUBLIC_VIEWS_ADDRESS = process.env.VIEWS_ADDRESS + process.env.PUBLIC_REGISTRY_ADDRESS = process.env.REGISTRY_ADDRESS + process.env.PUBLIC_UPKEEP_ADDRESS = process.env.UPKEEP_ADDRESS + process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS + process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS + process.env.PUBLIC_SWAP_FACTORY_ADDRESS = process.env.SWAP_FACTORY_ADDRESS + process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = + process.env.CRYPTO_COMPARE_API_KEY + process.env.PUBLIC_ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK + process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = + process.env.WALLET_CONNECT_PROJECT_ID + + if (process.env.BUILD_PREVIEW === 'true') { + await run('npm run build --workspace @casimir/web') + run('npm run preview --workspace @casimir/web') + } else { + run('npm run dev --workspace @casimir/web') + } + + if (process.env.MOCK_SERVICES === 'true') { + process.on('SIGINT', () => { + const mocked: string[] = [] + if (process.env.MOCK_SERVICES === 'true') + mocked.push(...Object.keys(services)) + const cleaners = mocked + .map((mock) => `npm run clean --workspace @casimir/${mock}`) + .join(' & ') + if (cleaners.length) { + console.log( + `\n🧹 Cleaning up: ${mocked + .map((mock) => `@casimir/${mock}`) + .join(', ')}` + ) + runSync(`${cleaners}`) + } + process.exit() + }) + } +})() diff --git a/services/blogs/package.json b/services/blogs/package.json new file mode 100644 index 000000000..1a5912b04 --- /dev/null +++ b/services/blogs/package.json @@ -0,0 +1,22 @@ +{ + "name": "@casimir/blogs", + "version": "1.0.0", + "description": "Server Side Note fetching from HackMD", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "npx esno -r dotenv/config src/index.ts" + }, + "author": "Stevan Najeeb", + "license": "ISC", + "dependencies": { + "cors": "^2.8.5", + "express": "^4.18.2" + }, + "devDependencies": { + "@types/cors": "^2.8.14", + "@types/express": "^4.17.18", + "@types/node": "^20.8.2", + "dotenv": "^16.3.1" + } +} \ No newline at end of file diff --git a/services/blogs/src/index.ts b/services/blogs/src/index.ts new file mode 100644 index 000000000..6d19763a9 --- /dev/null +++ b/services/blogs/src/index.ts @@ -0,0 +1,72 @@ +import express from 'express' +import cors from 'cors' + +const app = express() +const PORT = 3003 +app.use(cors()) +app.use(express.json()) + +app.get('/api/hackmd', async (req, res) => { + const token = '4DXXJDRZGGRFTYTV1LH633U66W32PGKTKF6NPEQKPGNEO5TJXJ' + + const requestOptions = { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + } + + const response = await fetch( + 'https://api.hackmd.io/v1/teams/consensusnetworks/notes', + requestOptions + ) + + if (!response.ok) { + console.error( + `Express HackMD API Error Fetching Team Notes: ${response.status} ${response.statusText}` + ) + res.status(response.status).send('API Error') + return + } + + const data = await response.json() + + const filteredData = data.filter( + (item) => item.tags.includes('blog') && item.publishedAt + ) + + res.json(filteredData) +}) + +app.get('/api/hackmd/:id', async (req, res) => { + const token = '4DXXJDRZGGRFTYTV1LH633U66W32PGKTKF6NPEQKPGNEO5TJXJ' + const notesId = req.params.id + const requestOptions = { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + } + + const response = await fetch( + `https://api.hackmd.io/v1/teams/consensusnetworks/notes/${notesId}`, + requestOptions + ) + + if (!response.ok) { + console.error( + `Express HackMD API Error Fetching Team Note: ${response.status} ${response.statusText}` + ) + res.status(response.status).send('API Error') + return + } + + const data = await response.json() + res.json(data) +}) + +app.listen(PORT, () => { + console.log(`Express server is running on port ${PORT}`) +})