website: glossary feature (#2529)

* web: quick fixes in glossary.md

* website: update header tags

* website: add glossary feature

* website: add & style the tooltips & glossary terms

* website: add overlay for glossary definition

* website: add list styling & update links

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
M Sarmad Qadeer 2023-06-11 11:52:55 +05:00 committed by GitHub
parent 92cf945e10
commit bbd4e6c8ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 626 additions and 44 deletions

View file

@ -30,7 +30,7 @@ In a more narrow sense, particularly in media, blockchain is used to refer speci
Centralized networks are provided or controlled by a single entity. The examples are Threema, Signal, WhatsApp and Telegram. The advantage of that design is that the provider can innovate faster, and has a centralized approach to security. But the disadvantage is that the provider can change or discontinue the service, and leak, sell or disclose in some other way all users' data, including who they are connected with.
## Content padding
## Content padding
[Message padding](#message-padding).
@ -149,7 +149,7 @@ Generalizing [the definition](https://csrc.nist.gov/glossary/term/pairwise_pseud
In the context of SimpleX network, these are the identifiers generated by SMP relays to access anonymous messaging queues, with a separate identifier (and access credential) for each accessing party: recipient, sender and and optional notifications subscriber. The same approach is used by XFTP relays to access file chunks, with separate identifiers (and access credentials) for sender and each recipient.
## Peer-to-peer
## Peer-to-peer
Peer-to-peer (P2P) is the network architecture when participants have equal rights and communicate directly via a general purpose transport or overlay network. Unlike client-server architecture, all peers in a P2P network both provide and consume the resources. In the context of messaging, P2P architecture usually means that the messages are sent between peers, without user accounts or messages being stored on any servers. Examples are Tox, Briar, Cwtch and many others.

View file

@ -3,10 +3,52 @@ const markdownItAnchor = require("markdown-it-anchor")
const markdownItReplaceLink = require('markdown-it-replace-link')
const slugify = require("slugify")
const uri = require('fast-uri')
const i18n = require('eleventy-plugin-i18n');
const fs = require("fs");
const path = require("path");
const pluginRss = require('@11ty/eleventy-plugin-rss');
const i18n = require('eleventy-plugin-i18n')
const fs = require("fs")
const path = require("path")
const pluginRss = require('@11ty/eleventy-plugin-rss')
const { JSDOM } = require('jsdom')
// The implementation of Glossary feature
const md = new markdownIt()
const glossaryMarkdownContent = fs.readFileSync(path.resolve(__dirname, '../docs/GLOSSARY.md'), 'utf8')
const glossaryHtmlContent = md.render(glossaryMarkdownContent)
const glossaryDOM = new JSDOM(glossaryHtmlContent)
const glossaryDocument = glossaryDOM.window.document
const glossary = require('./src/_data/glossary.json')
glossary.forEach(item => {
const headers = Array.from(glossaryDocument.querySelectorAll("h2"))
const matchingHeader = headers.find(header => header.textContent.trim() === item.definition)
if (matchingHeader) {
let sibling = matchingHeader.nextElementSibling
let definition = ''
let firstParagraph = ''
let paragraphCount = 0
while (sibling && sibling.tagName !== 'H2') {
if (sibling.tagName === 'P') {
Array.from(sibling.getElementsByTagName('a')).forEach(a => {
if (a.getAttribute('href').startsWith('#')) {
a.setAttribute('href', '/docs/glossary.html' + a.getAttribute('href'))
}
})
paragraphCount += 1
if (firstParagraph === '') {
firstParagraph = sibling.innerHTML
}
}
definition += sibling.outerHTML || sibling.textContent
sibling = sibling.nextElementSibling
}
item.definition = definition
item.tooltip = firstParagraph
item.hasMultipleParagraphs = paragraphCount > 1
}
})
const globalConfig = {
@ -55,6 +97,82 @@ module.exports = function (ty) {
}
})
ty.addFilter('applyGlossary', function (content) {
const dom = new JSDOM(content)
const { document } = dom.window
const body = document.querySelector('body')
const allContentNodes = document.querySelectorAll('p, td, a, h1, h2, h3, h4')
glossary.forEach((term, index) => {
let changeNoted = false
const id = `glossary-${index}`
allContentNodes.forEach((node) => {
const regex = new RegExp(`(?<![/#])\\b${term.term}\\b`, 'gi')
const replacement = `<span data-glossary=${id} class="glossary-term">${term.term}</span>`
const beforeContent = node.innerHTML
node.innerHTML = node.innerHTML.replace(regex, replacement)
if (beforeContent !== node.innerHTML && !changeNoted) {
changeNoted = true
}
})
if (changeNoted) {
const definitionTooltipDiv = document.createElement('div')
definitionTooltipDiv.id = id
definitionTooltipDiv.className = "glossary-tooltip"
const titleH4 = document.createElement('h4')
titleH4.innerHTML = term.term
titleH4.className = "tooltip-title"
const p = document.createElement('p')
p.innerHTML = term.tooltip
const innerDiv = document.createElement('div')
innerDiv.appendChild(titleH4)
innerDiv.appendChild(p)
if (term.hasMultipleParagraphs) {
const readMoreBtn = document.createElement('button')
readMoreBtn.innerHTML = "Read more"
readMoreBtn.className = "read-more-btn open-overlay-btn"
readMoreBtn.setAttribute('data-show-overlay', `overlay-${id}`)
innerDiv.appendChild(readMoreBtn)
const overlayDiv = document.createElement('div')
overlayDiv.id = `overlay-${id}`
overlayDiv.className = "overlay glossary-overlay hidden"
const overlayCardDiv = document.createElement('div')
overlayCardDiv.className = "overlay-card"
const overlayTitleH1 = document.createElement('h1')
overlayTitleH1.className = "overlay-title"
overlayTitleH1.innerHTML = term.term
const overlayContent = document.createElement('div')
overlayContent.className = "overlay-content"
overlayContent.innerHTML = term.definition
const crossSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg")
crossSVG.setAttribute('class', 'close-overlay-btn')
crossSVG.setAttribute('id', 'cross')
crossSVG.setAttribute('width', '16')
crossSVG.setAttribute('height', '16')
crossSVG.setAttribute('viewBox', '0 0 13 13')
crossSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
const crossPath = document.createElementNS("http://www.w3.org/2000/svg", "path")
crossPath.setAttribute('d', 'M12.7973 11.5525L7.59762 6.49833L12.7947 1.44675C13.055 1.19371 13.0658 0.771991 12.8188 0.505331C12.5718 0.238674 12.1602 0.227644 11.8999 0.480681L6.65343 5.58028L1.09979 0.182228C0.805 0.002228 0.430001 0.002228 0.135211 0.182228C-0.159579 0.362228 -0.159579 0.697228 0.135211 0.877228L5.68885 6.27528L0.4918 11.3295C0.231501 11.5825 0.220703 12.0042 0.467664 12.2709C0.714625 12.5376 1.12625 12.5486 1.38655 12.2956L6.63302 7.196L12.1867 12.5941C12.4815 12.7741 12.8565 12.7741 13.1513 12.5941C13.4461 12.4141 13.4461 12.0791 13.1513 11.8991L12.7973 11.5525Z')
crossSVG.appendChild(crossPath)
overlayCardDiv.appendChild(overlayTitleH1)
overlayCardDiv.appendChild(overlayContent)
overlayCardDiv.appendChild(crossSVG)
overlayDiv.appendChild(overlayCardDiv)
body.appendChild(overlayDiv)
}
innerDiv.className = "tooltip-content"
definitionTooltipDiv.appendChild(innerDiv)
body.appendChild(definitionTooltipDiv)
}
})
return dom.serialize()
})
ty.addShortcode("completeRoute", (obj) => {
const urlParts = obj.url.split("/")
@ -88,7 +206,7 @@ module.exports = function (ty) {
}
})
ty.addPlugin(pluginRss);
ty.addPlugin(pluginRss)
ty.addPlugin(i18n, {
translations,

View file

@ -29,6 +29,9 @@
},
"dependencies": {
"eleventy-plugin-i18n": "^0.1.3",
"gray-matter": "^4.0.3"
"fs": "^0.0.1-security",
"gray-matter": "^4.0.3",
"jsdom": "^22.1.0",
"markdown-it": "^13.0.1"
}
}

View file

@ -0,0 +1,110 @@
[
{
"term": "Address portability",
"definition": "Address portability"
},
{
"term": "Anonymous credentials",
"definition": "Anonymous credentials"
},
{
"term": "Blockchain",
"definition": "Blockchain"
},
{
"term": "Break-in recovery",
"definition": "Post-compromise security"
},
{
"term": "Centralized network",
"definition": "Centralized network"
},
{
"term": "Content padding",
"definition": "Message padding"
},
{
"term": "Decentralized network",
"definition": "Decentralized network"
},
{
"term": "Defense in depth",
"definition": "Defense in depth"
},
{
"term": "Double ratchet algorithm",
"definition": "Double ratchet algorithm"
},
{
"term": "End-to-end encryption",
"definition": "End-to-end encryption"
},
{
"term": "Federated network",
"definition": "Federated network"
},
{
"term": "Forward secrecy",
"definition": "Forward secrecy"
},
{
"term": "Key agreement protocol",
"definition": "Key agreement protocol"
},
{
"term": "Key exchange",
"definition": "Key agreement protocol"
},
{
"term": "Man-in-the-middle attack",
"definition": "Man-in-the-middle attack"
},
{
"term": "Merkle directed acyclic graph",
"definition": "Merkle directed acyclic graph"
},
{
"term": "Message padding",
"definition": "Message padding"
},
{
"term": "Onion routing",
"definition": "Onion routing"
},
{
"term": "Overlay network",
"definition": "Overlay network"
},
{
"term": "Pairwise pseudonymous identifier",
"definition": "Pairwise pseudonymous identifier"
},
{
"term": "Peer-to-peer",
"definition": "Peer-to-peer"
},
{
"term": "Perfect forward secrecy",
"definition": "Forward secrecy"
},
{
"term": "Post-compromise security",
"definition": "Post-compromise security"
},
{
"term": "Post-quantum cryptography",
"definition": "Post-quantum cryptography"
},
{
"term": "Proxied peer-to-peer",
"definition": "Proxied peer-to-peer"
},
{
"term": "Recovery from compromise",
"definition": "Post-compromise security"
},
{
"term": "User identity",
"definition": "User identity"
}
]

View file

@ -22,7 +22,7 @@
{% endif %}
</div>
<svg class="fill-grey-black dark:fill-white fixed right-5 top-5 cursor-pointer close-overlay-btn" id="cross" width="16" height="16" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg">
<svg class="close-overlay-btn" id="cross" width="16" height="16" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg">
<path d="M12.7973 11.5525L7.59762 6.49833L12.7947 1.44675C13.055 1.19371 13.0658 0.771991 12.8188 0.505331C12.5718 0.238674 12.1602 0.227644 11.8999 0.480681L6.65343 5.58028L1.09979 0.182228C0.839522 -0.070157 0.427909 -0.059127 0.18094 0.207531C-0.0660305 0.474191 -0.0552645 0.895911 0.205003 1.14894L5.70862 6.49833L0.20247 11.851C-0.0577975 12.104 -0.0685635 12.5257 0.178407 12.7924C0.306324 12.9306 0.477936 13 0.650181 13C0.811033 13 0.971873 12.9397 1.09726 12.817L6.65343 7.41639L11.9025 12.5186C12.0285 12.6406 12.1893 12.7015 12.3495 12.7015C12.5218 12.7015 12.6934 12.6321 12.8213 12.4939C13.0689 12.2273 13.0582 11.8062 12.7973 11.5525Z"/>
</svg>
</div>

View file

@ -7,8 +7,8 @@
<section class="hidden xl:block h-screen pt-[66px] bg-white dark:bg-gradient-radial-mobile dark:lg:bg-gradient-radial">
<div class="container m-auto h-full flex items-center justify-between px-5">
<div class="flex flex-col items-start justify-center w-full h-full">
<p class="text-[38px] leading-[43px] font-bold max-w-[500px] mb-[30px] primary-header-contact">{{ header | i18n({}, lang ) | safe }}</p>
<p class="text-[20px] leading-[28px] text-[#606C71] dark:text-white font-bold max-w-[475px] mb-[80px] secondary-header-contact">{{ "contact-hero-subheader" | i18n({}, lang ) | safe }}</p>
<h1 class="text-[38px] leading-[43px] font-bold max-w-[500px] mb-[30px] primary-header-contact">{{ header | i18n({}, lang ) | safe }}</h1>
<h2 class="text-[20px] leading-[28px] text-[#606C71] dark:text-white font-bold max-w-[475px] mb-[80px] secondary-header-contact">{{ "contact-hero-subheader" | i18n({}, lang ) | safe }}</h2>
<p class="text-grey-black dark:text-white text-base mb-[16px]">
{{ "contact-hero-p-1" | i18n({}, lang ) | safe }}
</p>
@ -43,7 +43,7 @@
<section class="block xl:hidden pt-[106px] pb-[90px] bg-white dark:bg-gradient-radial-mobile dark:lg:bg-gradient-radial">
<div class="container m-auto h-full px-5">
<div class="flex flex-col items-center">
<p class="text-[28px] font-bold text-center max-w-[602px] mb-[40px] primary-header-contact">{{ header | i18n({}, lang ) | safe }}</p>
<h1 class="text-[28px] font-bold text-center max-w-[602px] mb-[40px] primary-header-contact">{{ header | i18n({}, lang ) | safe }}</h1>
<p class="text-[20px] leading-[28px] text-grey-black dark:text-white font-medium mb-[30px]">{{ "to-make-a-connection" | i18n({}, lang ) | safe }}</p>
<div class="flex flex-col justify-center items-center p-4 w-full max-w-[468px] min-h-[131px] rounded-[30px] border-[1px] border-[#A8B0B4] dark:border-white border-opacity-60 mb-6 relative">
@ -88,7 +88,7 @@
<div class="hidden md:block xl:hidden for-tablet">
<div class="contact-tab">
<div class="flex items-center justify-between my-[40px] contact-tab-btn cursor-pointer">
<p class="text-xl font-bold">{{ "scan-the-qr-code-with-the-simplex-chat-app" | i18n({}, lang ) | safe }}</p>
<h2 class="text-xl font-bold">{{ "scan-the-qr-code-with-the-simplex-chat-app" | i18n({}, lang ) | safe }}</h2>
<svg class="fill-grey-black dark:fill-white" width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.40813 4.79332C8.69689 5.06889 9.16507 5.06889 9.45384 4.79332C9.7426 4.51775 9.7426 4.07097 9.45384 3.7954L5.69327 0.206676C5.65717 0.17223 5.61827 0.142089 5.57727 0.116255C5.29026 -0.064587 4.90023 -0.0344467 4.64756 0.206676L0.886983 3.7954C0.598219 4.07097 0.598219 4.51775 0.886983 4.79332C1.17575 5.06889 1.64393 5.06889 1.93269 4.79332L5.17041 1.70356L8.40813 4.79332Z"/>
</svg>
@ -108,7 +108,7 @@
<div class="hidden xl:block">
<div class="contact-tab">
<div class="flex items-center justify-between my-[40px] contact-tab-btn cursor-pointer">
<p class="text-xl font-bold">{{ "installing-simplex-chat-to-terminal" | i18n({}, lang ) | safe }}</p>
<h2 class="text-xl font-bold">{{ "installing-simplex-chat-to-terminal" | i18n({}, lang ) | safe }}</h2>
<svg class="fill-grey-black dark:fill-white" width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.40813 4.79332C8.69689 5.06889 9.16507 5.06889 9.45384 4.79332C9.7426 4.51775 9.7426 4.07097 9.45384 3.7954L5.69327 0.206676C5.65717 0.17223 5.61827 0.142089 5.57727 0.116255C5.29026 -0.064587 4.90023 -0.0344467 4.64756 0.206676L0.886983 3.7954C0.598219 4.07097 0.598219 4.51775 0.886983 4.79332C1.17575 5.06889 1.64393 5.06889 1.93269 4.79332L5.17041 1.70356L8.40813 4.79332Z"/>
</svg>
@ -139,7 +139,7 @@
<div class="contact-tab">
<div class="flex items-center justify-between my-[40px] contact-tab-btn cursor-pointer">
<p class="text-xl font-bold">{{ "if-you-already-installed-simplex-chat-for-the-terminal" | i18n({}, lang ) | safe }}</p>
<h2 class="text-xl font-bold">{{ "if-you-already-installed-simplex-chat-for-the-terminal" | i18n({}, lang ) | safe }}</h2>
<svg class="fill-grey-black dark:fill-white" width="10" height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.40813 4.79332C8.69689 5.06889 9.16507 5.06889 9.45384 4.79332C9.7426 4.51775 9.7426 4.07097 9.45384 3.7954L5.69327 0.206676C5.65717 0.17223 5.61827 0.142089 5.57727 0.116255C5.29026 -0.064587 4.90023 -0.0344467 4.64756 0.206676L0.886983 3.7954C0.598219 4.07097 0.598219 4.51775 0.886983 4.79332C1.17575 5.06889 1.64393 5.06889 1.93269 4.79332L5.17041 1.70356L8.40813 4.79332Z"/>
</svg>

View file

@ -7,8 +7,8 @@
<img class="static-phone-mobile md:hidden" src="/img/new/mobile-hero.png" alt="" />
<article class="w-full xl:max-w-[600px] landing-page-header-article">
<p class="primary-header text-center xl:text-left xl:rtl:text-right font-bold text-[38px] md:text-[55px] leading-[46px] md:leading-[63px] mb-2 xl:mb-8">{{ "hero-header" | i18n({}, lang ) | safe }}</p>
<p class="secondary-header text-center xl:text-left xl:rtl:text-right font-bold text-[28px] md:text-[38px] leading-[36px] md:leading-[43px] mb-2 xl:mb-8 tracking-[0.01em]">{{ "hero-subheader" | i18n({}, lang ) | safe }}</p>
<h1 class="primary-header text-center xl:text-left xl:rtl:text-right font-bold text-[38px] md:text-[55px] leading-[46px] md:leading-[63px] mb-2 xl:mb-8">{{ "hero-header" | i18n({}, lang ) | safe }}</h1>
<h2 class="secondary-header text-center xl:text-left xl:rtl:text-right font-bold text-[28px] md:text-[38px] leading-[36px] md:leading-[43px] mb-2 xl:mb-8 tracking-[0.01em]">{{ "hero-subheader" | i18n({}, lang ) | safe }}</h2>
<p class="landing-page-header-article-paragraph text-black dark:text-white text-center xl:text-justify text-[16px] leading-[24px] mb-[20px] header-description">
{{ "hero-p-1" | i18n({}, lang ) | safe }}
</p>
@ -87,9 +87,9 @@
</div>
<article class="w-full xl:max-w-[600px] landing-page-header-article px-5">
<p class="text-active-blue text-center xl:text-left xl:rtl:text-right font-bold text-[28px] md:text-[35px] leading-[36px] md:leading-[43px] mb-[28px]">
<h2 class="text-active-blue text-center xl:text-left xl:rtl:text-right font-bold text-[28px] md:text-[35px] leading-[36px] md:leading-[43px] mb-[28px]">
{{ "hero-2-header" | i18n({}, lang ) | safe }}
</p>
</h2>
<p class="text-center text-black dark:text-white xl:text-justify leading-[24px] text-[16px] mb-10 xl:mb-[25px] header-description">
{{ "hero-2-header-desc" | i18n({}, lang ) | safe }}
</p>

View file

@ -38,7 +38,7 @@
{% include "navbar.html" %}
</section>
{{ content | safe }}
{{ content | applyGlossary | safe }}
{% include "footer.html" %}

View file

@ -1,7 +1,7 @@
{# join simplex #}
<section id="join-simplex" class="bg-primary-bg-light dark:bg-primary-bg-dark lg:h-[855px] py-[90px] px-5">
<div class="container flex flex-col items-center">
<p class="text-[38px] leading-[36px] md:leading-[55px] text-grey-black dark:text-white text-center font-bold mb-5"><span class="text-active-blue">{{ "join" | i18n({}, lang ) | safe }}</span> SimpleX</p>
<h2 class="text-[38px] leading-[36px] md:leading-[55px] text-grey-black dark:text-white text-center font-bold mb-5"><span class="text-active-blue">{{ "join" | i18n({}, lang ) | safe }}</span> SimpleX</h2>
<p class="text-black dark:text-white text-base text-center mb-14">{{ "we-invite-you-to-join-the-conversation" | i18n({}, lang ) | safe }}</p>
<div class="flex flex-col items-center gap-5 self-stretch mb-12">

View file

@ -1,6 +1,6 @@
<section id="why-simplex" class="bg-primary-bg-light dark:bg-primary-bg-dark py-[90px] overflow-hidden px-0 sm:px-1 xl:h-[888px]">
<div class="container scale-100">
<p class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-14 px-5 sm:px-4">{{ "why-simplex-is" | i18n({}, lang ) | safe }} <span class="gradient-text">{{ "unique" | i18n({}, lang ) | safe }}</span></p>
<h2 class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-14 px-5 sm:px-4">{{ "why-simplex-is" | i18n({}, lang ) | safe }} <span class="gradient-text">{{ "unique" | i18n({}, lang ) | safe }}</span></h2>
<div class="swiper unique-swiper px-5 sm:px-4 py-2">
<div class="swiper-wrapper mb-16">
@ -15,8 +15,8 @@
<div class="card-content absolute md:static px-4 md:px-0 bottom-[80px] right-1 left-1 h-[180px] md:h-fit pt-5 lg:pt-0 bg-primary-bg-light dark:bg-primary-bg-dark">
<div class="content-head">
<p class="text-[35px] lg:text-[65px] font-bold tracking-[0.06em] text-active-blue text-center md:text-left md:rtl:text-right">#{{ section.id }}</p>
<p class="w-full max-w-[617px] text-[25px] leading-[33px] lg:text-[35px] lg:leading-[45px] text-center md:text-left md:rtl:text-right font-bold text-grey-black dark:text-white">{{ section.title | i18n({}, lang ) | safe }}</p>
<h1 class="text-[35px] lg:text-[65px] font-bold tracking-[0.06em] text-active-blue text-center md:text-left md:rtl:text-right">#{{ section.id }}</h1>
<h3 class="w-full max-w-[617px] text-[25px] leading-[33px] lg:text-[35px] lg:leading-[45px] text-center md:text-left md:rtl:text-right font-bold text-grey-black dark:text-white">{{ section.title | i18n({}, lang ) | safe }}</h3>
</div>
<div class="content-body py-5 md:py-7">

View file

@ -25,7 +25,7 @@
<section id="simplex-explained" class="bg-primary-bg-light dark:bg-primary-bg-dark lg:h-[890px] py-[90px] px-5">
<div class="container">
<p class="text-[35px] leading-[45px] md:leading-[55px] lg:text-[38px] text-center font-bold text-grey-black dark:text-white mb-9">{{ "simplex-explained" | i18n({}, lang ) | safe }}</p>
<h2 class="text-[35px] leading-[45px] md:leading-[55px] lg:text-[38px] text-center font-bold text-grey-black dark:text-white mb-9">{{ "simplex-explained" | i18n({}, lang ) | safe }}</h2>
<!-- Tab links -->
<div class="tabs hidden md:flex gap-2 mb-24">

View file

@ -35,7 +35,7 @@ active_blog: true
<section class="py-10 px-5 mt-[66px]" id="blog-list">
<div class="container">
<p class="text-[38px] text-center font-bold text-active-blue mb-9">Latest news</p>
<h1 class="text-[38px] text-center font-bold text-active-blue mb-9">Latest news</h1>
{% for blog in collections.blogs %}
{% if not(blog.data.draft) %}

View file

@ -428,13 +428,13 @@ header nav {
transform: translateY(40px);
}
.card:not(.no-hover):hover > div:nth-child(1) {
.card:not(.no-hover):hover > div:nth-child(1),
.card.hovered > div:nth-child(1) {
height: 200px;
padding: 12px 10px;
}
.card:not(.no-hover):hover > div:nth-child(2) {
.card:not(.no-hover):hover > div:nth-child(2),
.card.hovered > div:nth-child(2) {
height: 270px;
padding: 8px 24px;
}
.card.card-active > div:nth-child(2) {
height: 480px;
@ -443,13 +443,16 @@ header nav {
.card:not(.no-hover):hover > div:nth-child(2) > *:nth-child(2),
.card:not(.no-hover):hover > div:nth-child(2) > *:nth-child(3),
.card.card-active > div:nth-child(2) > *:nth-child(2),
.card.card-active > div:nth-child(2) > *:nth-child(3) {
.card.card-active > div:nth-child(2) > *:nth-child(3),
.card:not(.no-hover).hovered > div:nth-child(2) > *:nth-child(2),
.card:not(.no-hover).hovered > div:nth-child(2) > *:nth-child(3) {
opacity: 1;
max-height: 480px;
transform: translateY(0px);
}
.card:not(.no-hover):hover > div:nth-child(2) > *:nth-child(3){
.card:not(.no-hover):hover > div:nth-child(2) > *:nth-child(3),
.card:not(.no-hover).hovered > div:nth-child(2) > *:nth-child(3) {
opacity: 0;
}
@ -710,4 +713,227 @@ p a{
.contact-tab.active svg,
.contact-tab:hover svg{
transform: rotate(0deg);
}
/* Glossary */
.glossary-term{
display: inline-block;
text-decoration: underline;
text-decoration-style: dashed;
text-underline-offset: 3px;
position: relative;
z-index: 10000;
}
.glossary-term::before{
content: '';
position: absolute;
top: -5px;
bottom: -5px;
left: 0;
right: 0;
opacity: 0;
z-index: 9;
}
.glossary-tooltip {
visibility: hidden;
opacity: 0;
position: fixed;
width: 320px;
max-width: 100%;
z-index: 10001;
transition: opacity .5s;
padding-left: 5px;
padding-right: 5px;
}
.glossary-tooltip .tooltip-content{
background-color: #fff;
color: #000;
text-align: left;
padding: .8rem 1.2rem;
border-radius: 7px;
font-size: 14px;
line-height: 1.3rem;
box-shadow: 0 5px 10px rgba(0,0,0,.08);
}
.dark .glossary-tooltip .tooltip-content{
background-color: #000;
color: #fff;
box-shadow: none;
}
.tooltip-title{
margin-bottom: 0.5rem;
color: #0197FF;
font-weight: 600;
font-size: 1.1rem;
}
.dark .tooltip-title{
color: #70F0F9;
}
.glossary-tooltip .read-more-btn{
color: #0053D0;
display: block;
text-decoration: underline;
margin-top: .8rem;
text-underline-offset: 2px;
}
.dark .glossary-tooltip .read-more-btn{
color: #70F0F9;
}
.glossary-overlay{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: transparent;
align-items: center;
justify-content: center;
padding: 0.75rem;
z-index: 10005;
}
@media screen and (min-width: 768px) {
.glossary-overlay{
padding: 2.5rem;
}
}
.glossary-overlay::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background-color:#F3F6F7;
opacity: 0.9;
}
.dark .glossary-overlay::before {
content: '';
background-color: #0C0B13;
}
.glossary-overlay .overlay-card{
width: 100%;
background-color: white;
opacity: 1;
height: 100%;
z-index: 10006;
border-radius: 0.375rem;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.2);
padding: 2.5rem 1.5rem;
overflow: auto;
--tw-scale-x: 1;
--tw-scale-y: 1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.dark .glossary-overlay .overlay-card{
background-color: #17203D;
}
@media (min-width: 640px) {
.glossary-overlay .overlay-card{
padding: 3.5rem;
}
}
@media (min-width: 768px) {
.glossary-overlay .overlay-card{
width: fit-content;
max-width: 558px;
height: fit-content;
max-height: 660px;
}
}
.glossary-overlay .overlay-card .overlay-title{
font-size: 1.875rem;
line-height: 2.25rem;
font-weight: 700;
margin-bottom: 1rem;
margin-bottom: 1.5rem;
--tw-text-opacity: 1;
color: rgb(1 151 255 / var(--tw-text-opacity));
}
.glossary-overlay .overlay-card .overlay-content{
display: flex;
flex-direction: column;
gap: 1.5rem;
font-size: 1rem;
line-height: 1.5rem;
color: #3F484B;
}
.dark .glossary-overlay .overlay-card .overlay-content{
color: #fff;
}
.close-overlay-btn{
fill: #3F484B;
position: fixed;
right: 1.25rem;
top: 1.25rem;
cursor: pointer;
}
.dark .close-overlay-btn{
fill: #fff;
}
.glossary-overlay ul {
overflow-x: auto;
}
.glossary-overlay ul,
.glossary-overlay ol {
list-style-position: inside;
overflow: auto;
margin: 1rem 0;
/* padding-left: 1rem; */
}
.glossary-overlay ul li,
.glossary-overlay ol li {
margin-right: 0;
margin-left: 0;
-webkit-margin-start: 1.1rem;
color: #000;
}
.dark .glossary-overlay ul li,
.dark .glossary-overlay ol li {
color: #fff;
}
.glossary-overlay ul li::marker,
.glossary-overlay ol li::marker {
color: black;
}
.dark .glossary-overlay ul li::marker,
.dark .glossary-overlay ol li::marker {
color: white;
}
.glossary-overlay ul li a,
.glossary-overlay ol li a {
line-height: 30px;
}
.glossary-overlay ul li {
list-style: disc;
}
.glossary-overlay ol li {
list-style: decimal;
}

View file

@ -11,7 +11,7 @@ active_home: true
<section id="why-privacy" class="bg-secondary-bg-light dark:bg-secondary-bg-dark py-[90px] px-5 lg:h-[888px]">
<div class="container">
<p class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-4 md:mb-8">{{ "privacy-matters-section-header" | i18n({}, lang ) | safe }}</p>
<h2 class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-4 md:mb-8">{{ "privacy-matters-section-header" | i18n({}, lang ) | safe }}</h2>
<p class="text-center text-[18px] md:text-[20px] font-medium mb-7 md:mb-16 lg:mb-20 text-black dark:text-white">{{ "privacy-matters-section-subheader" | i18n({}, lang ) | safe }}</p>
<div class="flex flex-col lg:flex-row gap-[20px] mb-[62px] lg:mb-[90px]">
@ -41,7 +41,7 @@ active_home: true
{# Features #}
<section id="features" class="bg-secondary-bg-light dark:bg-secondary-bg-dark py-[95px] px-5 lg:h-[888px]">
<div class="container">
<p class="text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold gradient-text mb-20">{{ "features" | i18n({}, lang ) | safe }}</p>
<h2 class="text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold gradient-text mb-20">{{ "features" | i18n({}, lang ) | safe }}</h2>
<div class="mb-[50px] grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-x-10 gap-y-32">
{% for feature in features.sections %}
@ -60,7 +60,7 @@ active_home: true
{# what makes simplex private #}
<section id="privacy" class="bg-primary-bg-light dark:bg-primary-bg-dark py-[90px] overflow-hidden px-5 lg:h-[888px]">
<div class="container scale-100">
<p class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-20">{{ "simplex-private-section-header" | i18n({}, lang ) | safe }}</p>
<h2 class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-20">{{ "simplex-private-section-header" | i18n({}, lang ) | safe }}</h2>
<div class="swiper private-swiper overflow-hidden px-4 py-2">
<div class="swiper-wrapper mb-16">
@ -71,8 +71,8 @@ active_home: true
<img class="w-full max-w-[223px] h-full max-h-[226px] dark:hidden" src="{{ section.imgLight }}" alt=""/>
<img class="w-full max-w-[223px] h-full max-h-[226px] hidden dark:block" src="{{ section.imgDark }}" alt=""/>
</div>
<div class="flex flex-col items-center justify-between h-[138px] absolute bottom-0 py-6 px-6 bg-card-desc-bg-light dark:bg-card-desc-bg-dark rounded-b-[20px]">
<p class="text-grey-black dark:text-white text-[18px] my-4 font-bold leading-[26px] tracking-[0.01em] text-center">{{ section.title | i18n({}, lang ) | safe }}</p>
<div class="card-content flex flex-col items-center justify-between h-[138px] absolute bottom-0 py-6 px-6 bg-card-desc-bg-light dark:bg-card-desc-bg-dark rounded-b-[20px]">
<h3 class="text-grey-black dark:text-white text-[18px] my-4 font-bold leading-[26px] tracking-[0.01em] text-center">{{ section.title | i18n({}, lang ) | safe }}</h3>
<div class="flex-1 py-3 flex flex-col gap-3">
{% for point in section.points %}
<p class="text-grey-black dark:text-white text-[14px] text-center">{{ point | i18n({}, lang ) | safe }}</p>
@ -102,7 +102,7 @@ active_home: true
{# Network #}
<section id="network" class="bg-secondary-bg-light dark:bg-secondary-bg-dark lg:h-[642px] py-[95px] px-5">
<div class="container">
<p class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-5">{{ "simplex-network-section-header" | i18n({}, lang ) | safe }}</p>
<h2 class="text-grey-black dark:text-white text-[35px] leading-[45px] md:leading-[55px] lg:text-[45px] text-center font-bold mb-5">{{ "simplex-network-section-header" | i18n({}, lang ) | safe }}</h2>
<p class="text-black dark:text-white text-[16px] font-normal text-center mb-16">{{ "simplex-network-section-desc" | i18n({}, lang ) | safe }}</p>
<div class="flex flex-col lg:flex-row justify-between gap-12 md:gap-14 lg:gap-16">
@ -112,7 +112,7 @@ active_home: true
<img src="/img/new/network-1-dark.svg" alt="" class="hidden dark:block"/>
</div>
<div class="md:flex-[2] flex flex-col items-center justify-center">
<p class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-1-header" | i18n({}, lang ) | safe }}</p>
<h3 class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-1-header" | i18n({}, lang ) | safe }}</h3>
<p class="text-black dark:text-white text-base font-normal text-center md:text-left lg:text-center">
{{ "simplex-network-1-desc" | i18n({}, lang ) | safe }} <a href="javascript:void(0)" data-show-overlay="{{ simplex_network_overlay.sections[0].overlayContent.overlayId }}" class="open-overlay-btn">{{ "simplex-network-1-overlay-linktext" | i18n({}, lang ) | safe }}</a>.
{{ overlay(simplex_network_overlay.sections[0],lang) }}
@ -128,7 +128,7 @@ active_home: true
<img src="/img/new/network-2-dark.svg" alt="" class="hidden dark:block"/>
</div>
<div class="md:flex-[2] flex flex-col items-center justify-center">
<p class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-2-header" | i18n({}, lang ) | safe }}</p>
<h3 class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-2-header" | i18n({}, lang ) | safe }}</h3>
<p class="text-black dark:text-white text-base font-normal text-center md:text-left lg:text-center">
{{ "simplex-network-2-desc" | i18n({}, lang ) | safe }}
</p>
@ -143,7 +143,7 @@ active_home: true
<img src="/img/new/network-3-dark.svg" alt="" class="hidden dark:block"/>
</div>
<div class="md:flex-[2] flex flex-col items-center justify-center">
<p class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-3-header" | i18n({}, lang ) | safe }}</p>
<h3 class="text-active-blue text-xl font-bold text-center md:text-left lg:text-center self-stretch">{{ "simplex-network-3-header" | i18n({}, lang ) | safe }}</h3>
<p class="text-black dark:text-white text-base font-normal text-center md:text-left lg:text-center">
{{ "simplex-network-3-desc" | i18n({}, lang ) | safe }}
</p>
@ -163,7 +163,7 @@ active_home: true
{# Comparison #}
<section id="comparison" class="bg-secondary-bg-light dark:bg-secondary-bg-dark lg:h-[950px] py-[90px] px-5">
<div class="text-grey-black dark:text-white container flex flex-col">
<p class="text-[35px] leading-[43px] md:leading-[55px] lg:leading-[36px] text-center font-bold mb-12 lg:mb-[90px]">{{ "comparison-section-header" | i18n({}, lang ) | safe }}</p>
<h2 class="text-[35px] leading-[43px] md:leading-[55px] lg:leading-[36px] text-center font-bold mb-12 lg:mb-[90px]">{{ "comparison-section-header" | i18n({}, lang ) | safe }}</h2>
<div class="w-full overflow-auto">
<table class="w-full border-separate border-spacing-x-5 border-spacing-y-2 mb-14">

View file

@ -65,6 +65,19 @@ const privateSwiper = new Swiper('.private-swiper', {
allowTouchMove: true,
}
},
on: {
slideChange: function () {
const privateSwiperGlossaryTerms = document.querySelectorAll('.private-swiper .glossary-term');
privateSwiperGlossaryTerms.forEach(function (glossaryTerm) {
var tooltipId = glossaryTerm.getAttribute('data-glossary');
var tooltip = document.getElementById(tooltipId);
tooltip.style.visibility = 'hidden';
tooltip.style.opacity = '0';
const privateSwiper = glossaryTerm.closest('.private-swiper')
if (privateSwiper) glossaryTerm.closest('.card').classList.remove('hovered');
})
}
}
});
const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", {
@ -86,6 +99,17 @@ const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", {
pagination: {
el: ".simplex-explained-swiper-pagination",
clickable: true
},
on: {
slideChange: function () {
const explainedSwiperGlossaryTerms = document.querySelectorAll('.simplex-explained-swiper .glossary-term');
explainedSwiperGlossaryTerms.forEach(function (glossaryTerm) {
var tooltipId = glossaryTerm.getAttribute('data-glossary');
var tooltip = document.getElementById(tooltipId);
tooltip.style.visibility = 'hidden';
tooltip.style.opacity = '0';
})
}
}
});
@ -170,5 +194,106 @@ function openOverlay() {
}
}
window.addEventListener('load', openOverlay);
window.addEventListener('hashchange', openOverlay);
function updatePointerEventsInPrivateSwiperCards() {
var privateSwiperCards = document.querySelectorAll('.private-swiper .card')
privateSwiperCards.forEach(function (card) {
var cardContent = card.querySelector('.card-content')
function updatePointerEvents() {
var cardContentGlossaryTerms = cardContent.querySelectorAll('.glossary-term')
cardContentGlossaryTerms.forEach(function (glossaryTerm) {
if (cardContent.offsetHeight >= 270) {
glossaryTerm.style.pointerEvents = 'all'
} else {
glossaryTerm.style.pointerEvents = 'none'
}
})
}
updatePointerEvents()
cardContent.addEventListener('click', updatePointerEvents)
cardContent.addEventListener('mousemove', updatePointerEvents)
})
}
function updateTooltipPosition(glossaryTerm, tooltip) {
var glossaryTermOffset = glossaryTerm.getBoundingClientRect()
var tooltipOffset = tooltip.getBoundingClientRect()
if (glossaryTermOffset.top >= tooltipOffset.height) {
tooltip.style.top = glossaryTermOffset.top - tooltipOffset.height + 'px'
} else {
tooltip.style.top = glossaryTermOffset.bottom + 'px'
}
var leftPosition = glossaryTermOffset.left + glossaryTerm.offsetWidth / 2 - tooltip.offsetWidth / 2
if (leftPosition < 0) {
tooltip.style.left = '0px'
} else if (leftPosition + tooltip.offsetWidth > window.innerWidth) {
tooltip.style.left = window.innerWidth - tooltip.offsetWidth + 'px'
} else {
tooltip.style.left = leftPosition + 'px'
}
}
function setupTooltip(glossaryTerm) {
var tooltipId = glossaryTerm.getAttribute('data-glossary')
var tooltip = document.getElementById(tooltipId)
function showTooltip() {
tooltip.style.visibility = 'visible'
tooltip.style.opacity = '1'
updateTooltipPosition(glossaryTerm, tooltip)
const privateSwiper = glossaryTerm.closest('.private-swiper')
if (privateSwiper) glossaryTerm.closest('.card').classList.add('hovered')
}
function hideTooltip() {
tooltip.style.visibility = 'hidden'
tooltip.style.opacity = '0'
const privateSwiper = glossaryTerm.closest('.private-swiper')
if (privateSwiper) glossaryTerm.closest('.card').classList.remove('hovered')
}
let click = 0
glossaryTerm.addEventListener('mouseover', showTooltip)
glossaryTerm.addEventListener('mouseout', function (event) {
click = 0
if (event.relatedTarget !== tooltip) {
hideTooltip()
}
})
glossaryTerm.addEventListener('click', function (event) {
event.stopPropagation()
if (click == 1) {
hideTooltip()
click = 0
}
else {
showTooltip()
click = 1
}
})
tooltip.addEventListener('mouseover', showTooltip)
tooltip.addEventListener('mouseout', hideTooltip)
}
window.addEventListener('load', () => {
openOverlay()
updatePointerEventsInPrivateSwiperCards()
const glossaryTerms = document.querySelectorAll('.glossary-term')
window.addEventListener('scroll', function () {
glossaryTerms.forEach(function (glossaryTerm) {
var tooltipId = glossaryTerm.getAttribute('data-glossary')
var tooltip = document.getElementById(tooltipId)
updateTooltipPosition(glossaryTerm, tooltip)
})
})
glossaryTerms.forEach(setupTooltip)
})
window.addEventListener('hashchange', openOverlay)