diff --git a/ar/contact/index.html b/ar/contact/index.html index 5b3a91b6ce..8c4ebd14f9 100644 --- a/ar/contact/index.html +++ b/ar/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - بروتوكول دردشة SimpleX + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + بروتوكول دردشة SimpleX + + - الشروط وسياسة الخصوصية + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + الشروط وسياسة الخصوصية + + - تبرع + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + تبرع + +
- طرفية CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + طرفية CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/ar/index.html b/ar/index.html index 1cdc84b1d4..cd9b8dc975 100644 --- a/ar/index.html +++ b/ar/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - بروتوكول دردشة SimpleX + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + بروتوكول دردشة SimpleX + + - الشروط وسياسة الخصوصية + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + الشروط وسياسة الخصوصية + + - تبرع + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + تبرع + +
- طرفية CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + طرفية CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/ar/invitation/index.html b/ar/invitation/index.html index ea22b45a7a..29df3a1fcb 100644 --- a/ar/invitation/index.html +++ b/ar/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - بروتوكول دردشة SimpleX + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + بروتوكول دردشة SimpleX + + - الشروط وسياسة الخصوصية + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + الشروط وسياسة الخصوصية + + - تبرع + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + تبرع + +
- طرفية CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + طرفية CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/blog/20201022-simplex-chat.html b/blog/20201022-simplex-chat.html index f9b261a83d..165ff9b91e 100644 --- a/blog/20201022-simplex-chat.html +++ b/blog/20201022-simplex-chat.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -272,30 +351,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -338,6 +429,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20210512-simplex-chat-terminal-ui.html b/blog/20210512-simplex-chat-terminal-ui.html index b6567fddde..4827f1eeed 100644 --- a/blog/20210512-simplex-chat-terminal-ui.html +++ b/blog/20210512-simplex-chat-terminal-ui.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -280,30 +359,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -346,6 +437,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20210914-simplex-chat-v0.4-released.html b/blog/20210914-simplex-chat-v0.4-released.html index 33aec69863..9ae16e41ac 100644 --- a/blog/20210914-simplex-chat-v0.4-released.html +++ b/blog/20210914-simplex-chat-v0.4-released.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -284,30 +363,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -350,6 +441,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20211208-simplex-chat-v0.5-released.html b/blog/20211208-simplex-chat-v0.5-released.html index 37eab1b272..66db018471 100644 --- a/blog/20211208-simplex-chat-v0.5-released.html +++ b/blog/20211208-simplex-chat-v0.5-released.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -279,30 +358,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -345,6 +436,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220112-simplex-chat-v1-released.html b/blog/20220112-simplex-chat-v1-released.html index 686ecb29c1..c5fa6c939a 100644 --- a/blog/20220112-simplex-chat-v1-released.html +++ b/blog/20220112-simplex-chat-v1-released.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -293,30 +372,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -359,6 +450,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220214-simplex-chat-ios-public-beta.html b/blog/20220214-simplex-chat-ios-public-beta.html index 45ac1c9b08..cecfea15d6 100644 --- a/blog/20220214-simplex-chat-ios-public-beta.html +++ b/blog/20220214-simplex-chat-ios-public-beta.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -291,30 +370,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -357,6 +448,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220308-simplex-chat-mobile-apps.html b/blog/20220308-simplex-chat-mobile-apps.html index 31fff4b799..810b648ae0 100644 --- a/blog/20220308-simplex-chat-mobile-apps.html +++ b/blog/20220308-simplex-chat-mobile-apps.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -309,30 +388,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -375,6 +466,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220404-simplex-chat-instant-notifications.html b/blog/20220404-simplex-chat-instant-notifications.html index 9e9bef62cc..06efc49fba 100644 --- a/blog/20220404-simplex-chat-instant-notifications.html +++ b/blog/20220404-simplex-chat-instant-notifications.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -350,30 +429,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -416,6 +507,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220511-simplex-chat-v2-images-files.html b/blog/20220511-simplex-chat-v2-images-files.html index f51d14cabc..2c2d30550f 100644 --- a/blog/20220511-simplex-chat-v2-images-files.html +++ b/blog/20220511-simplex-chat-v2-images-files.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -285,30 +364,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -351,6 +442,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220524-simplex-chat-better-privacy.html b/blog/20220524-simplex-chat-better-privacy.html index 5f374535c4..a9cae31156 100644 --- a/blog/20220524-simplex-chat-better-privacy.html +++ b/blog/20220524-simplex-chat-better-privacy.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -272,30 +351,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -338,6 +429,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220604-simplex-chat-new-privacy-security-settings.html b/blog/20220604-simplex-chat-new-privacy-security-settings.html index 6687bf8fd2..67a7732452 100644 --- a/blog/20220604-simplex-chat-new-privacy-security-settings.html +++ b/blog/20220604-simplex-chat-new-privacy-security-settings.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -290,30 +369,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -356,6 +447,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.html b/blog/20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.html index c7fbe5a7b1..0f8e15fad3 100644 --- a/blog/20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.html +++ b/blog/20220711-simplex-chat-v3-released-ios-notifications-audio-video-calls-database-export-import-protocol-improvements.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -324,30 +403,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -390,6 +481,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220723-simplex-chat-v3.1-tor-groups-efficiency.html b/blog/20220723-simplex-chat-v3.1-tor-groups-efficiency.html index 36169f7ee6..0b8f8af9a5 100644 --- a/blog/20220723-simplex-chat-v3.1-tor-groups-efficiency.html +++ b/blog/20220723-simplex-chat-v3.1-tor-groups-efficiency.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -340,30 +419,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -406,6 +497,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220808-simplex-chat-v3.1-chat-groups.html b/blog/20220808-simplex-chat-v3.1-chat-groups.html index 1887416ce6..1128a90cbe 100644 --- a/blog/20220808-simplex-chat-v3.1-chat-groups.html +++ b/blog/20220808-simplex-chat-v3.1-chat-groups.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -339,30 +418,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -405,6 +496,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220901-simplex-chat-v3.2-incognito-mode.html b/blog/20220901-simplex-chat-v3.2-incognito-mode.html index 9225cb1997..6f40185e7a 100644 --- a/blog/20220901-simplex-chat-v3.2-incognito-mode.html +++ b/blog/20220901-simplex-chat-v3.2-incognito-mode.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -330,30 +409,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -396,6 +487,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20220928-simplex-chat-v4-encrypted-database.html b/blog/20220928-simplex-chat-v4-encrypted-database.html index c9b5b5ab09..501ae336e8 100644 --- a/blog/20220928-simplex-chat-v4-encrypted-database.html +++ b/blog/20220928-simplex-chat-v4-encrypted-database.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -353,30 +432,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -419,6 +510,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html b/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html index 34951741de..56621b6e62 100644 --- a/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html +++ b/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -383,30 +462,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -449,6 +540,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20221206-simplex-chat-v4.3-voice-messages.html b/blog/20221206-simplex-chat-v4.3-voice-messages.html index 05102fcb31..fdb4e1e0bc 100644 --- a/blog/20221206-simplex-chat-v4.3-voice-messages.html +++ b/blog/20221206-simplex-chat-v4.3-voice-messages.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -347,30 +426,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -413,6 +504,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20230103-simplex-chat-v4.4-disappearing-messages.html b/blog/20230103-simplex-chat-v4.4-disappearing-messages.html index 147cec1a13..3fefd84b17 100644 --- a/blog/20230103-simplex-chat-v4.4-disappearing-messages.html +++ b/blog/20230103-simplex-chat-v4.4-disappearing-messages.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -318,30 +397,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -384,6 +475,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html b/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html index aab9e87d5d..31970456b3 100644 --- a/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html +++ b/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -333,30 +412,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -399,6 +490,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20230301-simplex-file-transfer-protocol.html b/blog/20230301-simplex-file-transfer-protocol.html index ff9ae1e11d..3f56382018 100644 --- a/blog/20230301-simplex-file-transfer-protocol.html +++ b/blog/20230301-simplex-file-transfer-protocol.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -364,30 +443,42 @@ file ---> | XFTP | ------> XFTP ----> | Rela
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -430,6 +521,7 @@ file ---> | XFTP | ------> XFTP ----> | Rela
+ diff --git a/blog/20230328-simplex-chat-v4-6-hidden-profiles.html b/blog/20230328-simplex-chat-v4-6-hidden-profiles.html index 094629c508..63cdae1c5a 100644 --- a/blog/20230328-simplex-chat-v4-6-hidden-profiles.html +++ b/blog/20230328-simplex-chat-v4-6-hidden-profiles.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -328,30 +407,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -394,6 +485,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html index adda342a2f..00b66766ae 100644 --- a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html +++ b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html @@ -43,12 +43,41 @@ + -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -56,11 +85,11 @@
-
+ +
@@ -337,30 +416,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
@@ -403,6 +494,7 @@ window.addEventListener('scroll',changeHeaderBg);
+ diff --git a/blog/index.html b/blog/index.html index 7df074a0e2..03d1dd6dbe 100644 --- a/blog/index.html +++ b/blog/index.html @@ -52,7 +52,35 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -60,11 +88,11 @@
-
+ +
@@ -1086,30 +1164,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/contact/index.html b/contact/index.html index d3832368dc..31e9af37d9 100644 --- a/contact/index.html +++ b/contact/index.html @@ -52,7 +52,35 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -60,11 +88,11 @@
-
+ +
@@ -604,30 +684,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/cs/contact/index.html b/cs/contact/index.html index d3113a5d73..3c70d95543 100644 --- a/cs/contact/index.html +++ b/cs/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protokol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protokol + + - Podmínky a zásady ochrany osobních údajů + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Podmínky a zásady ochrany osobních údajů + + - Darovat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darovat + +
- Terminálové rozhraní příkazového řádku + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminálové rozhraní příkazového řádku + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/cs/index.html b/cs/index.html index 6b38cf64e0..fdbf7290d3 100644 --- a/cs/index.html +++ b/cs/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protokol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protokol + + - Podmínky a zásady ochrany osobních údajů + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Podmínky a zásady ochrany osobních údajů + + - Darovat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darovat + +
- Terminálové rozhraní příkazového řádku + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminálové rozhraní příkazového řádku + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/cs/invitation/index.html b/cs/invitation/index.html index 54948ba953..8f714bef6a 100644 --- a/cs/invitation/index.html +++ b/cs/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protokol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protokol + + - Podmínky a zásady ochrany osobních údajů + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Podmínky a zásady ochrany osobních údajů + + - Darovat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darovat + +
- Terminálové rozhraní příkazového řádku + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminálové rozhraní příkazového řádku + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/css/doc.css b/css/doc.css new file mode 100644 index 0000000000..002d6bae0f --- /dev/null +++ b/css/doc.css @@ -0,0 +1,412 @@ +html { + scroll-behavior: smooth; +} + +header { + transition: none; +} + +:focus { + outline: none; +} + +#doc { + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +#doc code, +#doc kbd, +#doc pre, +#doc samp { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; + overflow-x: auto; + overflow-y: hidden; +} + +#doc p { + margin: 0 0 16px; + gap: 2px; + flex-wrap: wrap; + align-items: center; +} + +.dark #doc p { + color: white; +} + +#doc h1 { + font-size: 32px; + font-weight: 700; + letter-spacing: 0.02em; + background: -webkit-linear-gradient(to bottom, #53C1FF -50%, #0053D0 160%); + background: linear-gradient(to bottom, #53C1FF -50%, #0053D0 160%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; + + position: relative; + margin: 0px 0px 16px; + padding: 0px 0px 9.6px; +} + +#doc h2 { + font-size: 24px; + font-weight: 700; + color: #3F484B; + position: relative; + margin: 24px 0px 16px; + padding: 0 0 7.2px; +} + +#doc h3 { + font-size: 20px; + font-weight: 700; + letter-spacing: 0.02em; + color: #606C71; + margin: 24px 0px 16px; +} + +#doc h1::after, +#doc h2::after { + content: ''; + position: absolute; + left: 0; + bottom: 0px; + width: 100%; + height: 1px; + background-color: rgb(216, 222, 228); +} + +.dark #doc h1::after, +.dark #doc h2::after { + background-color: transparent; +} + +.dark #doc h1 { + background: -webkit-linear-gradient(to bottom, #70F0F9 100%, #70F0F9 100%); + background: linear-gradient(to bottom, #70F0F9 100%, #70F0F9 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; +} + +.dark #doc h2, +.dark #doc h3, +.dark #doc h4 { + color: white; +} + +#doc img { + max-width: 100%; +} + +#doc article ul { + overflow-x: auto; +} + +#doc ul, +#doc ol { + list-style-position: inside; + overflow: auto; + margin: 1rem 0; + padding-left: 1rem; +} + +#doc ul li, +#doc ol li { + margin-right: 0; + margin-left: 0; + -webkit-margin-start: 1.1rem; + color: #000; +} + +.dark #doc ul li, +.dark #doc ol li { + color: #fff; +} + +#doc ul li::marker, +#doc ol li::marker { + color: black; +} + +.dark #doc ul li::marker, +.dark #doc ol li::marker { + color: white; +} + +#doc ul li a, +#doc ol li a { + line-height: 30px; +} + +#doc ul li { + list-style: disc; +} + +#doc ol li { + list-style: decimal; +} + +#doc a { + color: #0053D0; + text-decoration: underline; + text-underline-offset: 4px; +} + +#doc h1 a { + -webkit-text-fill-color: #0053D0; + text-fill-color: #0053D0; +} + +.dark #doc a { + color: #70F0F9; +} + +.dark #doc h1 a { + -webkit-text-fill-color: #70F0F9; + text-fill-color: #70F0F9; +} + +#doc pre { + overflow: auto; +} + +.dark #doc pre { + color: white; +} + +#doc table { + display: block; + border-collapse: collapse; + width: max-content; + max-width: 100%; + overflow: auto; + margin-bottom: 1rem; + border: 1px solid #e1e4e8; +} + +#doc table th, +#doc table td { + border: 1px solid #e1e4e8; + padding: 6px 13px; +} + +#doc table td a { + display: inline-block; +} + +#doc table th { + font-weight: 600; + background-color: #f6f8fa; + text-align: left; +} + +#doc table tbody tr:nth-child(odd) { + background-color: #ffffff; +} + +#doc table tbody tr:nth-child(even) { + background-color: #fafbfc; +} + +.dark #doc table tr, +.dark #doc table th { + color: white; + background-color: transparent !important; +} + +#doc main { + display: flex; +} + +#doc main aside { + width: 320px; + height: calc(100vh - 66px); + position: sticky; + top: 66px; + overflow-y: auto; + background-color: #fff; +} + +.dark #doc main aside { + background-color: #17203D; +} + +#doc main aside ul { + margin: 0; + padding: 0; +} + +#doc main aside ul li { + list-style: none; + margin: 0; +} + +#doc main aside ul li a { + font-size: 14px; + display: block; + color: rgb(60, 60, 60); + text-decoration: none; +} + +#doc main aside ul li a:hover { + color: #000; +} + +.dark #doc main aside ul li a:hover { + color: #fff; +} + +#doc main aside ul li a.active { + color: #0053D0; +} + +.dark #doc main aside ul li a.active { + color: #70F0F9; +} + +#doc main aside p { + margin: 0; + font-weight: 700; + letter-spacing: .8px; + margin-top: 1.2rem; + margin-bottom: .4rem; +} + +#doc main article { + width: calc(100vw - 320px); +} + +@media (max-width: 1024px) { + #doc main aside { + position: fixed; + top: 0; + left: 0; + height: 100vh; + z-index: 100; + transition: all ease .3s; + transform: translateX(-100%); + } + + #doc main.overlay aside { + transform: translateX(0); + } + + #doc main.overlay::after { + content: ""; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #F3F6F7; + opacity: 0.9; + z-index: 99; + } + + .dark #doc main.overlay::after { + background-color: #0C0B13; + } + + #doc main article { + width: 100%; + } +} + +#doc article>div { + max-width: 870px; + margin: 0 auto; + padding: 16px 32px 32px 32px; +} + +@media (max-width: 1024px) { + #doc article>div { + max-width: 600px; + padding-left: 0; + padding-right: 0; + } +} + +#doc .hash-link { + opacity: 0; + font-size: 1.5rem; + text-decoration: none !important; + position: absolute; + left: -16px; + top: 0; + transition: all ease .3s; +} + +#doc h1 a.hash-link { + top: 6px; +} + +#doc h1:hover .hash-link, +#doc h2:hover .hash-link, +#doc h3:hover .hash-link, +#doc h4:hover .hash-link, +#doc h5:hover .hash-link, +#doc h6:hover .hash-link, +#doc .hash-link:hover { + opacity: 1; +} + +#doc .hash-link:hover { + text-decoration: underline !important; +} + +#doc .hash-list { + padding: 1.5rem 2rem !important; +} + +#doc .hash-list li { + list-style: none !important; + width: 100%; + -webkit-margin-start: 0 !important; +} + +#doc .hash-list li a { + text-decoration: none !important; + color: #000 !important; +} + +.dark #doc .hash-list li a { + color: #fff !important; +} + +@media (max-width: 1024px) { + #doc .sub-menu.hash-list { + max-height: fit-content; + } +} + +#doc #back-to-top { + color: #0053D0 !important; + position: relative; + display: block; + width: 100%; +} + +.dark #doc #back-to-top { + color: #70F0F9 !important; +} + +#doc #back-to-top::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: -12px; + height: 1px; + background-color: rgb(216, 222, 228); +} + +.dark #doc #back-to-top::after { + opacity: 0.2; +} \ No newline at end of file diff --git a/css/prism.min.css b/css/prism.min.css new file mode 100644 index 0000000000..d6fbb50ad0 --- /dev/null +++ b/css/prism.min.css @@ -0,0 +1,4 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+csharp+cpp+css-extras+dart+docker+ejs+git+linker-script+gradle+haskell+http+java+javadoclike+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+kotlin+makefile+markdown+markup-templating+n1ql+nginx+plsql+powerquery+powershell+python+sql+swift+typescript+typoscript+xml-doc+xquery+yaml&plugins=normalize-whitespace+toolbar+copy-to-clipboard */ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} +div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none} diff --git a/css/style.css b/css/style.css index 83fd1a3eb2..2360044a9f 100644 --- a/css/style.css +++ b/css/style.css @@ -39,6 +39,13 @@ html { letter-spacing: 0.003em; } +img{ + user-select: none; + -webkit-user-select: none; /* For Safari and older Chrome versions */ + -moz-user-select: none; /* For Firefox */ + -ms-user-select: none; /* For Internet Explorer and Edge */ +} + /* #comparison::before { display: block; content: " "; @@ -175,6 +182,14 @@ html { color: #fff; } +.nav-link ul li a.active{ + color: #0053D0; + +} +.dark .nav-link ul li a.active{ + color: #66D9E2; +} + @media (min-width:1024px) { .nav-link-text, .menu-link { @@ -222,8 +237,13 @@ html { color: #505158; } -.dark .sub-menu { - color: #fff; +.sub-menu .no-hover{ + color: #505158 !important; +} + +.dark .sub-menu, +.dark .sub-menu .no-hover { + color: #fff !important; } .dark .sub-menu li:hover { @@ -275,7 +295,7 @@ header nav { } .active .sub-menu { - max-height: 200px; + max-height: 600px; transform: translateY(0px); opacity: 1; visibility: visible; diff --git a/css/tailwind.css b/css/tailwind.css index 7ee25bc1f7..385e944e08 100644 --- a/css/tailwind.css +++ b/css/tailwind.css @@ -574,8 +574,8 @@ video { position: sticky; } -.-right-14 { - right: -3.5rem; +.-left-10 { + left: -2.5rem; } .bottom-0 { @@ -658,10 +658,23 @@ video { z-index: 10001; } +.z-\[49\] { + z-index: 49; +} + +.float-right { + float: right; +} + .m-auto { margin: auto; } +.\!my-4 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + .mx-5 { margin-left: 1.25rem; margin-right: 1.25rem; @@ -875,6 +888,10 @@ video { display: inline-block; } +.inline { + display: inline; +} + .flex { display: flex; } @@ -919,6 +936,10 @@ video { height: 180px; } +.h-\[1px\] { + height: 1px; +} + .h-\[215px\] { height: 215px; } @@ -1020,6 +1041,10 @@ video { min-height: inherit; } +.w-4 { + width: 1rem; +} + .w-8 { width: 2rem; } @@ -1060,11 +1085,6 @@ video { width: 100%; } -.w-max { - width: -moz-max-content; - width: max-content; -} - .min-w-\[152px\] { min-width: 152px; } @@ -1077,10 +1097,6 @@ video { min-width: 180px; } -.min-w-\[200px\] { - min-width: 200px; -} - .min-w-\[210px\] { min-width: 210px; } @@ -1503,6 +1519,15 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-yellow-200 { + --tw-bg-opacity: 1; + background-color: rgb(254 240 138 / var(--tw-bg-opacity)); +} + +.fill-\[rgb\(60\2c 60\2c 60\)\] { + fill: rgb(60,60,60); +} + .fill-black { fill: #0D0E12; } @@ -1535,6 +1560,11 @@ video { padding: 1.5rem; } +.\!py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + .px-0 { padding-left: 0px; padding-right: 0px; @@ -1565,6 +1595,11 @@ video { padding-right: 2rem; } +.px-\[20px\] { + padding-left: 20px; + padding-right: 20px; +} + .px-\[34px\] { padding-left: 34px; padding-right: 34px; @@ -1760,6 +1795,14 @@ video { font-weight: 400; } +.capitalize { + text-transform: capitalize; +} + +.italic { + font-style: italic; +} + .leading-6 { line-height: 1.5rem; } @@ -1824,6 +1867,16 @@ video { letter-spacing: 0.06em; } +.\!text-\[rgb\(60\2c 60\2c 60\)\] { + --tw-text-opacity: 1 !important; + color: rgb(60 60 60 / var(--tw-text-opacity)) !important; +} + +.\!text-primary-pressed-light { + --tw-text-opacity: 1 !important; + color: rgb(64 122 210 / var(--tw-text-opacity)) !important; +} + .text-\[\#606C71\] { --tw-text-opacity: 1; color: rgb(96 108 113 / var(--tw-text-opacity)); @@ -1868,6 +1921,10 @@ video { text-decoration-line: underline; } +.\!no-underline { + text-decoration-line: none !important; +} + .no-underline { text-decoration-line: none; } @@ -2073,6 +2130,10 @@ video { display: inline-block; } +:is(.dark .dark\:flex) { + display: flex; +} + :is(.dark .dark\:\!hidden) { display: none !important; } @@ -2187,6 +2248,11 @@ video { fill: #fff; } +:is(.dark .dark\:\!text-white) { + --tw-text-opacity: 1 !important; + color: rgb(255 255 255 / var(--tw-text-opacity)) !important; +} + :is(.dark .dark\:text-\[\#70F0F9\]) { --tw-text-opacity: 1; color: rgb(112 240 249 / var(--tw-text-opacity)); @@ -2510,6 +2576,10 @@ video { display: none; } + .lg\:h-0 { + height: 0px; + } + .lg\:h-\[642px\] { height: 642px; } diff --git a/de/contact/index.html b/de/contact/index.html index 06819d5158..4fac6a487c 100644 --- a/de/contact/index.html +++ b/de/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat Protokoll + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat Protokoll + + - Bedingungen & Datenschutzbestimmungen + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Bedingungen & Datenschutzbestimmungen + + - Spenden + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Spenden + +
- Terminal Kommandozeilen-Schnittstelle + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal Kommandozeilen-Schnittstelle + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/de/index.html b/de/index.html index fdef6922ca..4229e08fc0 100644 --- a/de/index.html +++ b/de/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat Protokoll + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat Protokoll + + - Bedingungen & Datenschutzbestimmungen + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Bedingungen & Datenschutzbestimmungen + + - Spenden + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Spenden + +
- Terminal Kommandozeilen-Schnittstelle + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal Kommandozeilen-Schnittstelle + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/de/invitation/index.html b/de/invitation/index.html index 7a7e9ebf4d..261c1207ea 100644 --- a/de/invitation/index.html +++ b/de/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat Protokoll + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat Protokoll + + - Bedingungen & Datenschutzbestimmungen + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Bedingungen & Datenschutzbestimmungen + + - Spenden + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Spenden + +
- Terminal Kommandozeilen-Schnittstelle + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal Kommandozeilen-Schnittstelle + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/docs/android.html b/docs/android.html new file mode 100644 index 0000000000..d1e9697f4d --- /dev/null +++ b/docs/android.html @@ -0,0 +1,829 @@ + + + + + + + + + Accessing files in Android app + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 07.02.2023 | EN, CZ, FR |

+

Accessing files in Android app

+

SimpleX uses databases and stores its preferences inside private data directory in Android. The directory contains:

+
    +
  • databases
  • +
  • sent and received files
  • +
  • temporary files that will be deleted when not needed
  • +
  • user preferences.
  • +
+

If you want to view what's stored inside SimpleX data directory you need to have:

+
    +
  • Unix-based operating system (or MinGW on Windows)
  • +
  • ADB (Android Debug Bridge) tool installed on a computer (download it here and install)
  • +
  • your device connected via USB or Wi-Fi to the computer.
  • +
+

The process:

+
    +
  • open SimpleX, go to Database passphrase & export, enable App data backup. This will make other steps working
  • +
  • optional: if you want to view database contents, change database passphrase from random to yours. To do this, stop a chat in Database passphrase & export screen, open Database passphrase, enter new passphrase and confirm it, then update it. Do not forget it, otherwise you'll lose all your data in case passphrase will be asked again later
  • +
  • open a terminal emulator (Windows CMD/Powershell will not work) and change directory to the one you want to use for storing the backup:
  • +
+
cd /tmp  # just an example
+
+

Then run the following:

+
adb -d backup -f chat.ab -noapk chat.simplex.app && 
+tail -n +5 chat.ab > chat.dat && 
+printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - chat.dat > chat.gz && 
+tar -xvzf chat.gz
+
+

Now unlock the device and confirm a backup operation without using a password for encryption, otherwise the commands will not work.

+

After that the backup should be ended. If you see an error saying tar: Error is not recoverable: exiting now but before that you have printed some file names, don't worry, it's ok.

+

Now the backed-up files will be inside ./apps/chat.simplex.app/.

+

Please, note, that if you use a modern version of SimpleX, the databases will be encrypted, and you'll not be able to view contents of them without using sqlcipher application and without knowing decryption passphrase (you need to change it to yours from randomly generated in the app firstly).

+

Please, follow SQL.md guide for more info of how to decrypt your databases and to make queries to them.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/cli.html b/docs/cli.html new file mode 100644 index 0000000000..0226230b06 --- /dev/null +++ b/docs/cli.html @@ -0,0 +1,972 @@ + + + + + + + + + Terminal CLI + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 31.01.2023 | Languages: EN, FR, CZ |

+

SimpleX Chat terminal (console) app for Linux/MacOS/Windows

+

Table of contents

+ +

Terminal chat features

+
    +
  • 1-to-1 chat with multiple people in the same terminal window.
  • +
  • Group messaging.
  • +
  • Sending files to contacts and groups.
  • +
  • User contact addresses - establish connections via multiple-use contact links.
  • +
  • Messages persisted in a local SQLite database.
  • +
  • Auto-populated recipient name - just type your messages to reply to the sender once the connection is established.
  • +
  • Demo SMP servers available and pre-configured in the app - or you can deploy your own server.
  • +
  • No global identity or any names visible to the server(s), ensuring full privacy of your contacts and conversations.
  • +
  • Two layers of E2E encryption (double-ratchet for duplex connections, using X3DH key agreement with ephemeral Curve448 keys, and NaCl crypto_box for SMP queues, using Curve25519 keys) and out-of-band passing of recipient keys (see How to use SimpleX chat).
  • +
  • Message integrity validation (via including the digests of the previous messages).
  • +
  • Authentication of each command/message by SMP servers with automatically generated Ed448 keys.
  • +
  • TLS 1.3 transport encryption.
  • +
  • Additional encryption of messages from SMP server to recipient to reduce traffic correlation.
  • +
+

Public keys involved in key exchange are not used as identity, they are randomly generated for each contact.

+

See Encryption Primitives Used for technical details.

+

+

🚀 Installation

+

Download chat client

+

Linux and MacOS

+

To install or update simplex-chat, you should run the install script. To do that, use the following cURL or Wget command:

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+
wget -qO- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+

Once the chat client downloads, you can run it with simplex-chat command in your terminal.

+

Alternatively, you can manually download the chat binary for your system from the latest stable release and make it executable as shown below.

+
chmod +x <binary>
+mv <binary> ~/.local/bin/simplex-chat
+
+

(or any other preferred location on PATH).

+

On MacOS you also need to allow Gatekeeper to run it.

+

Windows

+
move <binary> %APPDATA%/local/bin/simplex-chat.exe
+
+

Build from source

+
+

Please note: to build the app use source code from stable branch.

+
+

Using Docker

+

On Linux, you can build the chat executable using docker build with custom output:

+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+DOCKER_BUILDKIT=1 docker build --output ~/.local/bin .
+
+
+

Please note: If you encounter version `GLIBC_2.28' not found error, rebuild it with haskell:8.10.7-stretch base image (change it in your local Dockerfile).

+
+

In any OS

+
    +
  1. Install Haskell GHCup, GHC 8.10.7 and cabal:
  2. +
+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
+
+
    +
  1. Build the project:
  2. +
+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+# on Linux
+apt-get update && apt-get install -y build-essential libgmp3-dev zlib1g-dev
+cp scripts/cabal.project.local.linux cabal.project.local
+# or on MacOS:
+# brew install openssl@1.1
+# cp scripts/cabal.project.local.mac cabal.project.local
+# you may need to amend cabal.project.local to point to the actual openssl location
+cabal update
+cabal install
+
+

Usage

+

Running the chat client

+

To start the chat client, run simplex-chat from the terminal.

+

By default, app data directory is created in the home directory (~/.simplex, or %APPDATA%/simplex on Windows), and two SQLite database files simplex_v1_chat.db and simplex_v1_agent.db are initialized in it.

+

To specify a different file path prefix for the database files use -d command line option:

+
$ simplex-chat -d alice
+
+

Running above, for example, would create alice_v1_chat.db and alice_v1_agent.db database files in current directory.

+

Three default SMP servers are hosted on Linode - they are pre-configured in the app.

+

If you deployed your own SMP server(s) you can configure client via -s option:

+
$ simplex-chat -s smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@smp.example.com
+
+

Base64url encoded string preceding the server address is the server's offline certificate fingerprint which is validated by client during TLS handshake.

+

You can still talk to people using default or any other server - it only affects the location of the message queue when you initiate the connection (and the reply queue can be on another server, as set by the other party's client).

+

Run simplex-chat -h to see all available options.

+

Access messaging servers via Tor

+

Install Tor and run it as SOCKS5 proxy on port 9050, e.g. on Mac you can:

+
brew install tor
+brew services start tor
+
+

Use -x option to access servers via Tor:

+
simplex-chat -x
+
+

You can also use option --socks-proxy=ipv4:port or --socks-proxy=:port to configure host and port of your SOCKS5 proxy, e.g. if you are running it on some other host or port.

+

How to use SimpleX chat

+

Once you have started the chat, you will be prompted to specify your "display name" and an optional "full name" to create a local chat profile. Your display name is an alias for your contacts to refer to you by - it is not unique and does not serve as a global identity. If some of your contacts chose the same display name, the chat client adds a numeric suffix to their local display name.

+

The diagram below shows how to connect and message a contact:

+
+ +
+

Once you've set up your local profile, enter /c (for /connect) to create a new connection and generate an invitation. Send this invitation to your contact via any other channel.

+

You are able to create multiple invitations by entering /connect multiple times and sending these invitations to the corresponding contacts you'd like to connect with.

+

The invitation can only be used once and even if this is intercepted, the attacker would not be able to use it to send you the messages via this queue once your contact confirms that the connection is established. See agent protocol for explanation of invitation format.

+

The contact who received the invitation should enter /c <invitation> to accept the connection. This establishes the connection, and both parties are notified.

+

They would then use @<name> <message> commands to send messages. You may also just start typing a message to send it to the contact that was the last.

+

Use /help in chat to see the list of available commands.

+

Groups

+

To create a group use /g <group>, then add contacts to it with /a <group> <name>. You can then send messages to the group by entering #<group> <message>. Use /help groups for other commands.

+

simplex-chat

+
+

Please note: the groups are not stored on any server, they are maintained as a list of members in the app database to whom the messages will be sent.

+
+

Sending files

+

You can send a file to your contact with /f @<contact> <file_path> - the recipient will have to accept it before it is sent. Use /help files for other commands.

+

simplex-chat

+

You can send files to a group with /f #<group> <file_path>.

+

User contact addresses

+

As an alternative to one-time invitation links, you can create a long-term address with /ad (for /address). The created address can then be shared via any channel, and used by other users as a link to make a contact request with /c <user_contact_address>.

+

You can accept or reject incoming requests with /ac <name> and /rc <name> commands.

+

User address is "long-term" in a sense that it is a multiple-use connection link - it can be used until it is deleted by the user, in which case all established connections would still remain active (unlike how it works with email, when changing the address results in people not being able to message you).

+

Use /help address for other commands.

+

simplex-chat

+

Access chat history

+

SimpleX chat stores all your contacts and conversations in a local SQLite database, making it private and portable by design, owned and controlled by user.

+

You can view and search your chat history by querying your database. Run the below script to create message views in your database.

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/scripts/message_views.sql | sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

Open SQLite Command Line Shell:

+
sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

See Message queries for examples.

+
+

Please note: SQLite foreign key constraints are disabled by default, and must be enabled separately for each database connection. The latter can be achieved by running PRAGMA foreign_keys = ON; command on an open database connection. By running data altering queries without enabling foreign keys prior to that, you may risk putting your database in an inconsistent state.

+
+

Convenience queries

+

Get all messages from today (chat_dt is in UTC):

+
select * from all_messages_plain where date(chat_dt) > date('now', '-1 day') order by chat_dt;
+
+

Get overnight messages in the morning:

+
select * from all_messages_plain where chat_dt > datetime('now', '-15 hours') order by chat_dt;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/contributing.html b/docs/contributing.html new file mode 100644 index 0000000000..67c9346f00 --- /dev/null +++ b/docs/contributing.html @@ -0,0 +1,807 @@ + + + + + + + + + Contributing guide + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 31.01.2023 | Languages: EN, FR, CZ |

+

Contributing guide

+

Compiling with SQLCipher encryption enabled

+

Add cabal.project.local to project root with the location of OpenSSL headers and libraries and flag setting encryption mode:

+
cp scripts/cabal.project.local.mac cabal.project.local
+# or
+# cp scripts/cabal.project.local.linux cabal.project.local
+
+

OpenSSL on MacOS

+

MacOS comes with LibreSSL as default, OpenSSL must be installed to compile SimpleX from source.

+

OpenSSL can be installed with brew install openssl@1.1

+

You will have to add /opt/homebrew/opt/openssl@1.1/bin to your PATH in order to have things working properly

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/app-settings.html b/docs/guide/app-settings.html new file mode 100644 index 0000000000..a12684e981 --- /dev/null +++ b/docs/guide/app-settings.html @@ -0,0 +1,871 @@ + + + + + + + + + App settings + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

App settings

+

Opening the app settings

+

To open app settings:

+
    +
  • Open the app.
  • +
  • Tap on your user profile image in the upper right-hand of the screen.
  • +
  • If you have more than one profile, tap the current profile again or choose Settings.
  • +
+

Your profile settings

+

This section is labelled "You" in the app settings.

+

Your active profile

+

Tap on your avatar/name to update your current profile names and avatar.

+

Display name cannot have any spaces and it is recommended to use latin characters and numbers to make it easier to type these names to the users who use SimpleX Chat for the terminal (CLI).

+

Please note: When you save your profile, the update will be sent to all your contacts (excluding the contacts with whom your incognito profiles were shared). If you have a large number of contacts it can take several seconds.

+

Your chat profiles

+

This page allows adding and configuring your chat profiles. Please see Your chat profiles for more details.

+

Incognito

+

This feature is unique to SimpleX Chat – it is independent from chat profiles.

+

When "Incognito” is turned on, your current profile name and image are NOT shared with your new contacts. It allows connections with other people without any shared data – when you make new connections or join groups via a link a new random profile name will be generated for each contact or group.

+

Please read more in this post.

+

Your SimpleX contact address

+

  

+

This page allows you to create a long term address that can be used by other people to connect with you. Unlike 1-time invitation links, these addresses can be used many times, that makes them good to share online, e.g. on other social media platforms.

+

When people connect to you via this address, you will receive a connection request that you can accept or reject. You can configure an automatic acceptance of connection request and an automatic welcome message that will be sent to the new contacts.

+

If you start receiving too many requests via this address it is always safe to remove it – all the connections you created via this address will remain active, as this address is not used to deliver the messages.

+

Read more in this post.

+

Chat preferences

+

This page allows to configure the chat preferences that would apply to all contacts - they can be changed separately for each contact:

+
    +
  • disappearing messages - to allow disappearing messages in the conversations with you, only if your contacts allow them.
  • +
  • delete for everyone - to allow irreversible message deletion (by default messages are marked as deleted, not fully deleted). "Yes" setting would allow it only if they allow it for you, and "Always" - even if they don't allow.
  • +
  • voice messages - to allow sending voice messages.
  • +
+

To set chat preferences in each contact, tap contact name on top of the conversation and then choose "Contact preferences".

+

Group owners can set similar preferences for their groups, when the group is created or later: tap group name on top of the conversation and then choose "Group preferences".

+

Your app settings

+

This section is labelled "Settings" in the app settings.

+

Notifications

+

This page allows to configure the notifications mode: instant, periodic or only when the app is running. There are some differences in how these options work on iOS and Android. Please read more in this post about how notifications work.

+

You can also configure whether the message preview is shown when the message arrives.

+

Please note: For instant and periodic notifications to work on Android, you need to disable power optimization when prompted by the app, or later via the settings. Also, some variants of Android system require additional settings, for example MIU system on Xiaomi phones requires to enable "Auto start" for the app for the notification service to work. Please read Don't kill my app guide for any settings that may be required on your device.

+

Also, currently instant notifications have the highest battery consumption - we are working to reduce it to be less or the same as for periodic notifications.

+

Network & servers

+

This page allows to configure your own SMP relays and change other network settings.

+ +

SMP servers

+

     

+

By default, the app has preset relays configured – you can change them to your own.

+

This page also allows testing the connection with the servers.

+

Read more in this post.

+

Use SOCKS proxy (Android only)

+

This option makes the app connect via a SOCKS proxy that should be provided by some other app running on your device.

+

The most typical use for this is to run Orbot app that provides a SOCKS proxy to connect via Tor network, but it can be some other app and it can proxy connections via some other overlay network.

+

Use .onion hosts

+
Android
+

Use .onion hosts option is only available when Use SOCKS proxy is enabled. You can choose:

+
    +
  • no: never use .onion hosts. Choose this option if your SOCKS proxy does not connect via Tor network.
  • +
  • when available (default): when SOCKS proxy is enabled the app assumes that it provides connections via Tor network and use .onion host addresses when SMP relays include them in their configuration.
  • +
  • required: always use .onion hosts. Choose this option if your SOCKS proxy connects via Tor network and you want to avoid connections without Tor. In this case, if the SMP relay address does not include .onion host, the connection will fail.
  • +
+
iOS
+

 

+

While iOS does not support SOCKS proxies, you can install Orbot app that works as VPN provider. You can choose:

+
    +
  • no (default): do not use .onion hosts. Choose this option if you do not use Orbot or if you use VPN that proxies connections via some other overlay network.
  • +
  • when available: use .onion host addresses when SMP relays include them in their configuration. Orbot VPN must be enabled for this option to work.
  • +
  • required: always use .onion hosts. Choose this option if you use Orbot VPN and you want to avoid connections without Tor. In this case, if the SMP relay address does not include .onion host, the connection will fail. If you use this option, you can enable "Disable Orbot for non-onion traffic" option in Orbot settings making the rest of your device traffic to not use Tor.
  • +
+

Please note VPN on iOS can send some traffic to the usual network, if, for example, VPN app crashes. You can configure enable always-on VPN mode on managed iOS devices, but this is not applicable to most individual devices.

+

Transport isolation (BETA)

+

This option is only available if you have enabled developer tools.

+

Please read the details in this post.

+

Advanced network settings

+ +

If your network is slow, and connections to the servers keep failing (you would see a spinner on your contacts), please increase TCP and protocol timeouts in this page.

+

Privacy and security

+

SimpleX Lock

+

SimpleX Lock when enabled requires to pass the device authentication when you open the app or use some security- or privacy-sensitive features.

+

You will be offered to enable it after you open the app a few times.

+

To enable it later:

+
    +
  • Open the app settings.
  • +
  • Tap on "Privacy & security".
  • +
  • Toggle on "SimpleX Lock" slider.
  • +
  • Confirm your phone credentials.
  • +
+

Done! Now you will be required to authenticate when you start or resume the app after 30 seconds in background.

+

Protect app screen

+ +

This option hides the app screen in recent apps - it is enabled by default. On Android it also prevents screenshots.

+

Auto Accept Images

+

Auto-accepting images may reduce privacy – your contacts will know you are online.

+ + +

Enabling sending link previews may reduce privacy – your app will be loading link preview from the website.

+ + +

This option affects how the links to connect to other SimpleX users or to join groups are shown in the conversations. You can choose between:

+
    +
  • description (default): only the link description and server host name are shown. The link won't be opened in the browser.
  • +
  • full link: the full link is shown. The link will still not be opened in the browser.
  • +
  • via browser: the full link is shown, and it will be opened in the browser. In this case, if the link domain is different from simplex.chat, the link will be shown in red color, as it might be malicious.
  • +
+

Read more about SimpleX Links security.

+

Appearance

+

This page allows configuring:

+
    +
  • interface language
  • +
  • app icon
  • +
  • accent color
  • +
+

Database passphrase & export

+

This page allows to change the database passphrase, export and import the database and configure the message retention period.

+

Read more in Managing Your Data page.

+

Help & feedback

+

This section has information on how to use the app and the links to connect to the team. Please use Send questions and ideas to connect to us via the chat to ask any questions, make any suggestions and report any issues.

+

Support SimpleX Chat

+
    +
  • contribute - the link to the information about how to contribute and to donate to the project.
  • +
  • rate the app - rate and review it on the App Store or Play Store - your feedback helps a lot.
  • +
  • star on GitHub - that also helps us grow very much.
  • +
+

Thank you for your support!

+

Developer tools

+

This page has options that normally are only needed for app developers and can be used to debug the app in case something is not working.

+

Chat console

+

Here you can see and use console command with the chat core. None of this information is sent over the network, this is an internal communication between different parts of the app.

+

Please be careful - some of the commands can disrupt app functioning, only use them if you know what you are doing or were instructed by the team.

+

Please note: the log in console can contain what looks like errors. Unless you experience any issues in the app UI, these errors should not be considered as the app malfunction - they are likely to be normal and expected behavior.

+

Confirm database upgrades

+

This option is off by default - the app database is migrated to the new version without any confirmations. Starting from v4.6.2 these migrations are reversible - you can rollback to the previous version(s) of the app (not earlier than v4.6.1). If you want to be asked a confirmation every time database is upgraded you may enable this option - this is not recommended, as it happens almost on every app update, and should not cause any concerns.

+

Show developer options

+

This option currently enables Transport isolation mode option and also enables showing database IDs in contacts, groups and group members to simplify debugging via console commands.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/audio-video-calls.html b/docs/guide/audio-video-calls.html new file mode 100644 index 0000000000..b05ef07c57 --- /dev/null +++ b/docs/guide/audio-video-calls.html @@ -0,0 +1,797 @@ + + + + + + + + + Audio & video Calls + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Audio and Video Calls

+

SimpleX Chat allows you to make end-to-end encrypted audio and video calls with your contacts via WebRTC. Note: Group calls are not supported at this time.

+

Making and accepting the calls

+

How to make an audio call

+
    +
  1. Tap on a contact.
  2. +
  3. Tap on the phone icon to the right of your contact's name at the top of the screen.
  4. +
+

How to make a video call

+
    +
  1. Tap on a contact.
  2. +
  3. Tap on the three vertical dots on the top right-hand corner of the screen to access more options.
  4. +
  5. Choose Video call.
  6. +
+

Accepting the calls

+

When there is an incoming call you have three options:

+
    +
  • accept: to connect the call
  • +
  • reject: to reject the call, without notifying the caller.
  • +
  • ignore: to temporarily dismiss the call, but in a way that it can be accepted later, if the caller is still waiting, via the Accept call message in the conversation with this contact.
  • +
+

There is no time limit that the call invitation can remain active - as long as the caller is still waiting, you can accept the call any time later.

+

The call can be accepted from the lock screen, both on Android (it needs to be enabled via options) and on iOS (by default, using native iOS call interface that can be disabled).

+

Calls on lock screen on Android

+

SimpleX Chat shows an incoming call on your device's lock screen by default. However, you can change this behavior in the app settings menu.

+
    +
  1. Open the app settings menu.
  2. +
  3. Tap Audio and Video calls.
  4. +
  5. On the Calls on lock screen drop-down list, choose from the following three options: +
      +
    • Disable - the call will show as a notification.
    • +
    • Show - the call will show on the lock screen, you need to unlock the device and the app to accept it.
    • +
    • Accept - the call can be accepted and rejected directly from the lock screen, without opening the app.
    • +
    +
  6. +
+

Please note: some Android systems/devices prohibit full screen views on lock screen - in this case the call will show as a usual notification.

+

Calls on lock screen on iOS

+ +

By default, SimpleX Chat uses native iOS call interface, where allowed, to show incoming calls on the lock screen. You can disable it:

+
    +
  1. Open the app settings menu.
  2. +
  3. Tap Audio and Video calls.
  4. +
  5. Toggle the Use iOS call interface switch off.
  6. +
+

Please note: iOS call interface allows accepting the calls without unlocking the device and the app. If this is undesirable, please disable it – the calls will show as notifications in this case.

+

Read more in this post.

+

Advanced call settings

+

WebRTC ICE servers

+ +

SimpleX Chat uses a preset relay server to hide your IP address from your contacts by default, but it can also observe the duration of your calls. If you don't want that, you can configure and use your self-hosted WebRTC relay servers instead for further control of your calls.

+
    +
  1. Open the app settings menu.
  2. +
  3. Tap Audio and Video calls.
  4. +
  5. Tap WebRTC ICE servers.
  6. +
  7. Toggle the Configure ICE servers switch on.
  8. +
  9. Enter your ICE server addresses (one per line).
  10. +
  11. Tap Save.
  12. +
+

Please note: unlike messaging relays (SMP servers), the configuration of WebRTC ICE servers is stored on the current device, not in the chat database. if you transfer the chat database to another device you need to update this configuration.

+

Always use relay

+

Audio and video calls on SimpleX Chat are routed via a TURN relay server by default. Optionally you can disable this and use peer-to-peer (P2P) instead, when it is supported by your network. However, your IP address will be known to your contacts.

+
    +
  1. Open the app settings menu.
  2. +
  3. Tap Audio and Video calls.
  4. +
  5. Toggle the Always use relay switch on to use a relay server or off for P2P.
  6. +
+

Please note: disabling this option allows P2P calls, but it does not prohibit the use of TURN relays – in case your network providers block P2P connections, the call will still use relays if the are available. To prohibit the use of relays you need to change WebRTC ICE server configuration to only include STUN servers, for example:

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/chat-profiles.html b/docs/guide/chat-profiles.html new file mode 100644 index 0000000000..47a4394e8b --- /dev/null +++ b/docs/guide/chat-profiles.html @@ -0,0 +1,811 @@ + + + + + + + + + Chat profiles + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Your chat profiles

+

Creating additional chat profiles

+

SimpleX Chat allows creating as many chat profiles as you like. Same as the first profile, they are only stored locally on your device.

+ +

To create an additional SimpleX Chat profile:

+
    +
  • Open the app settings.
  • +
  • Select "Your chat profiles".
  • +
  • Unlock option via fingerprint or PIN.
  • +
  • Tap on "+ Add profile”.
  • +
  • Create a new profile by inputting your display name and full name (optional).
  • +
  • Tap on "Create".
  • +
+

Hiding and muting chat profiles

+

v4.6 added the ability to mute and to hide chat profiles.

+

     

+

These actions are available via long-press (Android) or swipe (iOS) on the profile in the list.

+

To unhide hidden profiles, enter the full password in the search bar.

+

Switching between profiles

+ +
    +
  • Tap on your user profile image in the upper right-hand of the screen.
  • +
  • Select which profile you want to use.
  • +
+

You can also switch profile via Your chat profiles in the settings.

+

Incognito mode

+

+

This feature is unique to SimpleX Chat – it is independent from chat profiles.

+

When "Incognito Mode” is turned on, your currently chosen profile name and image are hidden from your new contacts. It allows anonymous connections with other people without any shared data – when you make new connections or join groups via a link a new random profile name will be generated for each connection.

+

To toggle the incognito mode on/off:

+ +

Please read more in this post.

+

Edit your profile

+

To edit your profile:

+
    +
  • Open the app settings.
  • +
  • Select your profile.
  • +
  • Tap on "Edit".
  • +
  • Input your desired profile name and/or update your full name.
  • +
  • You can also set and change profile image.
  • +
  • Tap on "Save and notify contacts".
  • +
+

Move your chat profiles to another device

+

SimpleX Chat stores all user data only on client devices using a portable encrypted database format that can be exported and transferred to any supported device.

+

To export your SimpleX Chat data:

+
    +
  • Open the app settings.
  • +
  • Select "Database passphrase & export".
  • +
  • Stop chat by toggling "Chat is running" (tap "Stop” in the confirmation dialog).
  • +
  • Confirm it with fingerprint or PIN, in case you have SimpleX Lock enabled.
  • +
  • If you didn't set it before, set a passphrase in "Database passphrase". Initially, the database is encrypted with a random passphrase that is stored in KeyChain (iOS) or with KeyStore (Android).
  • +
  • Tap on "Export database" - it won't allow exporting unless you have set a passphrase.
  • +
  • Save the file on your device or share it via any available option.
  • +
+

To import your SimpleX Chat data in the app on another device:

+
    +
  • Transfer the database file to the new device.
  • +
  • Install SimpleX Chat app.
  • +
  • Create chat profile with any name by following the steps in Create your first chat profile – you will replace it soon.
  • +
  • Open the app settings
  • +
  • Select "Database passphrase & export".
  • +
  • Stop chat by tapping the switch on "Chat is running".
  • +
  • Tap "Import database".
  • +
  • Select the .zip file of the exported chat data.
  • +
  • Tap "Import” in the confirmation dialog.
  • +
  • Start chat via toggle or close and start the app – you will be prompted to enter the passphrase for your chat database.
  • +
+

Please note:

+
    +
  1. +

    Currently you cannot move some of the profiles, only the whole database containing all profiles can be moved.

    +
  2. +
  3. +

    You must NOT use the exported database on more than one device at a time, as it may disrupt some of the connections. You also must always use the latest version of the chat database - using the old one is also likely to disrupt your connections.

    +
  4. +
  5. +

    There is no way to recover lost passphrase - make sure to store it securely.

    +
  6. +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/making-connections.html b/docs/guide/making-connections.html new file mode 100644 index 0000000000..af41b04b6e --- /dev/null +++ b/docs/guide/making-connections.html @@ -0,0 +1,738 @@ + + + + + + + + + Making connections + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Connect to somebody in the chat

+

Work in progress

+

Because you have no identifier on the SimpleX platform, nobody can contact you unless you share a one-time or temporary user address, such as a QR code or a link.

+

Even with the optional user address, while it can be used to send spam contact requests, you can change or completely delete it without losing any of your connections.

+

Private Connection — connect using an invitation link or QR code via video or in-person.

+

Group Chat — Users have the option to create a secret group, share their contact link [which can be deleted later on], or generate a one-time invitation link.

+

Conversation preferences

+

Tap on one of your conversations to open conversation preferences.
+Here you can choose whether you wish to allow disappearing messages, deleting messages for everyone and voice messages.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/managing-data.html b/docs/guide/managing-data.html new file mode 100644 index 0000000000..bdb7f512ce --- /dev/null +++ b/docs/guide/managing-data.html @@ -0,0 +1,753 @@ + + + + + + + + + Managing data + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Managing Your Data

+

Automatic message deletion

+

Here you can choose to delete messages from your local chat database after a set period of time.

+

Please note: This option does not delete messages for other users, only for you. This option is set independently for each chat profile.

+

Chat Database

+

To open your chat database settings:

+ +

Database passphrase

+ +

By default, database passphrase is random, you have to set it manually to be able to export it.

+

App data backup

+

Here you can allow the system to back up app data, wherever it is configured. A database passphrase must be set to use this.

+

Export database

+

Here you can export the chat database to a file.

+

Import database

+

Here you can import the chat database from a file.

+

Delete database

+

Here you can delete your chat database. WARNING: Results in a loss of all your SimpleX Chat data! Unless you have just exported the chat database.

+

Delete files and media

+ +

You can delete all sent and received files and media stored in the app via this option, without deleting the messages.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/privacy-security.html b/docs/guide/privacy-security.html new file mode 100644 index 0000000000..990bd31c5b --- /dev/null +++ b/docs/guide/privacy-security.html @@ -0,0 +1,765 @@ + + + + + + + + + Privacy & security + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Privacy and Security

+

SimpleX Chat default configuration aims to balance privacy, security and convenience. You may want to change the default options.

+

This page lists all the features and options that affect privacy and security.

+

Privacy and Security settings

+

These settings are available in the Privacy & Security settings.

+

Security code verification

+ +

While SimpleX Chat always establishes connection via link passed via an independent channel, so it is already more protected than other apps, there are scenarios when the invitation links can be substituted in transit (MITM attack). To protect against such attacks, you should verify the security code with your contacts:

+
    +
  • open the conversation with the contact
  • +
  • tap the contact name on top of the conversation
  • +
  • tap "Verify security code"
  • +
  • ask your contact to do the same
  • +
  • the connection is secure if you and your contact have the same security code
  • +
+

This can be validated by one of the following:

+
    +
  • one of you can scan the security code from their device, if the codes match the contact will be marked as verified on the device that scanned the code.
  • +
  • simply tap mark verified if you trust the confirmation from your contact that the code is verified.
  • +
  • you can also read the contact over the voice call.
  • +
+

Read more in this post

+

Database passphrase

+

When installed, the app generates a random passphrase for the chat database and stores it securely in KeyChain (iOS) or using KeyStore (Android, TPM module is used when available). You can set your own passphrase and also remove it from the device, in which case you will need to enter it every time you start the app, and notifications may be limited, in the Database passphrase & export settings.

+

Incognito mode

+

This feature generates a random profile name for each new contact. Read more in Incognito mode.

+

Hidden profiles

+

This feature allows to hide some of your chat profiles with the password. Read more in Hiding and muting chat profiles.

+

Network settings

+

Transport isolation (BETA) allows to isolate you traffic with each contact in a different TCP connection (and Tor circuit).

+

Using Tor

+

 

+

To connect to SMP relays (messaging servers) via Tor you need to install Orbot app.

+

Android: use Orbot app as SOCKS proxy on port 9050 (default) and enable Use SOCKS proxy.

+

iOS: use Orbot app as VPN provider and enable VPN.

+

You can also change which server addresses are used with Use .onion hosts option.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/readme.html b/docs/guide/readme.html new file mode 100644 index 0000000000..63f2e773b9 --- /dev/null +++ b/docs/guide/readme.html @@ -0,0 +1,788 @@ + + + + + + + + + Quick start + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

SimpleX Chat User Guide

+

The first messaging platform that has no user identifiers of any kind — 100% private by design.

+

Contents

+ +

Quick start

+

Create your first chat profile

+

After downloading SimpleX Chat via the links at https://simplex.chat:

+
    +
  • Open the app.
  • +
  • Create a new profile by inputting your display name and full name (optional).
  • +
  • Tap on "Create".
  • +
+

This profile is local to the device, it is not stored anywhere else

+

Choose notifications mode

+

After you have created the chat profile the app will ask you to choose notifications mode.

+ +

Please read their description, as on iOS it is trade-off between convenience and privacy, with instant notifications sharing more meta-data with the servers, and on Android it is a trade-off between notification delays and battery life.

+

You can read more about the differences between notifications work on Android and iOS.

+

Connect to developers

+

When you just start using the app, you can tap "chat with the developers" to ask any questions or just to test the app - feel free to send any test messages.

+

This button will disappear once you make the first connection. To connect to the developers later:

+ +

Join some user groups

+

There are links to join several user groups on our GitHub page - join them to ask any questions and discuss ideas.

+

You can also find some other user-managed groups via online search.

+

To join a group via a link:

+
    +
  • Get a link to a SimpleX user group, which you can get from your existing SimpleX conversations or by finding it online.
  • +
  • Tap on a button in the lower right-hand of the screen.
  • +
  • Tap on "Connect via link / QR code" button.
  • +
+

Connect to friends

+
    +
  • Tell your friends to download SimpleX Chat app via one of the links here: https://simplex.chat
  • +
  • Create a one-time link for each of you friends by tapping new chat button (Android: a floating pencil button in the bottom right corner, iOS: a pencil button in the top right corner)
  • +
  • Tap Create one-time invitation link.
  • +
  • Share each link with a different friend, or alternatively let them scan a QR code.
  • +
  • You can optionally assign a different alias to each link, to know when they connect who is who, if they use incognito mode, for example.
  • +
  • To use your link or QR code, tell your friends to tap new chat button and then tap on "Connect via link / QR code".
  • +
  • They can either scan QR code or paste the link. If they opened the link in the browser, they need to tap "Open in mobile app" button on the page.
  • +
+

Watch the video on the website that shows how it works.

+

You can also create a long-term contact address.

+

Explore the app

+

Most app settings are shared for all profiles, but some settings are specific to chat profile.

+

Read more in App settings page.

+

Many conversation actions are available via long-press or swipe – try them!

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/secret-groups.html b/docs/guide/secret-groups.html new file mode 100644 index 0000000000..c42bf60b0c --- /dev/null +++ b/docs/guide/secret-groups.html @@ -0,0 +1,779 @@ + + + + + + + + + Secret groups + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Secret groups

+

Secret groups are anonymous and private, they are designed to be hard to track by outsiders. Every message and file gets sent separately to every member in the group, which makes secret groups only fit for smaller groups.

+

Creating a group

+

+
    +
  • Tap on a button in the lower right-hand of the screen.
  • +
  • Tap on "Create secret group".
  • +
  • Enter group display name.
  • +
  • Tap on "Create".
  • +
+

Group preferences

+

Here you can choose whether you want to allow disappearing messages, direct messages, deleting for everyone and voice messages.

+

Adding members

+
    +
  • Open a group.
  • +
  • Tap on + button in the upper right-hand of the screen.
  • +
  • Select contacts you wish to invite.
  • +
  • Tap on "Invite to group".
  • +
+

Joining a group

+ +

When you receive the invitation to join the group you can accept it both from the conversation with your contact and from the list of conversations.

+

Leaving a group

+ +

Tap and hold (Android) or swipe (iOS) the group in the list of the conversations to leave the group.

+

You can also leave the group from the group page:

+
    +
  • Open a group conversation.
  • +
  • Tap group name on top.
  • +
  • Scroll to the bottom and tap "Leave group".
  • +
+

Member permissions

+

Open a group and tap on group's name to view members list, there you can tap on a member and change their role.

+
    +
  • Observer: can only read messages (and delete or mark deleted the messages they sent before their role was changed).
  • +
  • Member: can send messages and delete own messages.
  • +
  • Admin: Same as member, but can delete the messages of others and remove members from the group.
  • +
  • Owner: Same as admin, but can change group preferences.
  • +
+ +

  

+

If you are a group owner or admin, you can create a link that can be used by anyone to join the group, making a group more public.

+
    +
  • Open a group conversation.
  • +
  • Tap group name.
  • +
  • Tap on "Create group link.
  • +
+

Once the link is created, you can also change the role assigned to members when they join.

+

Welcome message

+

If you are a group owner you can create a welcome message that will be shown to all new members joining group.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/guide/send-messages.html b/docs/guide/send-messages.html new file mode 100644 index 0000000000..179d705277 --- /dev/null +++ b/docs/guide/send-messages.html @@ -0,0 +1,797 @@ + + + + + + + + + Sending messages + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Sending, editing and deleting messages

+

Sending text messages on SimpleX Chat is pretty straightforward, tap on your contact and then tap on text area, type in your message and tap on "Send" button.

+

You need to open a conversation to send messages.

+

Sending messages

+

Sending text messages

+

You can send, edit and quote messages in a conversation.

+

To send, simply type in the message in the entry box and tap "Send".

+

To edit or quote a message, tap and hold the message and choose the action.

+

Sending images and files

+
    +
  • Tap 📎 (paperclip) button on the left of the message entry box.
  • +
  • Choose between "Use Camera", "From Gallery" and "Choose file".
  • +
  • Once you have chosen what you wish to send, tap on "Send" button.
  • +
+

On iOS you can also paste images from the clipboard.

+

Sending voice messages

+ +
    +
  • Tap 🎤 (microphone) button on the right of the message entry box.
  • +
  • Allow SimpleX Chat to record the voice if prompted. You will have to tap on the microphone button once again if this happens.
  • +
  • Speak, once you've finished the recording, tap on the square stop icon on the right.
  • +
  • You may listen to the recording before sending it, and re-record if necessary.
  • +
  • Tap on "Send" button to send the recorded voice message.
  • +
+

You can also tap and hold the microphone button to record a voice message. In this case the recording will stop once you release the button. You still need to tap "Send" to send the message.

+

Please note: if the microphone button is gray, that means voice messages are disabled in this conversation. Ask your contact or group owner to enable them (they are enabled by default).

+

How to use disappearing messages

+

  

+
    +
  • Tap on name of the conversation.
  • +
  • Toggle the slider next to "Disappearing messages".
  • +
  • Choose how long until messages are deleted after being sent in "Delete after".
  • +
+

Please note: Your contact must also enable disappearing messages. In a group, only group owner can enable disappearing messages.

+

Sending "live" messages

+ +

You can use "live" messages for your recipients to see the messages as you type them, without having to tap "Send" button until it's completed. It can be useful in these scenarios:

+
    +
  1. Real-time conversation, like talking in person or in a discussion club. You can retract what you wrote, but your recipients would see it. Also people don’t need to guess what you’re typing. This allows to avoid interrupting the flow of conversation and still send longer messages.
  2. +
  3. An activist doing live reporting when there is a risk to lose the phone or connection at any moment. This feature allows to send as much as possible, up to the last word, without having to send only very short messages.
  4. +
+

To send a "live" message:

+
    +
  • Tap ⚡️ (lightning) button on the right of the message entry box.
  • +
  • When you do it first time, you would see and alert explaining the feature. Tap "OK", and tap it again.
  • +
  • Now you can start typing the messages, the app will be periodically sending the updates to your recipients, as you type (every few seconds, and only complete words).
  • +
+

Sending stickers and animated messages

+

  

+

While there are no stickers and GIFs in the app itself, you can send them using third-party (such as GIPHY on iOS) or native (Android 13+) keyboards.

+

Message drafts

+

  

+

Messages are kept in the chat until they are sent, even if you leave the chat.

+

For privacy and simplicity, we decided to allow only one message draft and keep it only until the app is stopped.

+

Read more in this post.

+

Deleting messages

+

  

+

To delete a message, tap and hold the message and choose "Delete".

+

If you sent this message yourself within the last 24 hours, you will be offered two options:

+
    +
  • delete for everyone - this will either mark the message as deleted for you and the recipient(s) (this is the default) or fully delete the message on your and recipients' devices (if you have enabled "Delete for everyone" in the conversation preferences)
  • +
  • delete for me - this will delete the message only locally.
  • +
+

Please read about reasons for not allowing full deletion by default. TL;DR: data sovereignty.

+

Moderating messages in the groups

+

Group admins can delete member messages that are inappropriate for the groups.

+

To remove a message of another member, tap and hold the message and choose "Moderate".

+

Please read about group moderation.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/images/weblate_1.png b/docs/images/weblate_1.png new file mode 100644 index 0000000000..a8b2c60c3e Binary files /dev/null and b/docs/images/weblate_1.png differ diff --git a/docs/images/weblate_2.png b/docs/images/weblate_2.png new file mode 100644 index 0000000000..f73f3de649 Binary files /dev/null and b/docs/images/weblate_2.png differ diff --git a/docs/lang/cs/android.html b/docs/lang/cs/android.html new file mode 100644 index 0000000000..44bf69b515 --- /dev/null +++ b/docs/lang/cs/android.html @@ -0,0 +1,813 @@ + + + + + + + + + Přístup k souborům v aplikaci Android + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 07.02.2023 | Jazyky: CZ, EN |

+

Přístup k souborům v aplikaci Android

+

SimpleX používá databáze a ukládá své předvolby do soukromého datového adresáře v systému Android. Adresář obsahuje:

+
    +
  • Databáze
  • +
  • odeslané a přijaté soubory
  • +
  • dočasné soubory, které budou smazány, když nebudou potřeba
  • +
  • uživatelské předvolby.
  • +
+

Pokud chcete zobrazit, co je uloženo v datovém adresáři SimpleX, musíte mít:

+
    +
  • Unixový operační systém (nebo MinGW na Windows).
  • +
  • Nástroj ADB (Android Debug Bridge) nainstalovaný v počítači (stáhněte si jej zde a nainstalujte).
  • +
  • zařízení připojené přes USB nebo Wi-Fi k počítači.
  • +
+

Postup:

+
    +
  • Otevřete SimpleX, přejděte na Databáze passphrase & export, povolte Zálohování dat aplikace. Tím se zprovozní další kroky
  • +
  • Volitelné: pokud chcete zobrazit obsah databáze, změňte přístupovou frázi databáze z náhodné na svou. Chcete-li to provést, zastavte chat na obrazovce Database passphrase & export, otevřete Database passphrase, zadejte novou passphrase a potvrďte ji, poté ji aktualizujte. Nezapomeňte ji, jinak přijdete o všechna svá data v případě, že bude passphrase později znovu požadována.
  • +
  • otevřete emulátor terminálu (Windows CMD/Powershell nebude fungovat) a změňte adresář na ten, který chcete použít pro uložení zálohy:
  • +
+
cd /tmp # jen příklad
+
+

Poté spusťte následující příkaz:

+
adb -d backup -f chat.ab -noapk chat.simplex.app && 
+tail -n +5 chat.ab > chat.dat && 
+printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - chat.dat > chat.gz && 
+tar -xvzf chat.gz
+
+

Nyní odemkněte zařízení a potvrďte operaci zálohování bez použití hesla pro šifrování, jinak příkazy nebudou fungovat.

+

Poté by mělo být zálohování ukončeno. Pokud se zobrazí chybové hlášení tar: Error is not recoverable: exiting now, ale předtím jste vypsali názvy některých souborů, nebojte se, je to v pořádku.

+

Nyní budou zálohované soubory uvnitř ./apps/chat.simplex.app/.

+

Upozorňujeme, že pokud používáte moderní verzi SimpleX, budou databáze zašifrované a jejich obsah nebudete moci zobrazit bez použití aplikace sqlcipher a bez znalosti dešifrovací fráze (musíte ji nejprve změnit na svou z náhodně vygenerovaných v aplikaci).

+

Další informace o tom, jak dešifrovat databáze a provádět dotazy do nich, najdete v příručce SQL.md.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/cli.html b/docs/lang/cs/cli.html new file mode 100644 index 0000000000..124a7cf1cd --- /dev/null +++ b/docs/lang/cs/cli.html @@ -0,0 +1,956 @@ + + + + + + + + + SimpleX Chat terminálová + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 31.01.2023 | Jazyky: CZ, EN, FR |

+

SimpleX Chat terminálová (konzolová) aplikace pro Linux/MacOS/Windows

+

Obsah

+ +

Funkce chatu v terminálu

+
    +
  • Chat 1:1 s více lidmi v jednom okně terminálu.
  • +
  • Skupinové zasílání zpráv.
  • +
  • Posílání souborů kontaktům a skupinám.
  • +
  • Kontaktní adresy uživatelů - navázání spojení prostřednictvím odkazů na více kontaktů.
  • +
  • Zprávy uchovávané v místní databázi SQLite.
  • +
  • Automaticky vyplňované jméno příjemce - po navázání spojení stačí napsat zprávu a odpovědět odesílateli.
  • +
  • K dispozici ukázkové servery SMP, které jsou v aplikaci předkonfigurovány - nebo si můžete nasadit vlastní server.
  • +
  • Žádná globální identita ani žádná jména nejsou pro server(y) viditelná, což zajišťuje plné soukromí vašich kontaktů a konverzací.
  • +
  • Dvě vrstvy šifrování E2E (double-ratchet pro duplexní spojení s použitím dohody klíčů X3DH s efemérními klíči Curve448 a NaCl crypto_box pro fronty SMP s použitím klíčů Curve25519) a předávání klíčů příjemců mimo pásmo (viz Jak používat chat SimpleX).
  • +
  • Ověřování integrity zpráv (pomocí zahrnutí digestů předchozích zpráv).
  • +
  • Ověřování každého příkazu/zprávy servery SMP pomocí automaticky generovaných klíčů Ed448.
  • +
  • Transportní šifrování TLS 1.3.
  • +
  • Dodatečné šifrování zpráv od serveru SMP k příjemci za účelem snížení korelace provozu.
  • +
+

Veřejné klíče zapojené do výměny klíčů se nepoužívají jako identita, jsou náhodně generovány pro každý kontakt.

+

Technické podrobnosti viz Použité šifrovací primitivy.

+

+

🚀 Instalace

+

Stáhněte si klienta chatu

+

Linux a MacOS

+

Chcete-li nainstalovat nebo aktualizovat simplex-chat, měli byste spustit instalační skript. K tomu použijte následující příkaz cURL nebo Wget:

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+
wget -qO- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+

Jakmile se chatovací klient stáhne, můžete jej spustit pomocí příkazu simplex-chat v terminálu.

+

Případně můžete binární soubor chatu pro váš systém stáhnout ručně z latest stable release a spustit jej podle následujícího návodu.

+
chmod +x <binary>
+mv <binary> ~/.local/bin/simplex-chat
+
+

(nebo v jakémkoli jiném preferovaném umístění v PATH).

+

V systému MacOS musíte také povolit spuštění nástroje Gatekeeper.

+

Windows

+
move <binary> %APPDATA%/local/bin/simplex-chat.exe
+
+

Sestavení ze zdrojových kódů

+
+

Upozornění: pro sestavení aplikace použijte zdrojový kód ze stabilní větve.

+
+

Použití nástroje Docker

+

V systému Linux můžete spustitelný soubor chatu sestavit pomocí docker build with custom output:

+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+DOCKER_BUILDKIT=1 docker build --output ~/.local/bin .
+
+
+

Upozornění: Pokud narazíte na chybu verze `GLIBC_2.28' nenalezena, obnovte jej pomocí základního obrazu haskell:8.10.7-stretch (změňte jej ve svém lokálním Dockerfile).

+
+

V libovolném operačním systému

+
    +
  1. Nainstalujte Haskell GHCup, GHC 8.10.7 a cabal:
  2. +
+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
+
+
    +
  1. Sestavte projekt:
  2. +
+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+# v Linuxu
+apt-get update && apt-get install -y build-essential libgmp3-dev zlib1g-dev
+cp scripts/cabal.project.local.linux cabal.project.local
+# nebo na MacOS:
+# brew install openssl@1.1
+# cp scripts/cabal.project.local.mac cabal.project.local
+# možná budete muset změnit cabal.project.local tak, aby ukazoval na skutečné umístění openssl
+cabal update
+cabal install
+
+

Použití

+

Spuštění klienta chatu

+

Chcete-li spustit klienta chatu, spusťte z terminálu příkaz simplex-chat.

+

Ve výchozím nastavení je datový adresář aplikace vytvořen v domovském adresáři (~/.simplex nebo %APPDATA%/simplex ve Windows) a jsou v něm inicializovány dva databázové soubory SQLite simplex_v1_chat.db a simplex_v1_agent.db.

+

Chcete-li zadat jiný prefix cesty k souborům databáze, použijte volbu příkazového řádku -d:

+
$ simplex-chat -d alice
+
+

Spuštění výše uvedeného příkladu vytvoří databázové soubory alice_v1_chat.db a alice_v1_agent.db v aktuálním adresáři.

+

Na serveru Linode jsou umístěny tři výchozí servery SMP - jsou předkonfigurovány v aplikaci.

+

Pokud jste nasadili vlastní SMP server(y), můžete klienta nakonfigurovat pomocí volby -s:

+
$ simplex-chat -s smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@smp.example.com
+
+

Řetězec zakódovaný v Base64url před adresou serveru je offline otisk certifikátu serveru, který je ověřován klientem během TLS handshake.

+

S lidmi můžete stále hovořit pomocí výchozího nebo jakéhokoli jiného serveru - ovlivňuje to pouze umístění fronty zpráv při navazování spojení (a fronta odpovědí může být na jiném serveru, jak nastaví klient druhé strany).

+

Spusťte simplex-chat -h a zobrazte všechny dostupné možnosti.

+

Přístup k serverům pro zasílání zpráv přes Tor

+

Nainstalujte Tor a spusťte jej jako proxy server SOCKS5 na portu 9050, např. na Macu můžete:

+
brew install tor
+brew services start tor
+
+

Pro přístup k serverům přes Tor použijte volbu -x:

+
simplex-chat -x
+
+

Můžete také použít volbu --socks-proxy=ipv4:port nebo --socks-proxy=:port pro konfiguraci hostitele a portu vašeho SOCKS5 proxy serveru, např. pokud jej provozujete na jiném hostiteli nebo portu.

+

Jak používat SimpleX chat

+

Po spuštění chatu budete vyzváni k zadání svého "zobrazovacího jména" a volitelného "celého jména" pro vytvoření místního profilu chatu. Vaše zobrazované jméno je přezdívka, pod kterou se na vás mohou obracet vaše kontakty - není jedinečné a neslouží jako globální identita. Pokud si některé vaše kontakty zvolily stejné zobrazovací jméno, přidá chatovací klient k jejich místnímu zobrazovacímu jménu číselnou příponu.

+

Následující schéma ukazuje, jak se připojit ke kontaktu a poslat mu zprávu:

+
+ +
+

Po nastavení místního profilu zadejte /c (pro /connect) pro vytvoření nového spojení a vygenerování pozvánky. Tuto pozvánku odešlete svému kontaktu prostřednictvím jakéhokoli jiného kanálu.

+

Můžete vytvořit více pozvánek zadáním /connect vícekrát a odesláním těchto pozvánek příslušným kontaktům, se kterými se chcete spojit.

+

Pozvánku lze použít pouze jednou, a i kdyby byla zachycena, útočník by ji nemohl použít k odeslání zpráv prostřednictvím této fronty, jakmile váš kontakt potvrdí, že spojení bylo navázáno. Vysvětlení formátu pozvánky naleznete v protokolu agenta.

+

Kontakt, který obdržel pozvánku, by měl zadat /c <pozvánka>, aby spojení přijal. Tím se spojení naváže a obě strany jsou o tom informovány.

+

Poté by měly použít příkazy @<jméno> <zpráva> k odesílání zpráv. Můžete také prostě začít psát zprávu a odeslat ji kontaktu, který byl poslední.

+

Seznam dostupných příkazů zobrazíte pomocí /help v chatu.

+

Skupiny

+

Skupinu vytvoříte příkazem /g <group> a kontakty do ní přidáte příkazem /a <group> <name>. Do skupiny pak můžete posílat zprávy zadáním #<skupina> <zpráva>. Pro další příkazy použijte /help groups.

+

simplex-chat

+
+

Upozornění: skupiny nejsou uloženy na žádném serveru, jsou vedeny jako seznam členů v databázi aplikace, kterým budou zprávy zasílány.

+
+

Odesílání souborů

+

Soubor můžete odeslat kontaktu pomocí /f @<contact> <soubor_cesta> - příjemce jej bude muset před odesláním přijmout. Pro další příkazy použijte /help files.

+

simplex-chat

+

Soubory můžete posílat skupině pomocí /f #<skupina> <soubor_cesta>.

+

Kontaktní adresy uživatelů

+

Jako alternativu k jednorázovým pozvánkovým odkazům můžete vytvořit dlouhodobou adresu pomocí /ad (pro /adresa). Vytvořenou adresu pak můžete sdílet libovolným kanálem a používat ji ostatními uživateli jako odkaz na žádost o kontakt pomocí /c <uživatelská_kontaktní_adresa>.

+

Příchozí žádosti můžete přijmout nebo odmítnout pomocí příkazů /ac <jméno> a /rc <jméno>.

+

Uživatelská adresa je "dlouhodobá" v tom smyslu, že se jedná o odkaz pro vícenásobné použití - lze ji používat, dokud ji uživatel nesmaže, v takovém případě by všechna navázaná spojení zůstala stále aktivní (na rozdíl od toho, jak to funguje u e-mailu, kdy změna adresy vede k tomu, že vám lidé nemohou posílat zprávy).

+

Pro ostatní příkazy použijte /help address.

+

simplex-chat

+

Přístup k historii chatu

+

SimpleX chat ukládá všechny vaše kontakty a konverzace do místní databáze SQLite, takže jsou soukromé a přenosné, vlastněné a kontrolované uživatelem.

+

Historii chatu můžete zobrazit a prohledávat dotazem do databáze. Spusťte níže uvedený skript pro vytvoření zobrazení zpráv ve vaší databázi.

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/scripts/message_views.sql | sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

Otevřete SQLite Command Line Shell:

+
sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

Příklady viz Message queries.

+
+

Upozornění: Omezení cizích klíčů SQLite jsou ve výchozím nastavení vypnuta a musí být povolena pro každé připojení k databázi zvlášť. Toho lze dosáhnout spuštěním příkazu PRAGMA foreign_keys = ON; na otevřeném databázovém připojení. Spouštěním dotazů měnících data bez předchozího povolení cizích klíčů můžete riskovat, že se databáze dostane do nekonzistentního stavu.

+
+

Pohodlné dotazy

+

Získat všechny zprávy z dnešního dne (chat_dt je v UTC):

+
select * from all_messages_plain where date(chat_dt) > date('now', '-1 day') order by chat_dt;
+
+

Získejte ranní noční zprávy:

+
select * from all_messages_plain where chat_dt > datetime('now', '-15 hours') order by chat_dt;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/contributing.html b/docs/lang/cs/contributing.html new file mode 100644 index 0000000000..92d0cf3807 --- /dev/null +++ b/docs/lang/cs/contributing.html @@ -0,0 +1,791 @@ + + + + + + + + + Průvodce přispíváním + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 31.01.2023 | Jazyky: CZ, EN, FR |

+

Průvodce přispíváním

+

Kompilace s povoleným šifrováním SQLCipher

+

Do kořenového adresáře projektu přidejte cabal.project.local s umístěním hlaviček a knihoven OpenSSL a příznakem nastavujícím režim šifrování:

+
cp scripts/cabal.project.local.mac cabal.project.local
+# nebo
+# cp scripts/cabal.project.local.linux cabal.project.local
+
+

OpenSSL na MacOS

+

Systém MacOS je standardně dodáván s LibreSSL, pro kompilaci SimpleX ze zdrojových kódů je nutné nainstalovat OpenSSL.

+

OpenSSL lze nainstalovat pomocí brew install openssl@1.1.

+

Aby vše fungovalo správně, musíte do své cesty PATH přidat /opt/homebrew/opt/openssl@1.1/bin.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/server.html b/docs/lang/cs/server.html new file mode 100644 index 0000000000..09ad3be4ff --- /dev/null +++ b/docs/lang/cs/server.html @@ -0,0 +1,1067 @@ + + + + + + + + + Hostování vlastního serveru SMP + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 31.01.2023 | Jazyky: CZ, EN, FR |

+

Hostování vlastního serveru SMP

+

Přehled

+

SMP server je relay server používaný k předávání zpráv v síti SimpleX. Aplikace SimpleX Chat mají přednastavené servery (pro mobilní aplikace jsou to smp8, smp9 a smp10.simplex.im), ale konfiguraci aplikace můžete snadno změnit a používat jiné servery.

+

Klienti SimpleX pouze určují, který server bude použit pro příjem zpráv, a to pro každý kontakt (nebo spojení skupiny s členem skupiny) zvlášť, přičemž tyto servery jsou pouze dočasné, protože adresa pro doručování se může změnit.

+

Upozornění: když změníte servery v konfiguraci aplikace, ovlivní to pouze to, který server bude použit pro nové kontakty, stávající kontakty se na nové servery automaticky nepřesunou, ale můžete je přesunout ručně pomocí tlačítka "Změnit adresu příjmu" na stránkách s informacemi o kontaktech/členech - brzy bude automatizováno.

+

Instalace

+
    +
  1. +

    Nejprve nainstalujte smp-server:

    + +
  2. +
+

Ruční instalace vyžaduje několik předběžných úkonů:

+
    +
  1. +

    Vytvoření uživatele a skupiny pro smp-server:

    +
    sudo useradd -m smp
    +
    +
  2. +
  3. +

    Vytvořte potřebné adresáře a přiřaďte jim oprávnění:

    +
    sudo mkdir -p /var/opt/simplex /etc/opt/simplex
    +sudo chown smp:smp /var/opt/simplex /etc/opt/simplex /etc/opt/simplex
    +
    +
  4. +
  5. +

    Povolte port smp-server ve firewallu:

    +
    # Pro Ubuntu
    +ufw allow 5233
    +
    +
  6. +
  7. +

    Volitelné - Pokud používáte distribuci s systemd, vytvořte soubor /etc/systemd/system/smp-server.service s následujícím obsahem:

    +
    [Unit]
    +Description=SMP server
    +[Service]
    +User=smp
    +Group=smp
    +Type=simple
    +ExecStart=smp-server start
    +ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex/smp-server-store.log" ] && cp "/var/opt/simplex/smp-server-store.log" "/var/opt/simplex/smp-server-store.log.bak"'
    +KillSignal=SIGINT
    +TimeoutStopSec=infinity
    +Restart=vždy
    +RestartSec=10
    +LimitNOFILE=65535
    +[Install]
    +WantedBy=multi-user.target
    +
    +

    A spusťte sudo systemctl daemon-reload.

    +
  8. +
+

Konfigurace

+

Chcete-li zjistit, které možnosti jsou k dispozici, spusťte smp-server bez příznaků:

+
sudo su smp -c smp-server
+
+...
+Dostupné příkazy:
+  init Inicializace serveru - vytvoří /etc/opt/simplex a
+                           /var/opt/simplex adresáře a konfigurační soubory.
+  start Spustí server (konfigurace:
+                           /etc/opt/simplex/smp-server.ini).
+  delete Odstranění konfiguračních a protokolových souborů
+
+

Další nápovědu můžete získat příkazem sudo su smp -c "smp-server <příkaz> -h"

+

Poté musíme nakonfigurovat smp-server:

+

Interaktivně

+

Spusťte následující příkaz:

+
sudo su smp -c "smp-server init"
+
+

Je třeba zvážit několik možností:

+
    +
  • +

    Povolit ukládání protokolu pro obnovení front a zpráv při restartu serveru (Yn):

    +

    Zadáním y povolíte ukládání a obnovu spojení a zpráv při restartu serveru.

    +

    Pozor: je důležité použít SIGINT pro restart serveru, protože jinak nebudou nedoručené zprávy obnoveny. Spojení budou obnovena bez ohledu na to, jakým způsobem je server restartován, protože na rozdíl od zpráv jsou při každé změně přidávána do protokolu pouze pro doplnění.

    +
  • +
  • +

    Zapnout protokolování denních statistik (yN):

    +

    Zadáním y povolíte protokolování statistik ve formátu CSV, které lze například použít k zobrazení souhrnných grafů využití v Grafanu.

    +
  • +
+

Tyto statistiky zahrnují denní počty vytvořených, zajištěných a smazaných front, odeslaných a přijatých zpráv a také denní, týdenní a měsíční počty aktivních front (tj. front, které byly použity pro nějaké zprávy). Domníváme se, že tyto informace neobsahují nic, co by umožňovalo korelovat různé fronty jako patřící stejným uživatelům, ale pokud se domníváte, že to lze nějak zneužít, dejte nám prosím důvěrně vědět.

+
    +
  • +

    Vyžadovat heslo pro vytvoření nové fronty zpráv?

    +

    Zadejte r nebo své libovolné heslo pro ochranu heslem smp-server nebo n pro vypnutí ochrany heslem.

    +
  • +
  • +

    Zadejte FQDN serveru nebo IP adresu pro certifikát (127.0.0.1):

    +

    Zadejte svou doménu nebo ip adresu, na které běží váš smp-server - bude zahrnuta do certifikátů serveru a také vypsána jako součást adresy serveru.

    +
  • +
+

Prostřednictvím voleb příkazového řádku

+

Spusťte následující příkaz:

+
sudo su smp -c "smp-server init -h"
+
+...
+Dostupné možnosti:
+  -l,--store-log Povolit protokol úložiště pro perzistenci
+  -s,--daily-stats Povolí protokolování denních statistik serveru
+  -a,--sign-algorithm ALG Algoritmus podpisu používaný pro certifikáty TLS:
+                           ED25519, ED448 (výchozí: ED448).
+  --ip IP IP adresa serveru, používaná jako Common Name pro TLS online
+                           certifikátu, pokud není zadáno FQDN
+                           (výchozí: "127.0.0.1")
+  -n,--fqdn FQDN FQDN serveru použitý jako Common Name pro certifikát TLS online
+                           certifikát
+  --no-password Povolit vytváření nových front bez hesla
+  --password PASSWORD Nastavení hesla pro vytváření nových front zpráv
+  -y,--yes Neinteraktivní inicializace pomocí příkazového řádku
+                           volby
+  -h,--help Zobrazí text nápovědy
+
+

Měli byste určit, které příznaky jsou pro váš případ použití potřebné, a poté spustit smp-server init s příznakem -y pro neinteraktivní inicializaci:

+
sudo su smp -c "smp-server init -y -<vůj příznak> <vaše volba>"
+
+

Spusťte například:

+
sudo su smp -c "smp-server init -y -l --ip 192.168.1.5 --heslo test"
+
+

a inicializujte konfiguraci smp-serveru pomocí:

+
    +
  • obnovení spojení a zpráv při restartu serveru (příznak -l),
  • +
  • IP adresa 192.168.1.5,
  • +
  • chránit smp-server heslem test.
  • +
+
+

Poté je instalace dokončena a ve výstupu teminálu byste měli vidět něco takového:

+
Certificate request self-signature ok
+subject=CN = 127.0.0.1
+Server je inicializován, konfiguraci můžete upravit v souboru /etc/opt/simplex/smp-server.ini.
+Spusťte `smp-server start` pro spuštění serveru.
+----------
+Měli byste bezpečně uložit soukromý klíč CA a odstranit jej ze serveru.
+Pokud dojde ke kompromitaci pověření TLS serveru, lze tento klíč použít k podpisu nového, přičemž zůstane zachována stejná identita serveru a navázaná spojení.
+Umístění soukromého klíče CA: /etc/opt/simplex/ca.key.
+----------
+SMP server v3.4.0
+Otisk prstu: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Adresa serveru: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+
+

Výše uvedená adresa serveru by měla být použita v konfiguraci klienta a pokud jste přidali heslo k serveru, mělo by být sdíleno s ostatními lidmi pouze tehdy, když jim chcete povolit používat váš server pro příjem zpráv (všechny vaše kontakty budou moci posílat zprávy, protože nevyžadují heslo). Pokud jste při inicializaci předali IP adresu nebo názvy hostitelů, budou vypsány jako součást adresy serveru, jinak nahraďte <hostnames> skutečnými adresami serverů.

+

Dokumentace

+

Všechny potřebné soubory pro smp-server jsou umístěny ve složce /etc/opt/simplex/.

+

Uložené zprávy, spojení, statistiky a protokol serveru jsou umístěny ve složce /var/opt/simplex/.

+

Adresa serveru SMP

+

Adresa serveru SMP má následující formát:

+
smp://<otisk prstu>[:<heslo>]@<jméno_veřejného_hostitele>[,<jméno_hostitele>]
+
+
    +
  • +

    <otisk prstu>

    +

    Váš otisk certifikátu smp-server. Otisk svého certifikátu můžete zkontrolovat v souboru /etc/opt/simplex/fingerprint.

    +
  • +
  • +

    nepovinné <heslo>

    +

    Vaše nakonfigurované heslo smp-serveru. Nakonfigurované heslo můžete zkontrolovat v souboru /etc/opt/simplex/smp-server.ini v sekci [AUTH] v poli create_password:.

    +
  • +
  • +

    <public_hostname>, volitelně <onion_hostname>.

    +

    Vaše nakonfigurované jméno (jména) hostitele smp-serveru. Nakonfigurované hostitele můžete zkontrolovat v souboru /etc/opt/simplex/smp-server.ini, v části [TRANSPORT] v poli host:.

    +
  • +
+

Příkazy Systemd

+

Chcete-li spustit smp-server při startu hostitele, spusťte:

+
sudo systemctl enable smp-server.service
+
+Vytvořen symlink /etc/systemd/system/multi-user.target.wants/smp-server.service → /etc/systemd/system/smp-server.service.
+
+

Chcete-li spustit smp-server, spusťte:

+
sudo systemctl start smp-server.service
+
+

Chcete-li zkontrolovat stav smp-serveru, spusťte:

+
sudo systemctl status smp-server.service
+
+● smp-server.service - server SMP
+     Načteno: načteno (/etc/systemd/system/smp-server.service; povoleno; předvolba dodavatele: povoleno)
+     Aktivní: aktivní (běží) od so 2022-11-23 19:23:21 UTC; před 1min 48s
+   Hlavní PID: 30878 (smp-server)
+     CGroup: /docker/5588ab759e80546b4296a7c50ffebbb1fb7b55b8401300e9201313b720989aa8/system.slice/smp-server.service
+             └─30878 smp-server start
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Spuštěn SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Adresa serveru: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Uložit protokol: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Naslouchání na portu 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: neaktivní klienti nevypršeli.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: vytváření nových front vyžaduje heslo
+
+

Chcete-li zastavit smp-server, spusťte:

+
sudo systemctl stop smp-server.service
+
+

Chcete-li zkontrolovat ocas protokolu smp-server, spusťte:

+
sudo journalctl -fu smp-server.service
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Spuštěn SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Adresa serveru: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Uložit protokol: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Naslouchání na portu 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: neaktivní klienti nevypršeli.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: vytváření nových front vyžaduje heslo
+
+

Monitoring

+

Statistiky smp-serveru pro Grafana dashboard můžete povolit nastavením hodnoty on v souboru /etc/opt/simplex/smp-server.ini v sekci [STORE_LOG] v poli log_stats:.

+

Protokoly budou uloženy jako soubor csv v souboru /var/opt/simplex/smp-server-stats.daily.log. Pole pro soubor csv jsou:

+
fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,monthMsgQueues
+
+
    +
  • +

    fromTime - časová značka; datum a čas události

    +
  • +
  • +

    qCreated - int; vytvořené fronty

    +
  • +
  • +

    qSecured - int; vytvořené fronty

    +
  • +
  • +

    qDeleted - int; smazané fronty

    +
  • +
  • +

    msgSent - int; odeslané zprávy

    +
  • +
  • +

    msgRecv - int; přijaté zprávy

    +
  • +
  • +

    dayMsgQueues - int; aktivní fronty za den

    +
  • +
  • +

    weekMsgQueues - int; aktivní fronty za týden

    +
  • +
  • +

    monthMsgQueues - int; aktivní fronty za měsíc

    +
  • +
+

Pro import csv do Grafana je třeba:

+
    +
  1. +

    Nainstalovat zásuvný modul Grafana: Grafana - CSV datasource

    +
  2. +
  3. +

    Povolit místní režim připojením následujícího:

    +
    [plugin.marcusolsson-csv-datasource].
    +allow_local_mode = true
    +
    +

    ... do /etc/grafana/grafana.ini

    +
  4. +
  5. +

    Přidejte zdroj dat CSV:

    +
      +
    • V postranní nabídce klikněte na záložku Configuration (ikona ozubeného kola).
    • +
    • V pravém horním rohu karty Zdroje dat klikněte na tlačítko Přidat zdroj dat.
    • +
    • Do vyhledávacího pole zadejte "CSV" a vyhledejte zdroj dat CSV.
    • +
    • Klikněte na výsledek hledání s nápisem "CSV".
    • +
    • Do pole URL zadejte soubor, který odkazuje na obsah CSV
    • +
    +
  6. +
  7. +

    Hotovo! Měli byste být schopni vytvořit vlastní řídicí panel se statistikami.

    +
  8. +
+

Další dokumentaci naleznete na adrese: CSV Data Source for Grafana - Documentation

+

Konfigurace aplikace pro použití serveru

+

Chcete-li aplikaci nakonfigurovat tak, aby používala váš server pro zasílání zpráv, zkopírujte jeho úplnou adresu včetně hesla a přidejte ji do aplikace. Máte možnost používat svůj server společně s přednastavenými servery nebo bez nich - můžete je odebrat nebo zakázat.

+

Adresu svého serveru můžete také sdílet se svými přáteli tak, že je necháte naskenovat QR kód z nastavení serveru - ten bude obsahovat heslo serveru, takže budou moci přijímat zprávy i prostřednictvím vašeho serveru.

+

Upozornění: pro podporu hesla je třeba mít SMP server verze 4.0. Pokud již máte nasazený server, můžete heslo přidat přidáním do souboru INI serveru.

+

     

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/simplex.html b/docs/lang/cs/simplex.html new file mode 100644 index 0000000000..249a35d5d2 --- /dev/null +++ b/docs/lang/cs/simplex.html @@ -0,0 +1,890 @@ + + + + + + + + + Platforma SimpleX + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 07.02.2023 | Jazyky: CZ, EN, FR |

+

Platforma SimpleX - motivace a srovnání

+

Problémy

+

Stávající chatovací platformy a protokoly mají některé nebo všechny následující problémy:

+
    +
  • Nedostatek soukromí uživatelského profilu a kontaktů (soukromí metadat).
  • +
  • Žádná ochrana (nebo pouze volitelná ochrana) implementací E2EE před útoky MITM prostřednictvím poskytovatele.
  • +
  • Nevyžádané zprávy (spam a zneužití).
  • +
  • Chybějící vlastnictví a ochrana dat.
  • +
  • Složitost použití všech necentralizovaných protokolů pro netechnické uživatele.
  • +
+

Koncentrace komunikace v malém počtu centralizovaných platforem činí řešení těchto problémů poměrně obtížným.

+ +

Navrhovaný zásobník protokolů řeší tyto problémy tím, že zprávy i kontakty jsou uloženy pouze v klientských zařízeních, čímž se role serverů omezuje na pouhé zprostředkovatele zpráv, kteří vyžadují pouze autorizaci zpráv odesílaných do front, ale NEvyžadují autentizaci uživatelů - chráněny jsou nejen zprávy, ale i metadata, protože uživatelé nemají přiřazeny žádné identifikátory - na rozdíl od jiných platforem.

+

Více informací o cílech a technickém návrhu platformy naleznete v dokumentu SimpleX whitepaper.

+

Proč používat SimpleX

+

Jedinečný přístup SimpleX k ochraně soukromí a zabezpečení

+

Každý by měl dbát na soukromí a bezpečnost své komunikace - i obyčejné konverzace vás mohou ohrozit.

+

Úplné soukromí vaší identity, profilu, kontaktů a metadat.

+

Na rozdíl od všech ostatních existujících platforem pro zasílání zpráv nemá SimpleX žádné identifikátory přiřazené uživatelům - k identifikaci svých uživatelů nepoužívá telefonní čísla (jako Signal nebo WhatsApp), adresy založené na doméně (jako e-mail, XMPP nebo Matrix), uživatelská jména (jako Telegram), veřejné klíče nebo dokonce náhodná čísla (jako všechny ostatní messengery) - ani nevíme, kolik lidí SimpleX používá.

+

K doručování zpráv místo identifikátorů uživatelů, které používají všechny ostatní platformy, používá SimpleX adresy jednosměrných (simplexních) front zpráv. Používání služby SimpleX je jako mít pro každý kontakt jinou e-mailovou adresu nebo telefonní číslo, ale bez starostí se správou všech těchto adres. V blízké budoucnosti budou aplikace SimpleX také automaticky měnit fronty zpráv a přesouvat konverzace z jednoho serveru na druhý, aby uživatelům poskytly ještě lepší soukromí.

+

Tento přístup chrání soukromí toho, s kým komunikujete, a skrývá ho před servery platformy SimpleX a před jakýmikoli pozorovateli. Své soukromí můžete dále zlepšit nastavením přístupu k síti tak, abyste se k serverům SimpleX připojovali prostřednictvím některé překryvné transportní sítě, např. sítě Tor.

+

Nejlepší ochrana proti spamu a zneužití

+

Protože na platformě SimpleX nemáte žádný identifikátor, nelze vás kontaktovat, pokud nesdílíte odkaz s jednorázovou pozvánkou nebo volitelnou dočasnou uživatelskou adresu. I v případě volitelných uživatelských adres je sice lze využít k zasílání nevyžádaných kontaktů, ale můžete je změnit nebo zcela odstranit, aniž byste přišli o jakékoli spojení.

+

Úplné vlastnictví, kontrola a zabezpečení vašich údajů

+

SimpleX ukládá všechna uživatelská data v klientských zařízeních, zprávy jsou pouze dočasně uchovávány na relay serverech SimpleX, dokud nejsou přijaty.

+

Používáme přenosný formát databáze, který lze použít na všech podporovaných zařízeních - brzy přidáme možnost exportovat databázi chatu z mobilní aplikace, aby ji bylo možné použít na jiném zařízení.

+

Na rozdíl od serverů federativních sítí (e-mail, XMPP nebo Matrix) servery SimpleX neukládají uživatelské účty, pouze předávají zprávy příjemcům, čímž chrání soukromí obou stran. Mezi odesílaným a přijímaným provozem serveru nejsou žádné společné identifikátory ani šifrované zprávy, a to díky dodatečné vrstvě šifrování doručovaných zpráv. Pokud tedy kdokoli sleduje provoz serveru, nemůže snadno zjistit, kdo s kým komunikuje (známé útoky na korelaci provozu viz SimpleX whitepaper).

+

Uživatelé vlastní síť SimpleX

+

Můžete používat SimpleX s vlastními servery a přitom komunikovat s lidmi, kteří používají servery předkonfigurované v aplikacích nebo jakékoli jiné servery SimpleX.

+

Platforma SimpleX používá otevřený protokol a poskytuje SDK pro vytváření chatovacích botů, což umožňuje implementaci služeb, s nimiž mohou uživatelé komunikovat prostřednictvím aplikací SimpleX Chat - opravdu se těšíme, jaké služby SimpleX bude možné vytvořit.

+

Pokud uvažujete o vývoji s platformou SimpleX, ať už jde o služby chatovacích botů pro uživatele aplikací SimpleX, nebo o integraci knihovny SimpleX Chat do vašich mobilních aplikací, obraťte se na nás pro případné rady a podporu.

+

Srovnání s jinými protokoly

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SimpleX chatSignal, big platformsXMPP, MatrixP2P protocols
Vyžaduje uživatelské identifikátoryNe = privateAno1Ano2Yes3
Možnost MITM útokuŽádná = bezpečnéAno4AnoAno
Závislost na DNSNe = neumlčitelnéAnoAnoNe
Single operator or networkNe = decentralizovanéAnoNeAno5
Centrální součást nebo jiný celosíťový útokNe = neumlčitelnéAnoAno2Ano6
+
    +
  1. Obvykle na základě telefonního čísla, v některých případech na základě uživatelských jmen.
  2. +
  3. Založeno na DNS.
  4. +
  5. Veřejný klíč nebo jiné globálně jedinečné ID.
  6. +
  7. Pokud jsou servery provozovatele kompromitovány.
  8. +
  9. Sítě P2P a sítě založené na kryptoměnách jsou sice distribuované, ale nejsou decentralizované - fungují jako jediná síť s jediným jmenným prostorem uživatelských adres.
  10. +
  11. Sítě P2P mají buď centrální autoritu, nebo může být kompromitována celá síť - viz následující část.
  12. +
+

Srovnání s protokoly pro zasílání zpráv P2P.

+

Existuje několik protokolů P2P pro chatování/zprávy a jejich implementací, jejichž cílem je vyřešit problém soukromí a centralizace, ale mají svůj vlastní soubor problémů, kvůli kterým jsou méně spolehlivé než navrhovaný návrh, složitější na implementaci a analýzu a zranitelnější vůči útokům.

+
    +
  1. +

    Sítě P2P používají k směrování zpráv/požadavků v síti některou variantu DHT. Implementace DHT mají složité návrhy, které musí vyvažovat spolehlivost, záruku doručení a latenci. Navrhovaný návrh má lepší záruky doručení i nižší latenci (zpráva je předávána vícekrát paralelně, pokaždé přes jeden uzel, přičemž se používají servery vybrané příjemcem, zatímco v sítích P2P je zpráva předávána přes O(log N) uzlů postupně, přičemž se používají uzly vybrané algoritmem).

    +
  2. +
  3. +

    Navrhovaný návrh na rozdíl od většiny sítí P2P nemá žádné globální identifikátory uživatelů, a to ani dočasné.

    +
  4. +
  5. +

    P2P samo o sobě neřeší problém útoku MITM a většina existujících řešení nepoužívá pro počáteční výměnu klíčů zprávy mimo pásmo. Navrhované řešení využívá pro počáteční výměnu klíčů zprávy mimo pásmo nebo v některých případech již existující bezpečná a důvěryhodná spojení.

    +
  6. +
  7. +

    Implementace P2P mohou být blokovány některými poskytovateli internetu (jako například BitTorrent). Navrhovaný návrh je transportně agnostický - může fungovat přes standardní webové protokoly a servery mohou být nasazeny na stejných doménách jako webové stránky.

    +
  8. +
  9. +

    Všechny známé sítě P2P jsou pravděpodobně zranitelné vůči Sybilovu útoku, protože každý uzel je zjistitelný a síť funguje jako celek. Známá opatření ke snížení pravděpodobnosti Sybilova útoku buď vyžadují centralizovanou složku, nebo nákladný proof of work. Navrhovaný návrh naopak nemá žádnou zjistitelnost serverů - servery nejsou propojeny, nejsou známy navzájem ani všem klientům. Síť SimpleX je fragmentovaná a funguje jako několik izolovaných spojení. To znemožňuje útoky na celou síť SimpleX - i když jsou některé servery kompromitovány, ostatní části sítě mohou fungovat normálně a postižení klienti mohou přejít na používání jiných serverů, aniž by ztratili kontakty nebo zprávy.

    +
  10. +
  11. +

    Sítě P2P jsou pravděpodobně zranitelné vůči útoku DRDoS. V navrhovaném návrhu klienti pouze předávají provoz ze známého důvěryhodného spojení a nelze je použít k odrážení a zesilování provozu v celé síti.

    +
  12. +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/sql.html b/docs/lang/cs/sql.html new file mode 100644 index 0000000000..0e8d6bec29 --- /dev/null +++ b/docs/lang/cs/sql.html @@ -0,0 +1,825 @@ + + + + + + + + + Přístup ke zprávám v databázi + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 31.01.2023 | Jazyky: CZ, EN, FR |

+

Přístup ke zprávám v databázi

+

Dešifrování databází

+

Chcete-li zobrazit data v databázi, musíte je nejprve dešifrovat. Nainstalujte sqlcipher pomocí svého oblíbeného správce balíčků a v adresáři s databázemi spusťte následující příkazy:

+
sqlcipher files_chat.db
+pragma key="youDecryptionPassphrase";
+# Ujistěte se, že vše funguje správně
+select * from users;
+
+

Pokud se zobrazí Parse error: no such table: users, ujistěte se, že jste zadali správnou přístupovou frázi a že jste ji v aplikaci pro Android změnili z náhodné (pokud jste tuto databázi získali ze zařízení s Androidem, samozřejmě).

+

SQL dotazy

+

Můžete spouštět dotazy proti direct_messages, group_messages a all_messages (nebo jejich jednodušším alternativám direct_messages_plain, group_messages_plain a all_messages_plain), např:

+
-- tato nebo vámi preferovaná nastavení můžete vložit do souboru ~/.sqliterc
+-- aby přetrvaly napříč relacemi klienta sqlite3
+.mode column
+.headers on
+.nullvalue NULL
+
+-- jednoduché pohledy na direct, group a all_messages
+-- s deduplikací uživatelských zpráv pro group a all_messages;
+-- pouze události chatu 'x.msg.new' ("nová zpráva") - filtruje události služby;
+-- msg_sent je 0 pro přijaté, 1 pro odeslané
+select * from direct_messages_plain;
+select * from group_messages_plain;
+select * from all_messages_plain;
+
+-- dotaz na další podrobnosti historie chatu pomocí běžného SQL, například:
+-- soubory, které jste nabídli k odeslání
+select * from direct_messages where msg_sent = 1 and chat_msg_event = 'x.file';
+-- vše, co catherine poslala v souvislosti s kočkami
+select * from direct_messages where msg_sent = 0 and contact = 'catherine' and msg_body like '%cats%';
+-- veškerá korespondence s alice v #teamu
+select * from group_messages where group_name = 'team' and contact = 'alice';
+
+-- shrňte data z chatu
+select contact_or_group, num_messages from (
+  select
+    contact as contact_or_group, count(1) as num_messages
+    from direct_messages_plain group by contact
+  union
+  select
+    group_name as contact_or_group, count(1) as num_messages
+    from group_messages_plain group by group_name
+)
+order by num_messages desc;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/translations.html b/docs/lang/cs/translations.html new file mode 100644 index 0000000000..855c9f7a92 --- /dev/null +++ b/docs/lang/cs/translations.html @@ -0,0 +1,843 @@ + + + + + + + + + Přispívání překladů do SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 07.02.2023 | Jazyky: CZ, EN |

+

Přispívání překladů do SimpleX Chat

+

Obrovské díky za váš zájem o překlady SimpleX Chat - velmi nám to pomáhá zpřístupnit jej širšímu okruhu uživatelů a vaší pomoci si opravdu vážíme.

+

Vyžaduje to značnou časovou investici - většina lidí ji zpočátku podceňuje - a průběžnou údržbu v průběhu vývoje aplikace.

+

Tento dokument vznikl proto, abychom tento proces urychlili, a podělili se s vámi o některé důležité "háčky", které jsme objevili při práci s Weblate - platformou, kterou používáme pro překlady rozhraní.

+

Než začnete překládat

+
    +
  1. +

    Vytvořte si účet na Weblate a použijte stejný e-mail, který používáte na GitHubu - díky tomu budou vaše příspěvky spojeny s vaším účtem na GitHubu a v některých případech vám to může pomoci. Jakmile bude překlad uvolněn pro uživatele, přidáme jméno vašeho účtu do seznamu překladatelů.

    +
  2. +
  3. +

    Před zahájením překladu je třeba podepsat jednoduchou smlouvu s přispěvatelem prostřednictvím Weblate - to proto, aby se předešlo případným konfliktům kolem práv duševního vlastnictví.

    +
  4. +
  5. +

    Můžeme vás také přidat do skupiny překladatelů pro případné dotazy a aktualizace - spojte se se mnou přes chat.

    +
  6. +
+

Průběh překladu

+
    +
  1. +

    Začněte prosím od aplikace pro Android, a to jak při časově nejnáročnějším počátečním překladu, tak při pozdějším přidávání případných řetězců. Za prvé, řetězce pro iOS se mohou ve Weblate objevit s určitým zpožděním, protože to od nás vyžaduje ruční krok, než se zobrazí. Zadruhé, aplikace Android je nastavena jako slovník pro aplikaci iOS a 2/3 všech řetězců vyžadují jen kliknutí pro jejich převod z Androidu do iOS (to ještě nějakou dobu trvá, Weblate to bohužel neautomatizuje).

    +
  2. +
  3. +

    Některé řetězce není třeba překládat, ale přesto je třeba je překopírovat - v uživatelském rozhraní Weblate je k tomu tlačítko:

    +
  4. +
+weblate: zkopírovat zdroj do překladu +
    +
  1. +

    Weblate má také automatické návrhy, které mohou proces urychlit. Někdy je lze použít tak, jak jsou, jindy je třeba je upravit - kliknutím je použijete v překladu.

    +
  2. +
  3. +

    Jakmile jsou všechny řetězce v aplikaci pro Android přeloženy, zkontrolujte je, abyste zajistili konzistentní styl a jazyk, aby se pro podobné uživatelské akce důsledně používala stejná slova jako v angličtině. Někdy budete muset použít různá slova v případech, kdy angličtina má jen jedno, snažte se prosím tyto volby používat důsledně v podobných kontextech, aby to bylo pro koncové uživatele jednodušší.

    +
  4. +
  5. +

    Při překladu aplikace pro iOS je velká část řetězců naprosto stejná - lze je jedním kliknutím překopírovat do sekce glosář. Vizuální nápovědou, že to lze provést, je to, že celý zdrojový řetězec je zvýrazněn žlutě. Mnoho dalších řetězců je velmi podobných, liší se pouze syntaxí interpolace nebo způsobem použití tučného písma - vyžadují minimální úpravy. Existují některé řetězce, které jsou jedinečné pro platformu iOS - ty je třeba přeložit zvlášť.

    +
  6. +
+weblate: automatické návrhy +

Po dokončení překladu

+

Jakmile budou aplikace pro Android i iOS přeloženy, dejte nám prosím vědět.

+

My pak:

+
    +
  • zkontrolujeme všechny překlady a navrhneme případné opravy - to také zabere trochu času :)
  • +
  • sloučíme je do zdrojového kódu - během toho bude weblate uzamčen pro změny.
  • +
  • vytvoříme beta verze aplikací pro iOS i Android - můžeme vás také přidat do interních skupin testerů, abyste mohli aplikace instalovat dříve než ostatní.
  • +
  • Vydáme ji pro naše uživatele beta verzí - jedná se o více než tisíc lidí, kteří používají naše beta verze.
  • +
  • Vydání aplikace a uvedení nového jazyka v oznámení.
  • +
+

Upozornění: pokud je to možné, snažíme se zachovat konzistentní funkce aplikace mezi platformami Android a iOS, takže nový jazyk vydáme a oznámíme, až budou obě platformy přeloženy. Neznamená to, že to musíte udělat vy, ale budeme muset počkat, až druhou platformu přeloží někdo jiný. Pokud ale začnete od Androidu, přidání iOS obvykle trvá 3-4x kratší dobu.

+

Co bude dál

+
    +
  1. +

    Jakmile budeme aplikaci aktualizovat, zveřejníme aktualizace ve skupině překladatelů. Nemáte absolutně žádnou povinnost tyto dodatečné řetězce překládat. Nesmírně si však vážíme toho, pokud tak učiníte, protože uživatelé mají mnohem lepší zážitek, když jsou závislí na vašich překladech, než když nějaká nová část aplikace přeložena není.

    +
  2. +
  3. +

    Adopci ve vaší zemi / jazykové skupině můžete pomoci také překládáním našich dokumentů - právě jsme s tím začali - a také obsahu našich webových stránek. Objevilo se mnoho žádostí o to a v současné době přidáváme překladový rámec pro webové stránky.

    +
  4. +
  5. +

    Také pokud chcete být moderátorem/adminem skupiny uživatelů ve vašem jazyce, jakmile bude aplikace přeložena, můžeme takovou skupinu hostit - připravujeme komunitní směrnice a přidáváme do aplikace některé moderátorské nástroje, které budou vydány v březnu ve verzi v5.

    +
  6. +
+

Ještě jednou děkujeme, že nám pomáháte rozvíjet SimpleX Chat!

+

Evgeny, zakladatel SimpleX Chat.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/cs/webrtc.html b/docs/lang/cs/webrtc.html new file mode 100644 index 0000000000..d958ade34a --- /dev/null +++ b/docs/lang/cs/webrtc.html @@ -0,0 +1,912 @@ + + + + + + + + + Použití vlastních serverů WebRTC ICE v SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Aktualizováno 31.01.2023 | Jazyky: CZ, EN, FR |

+

Použití vlastních serverů WebRTC ICE v SimpleX Chat

+

Nasazení serveru STUN/TURN

+

V tomto průvodci budeme používat nejvybavenější a nejosvědčenější implementaci serveru STUN/TURN - coturn a Ubuntu 20.04 LTS distribuci Linuxu.

+
    +
  1. +

    Získejte certifikáty stun.$Vaše_doména a turn.$Vaše_doména.

    +

    Používáme Let's Encrypt.

    +
  2. +
  3. +

    Nainstalujte balíček coturn z hlavního repozitáře.

    +
  4. +
+
apt update && apt install coturn`.
+
+
    +
  1. Odkomentujte TURNSERVER_ENABLED=1 z /etc/default/coturn:
  2. +
+
sed -i '/TURN/s/^#//g' /etc/default/coturn
+
+
    +
  1. +

    Konfigurace coturn v souboru /etc/turnserver.conf:

    +

    Viz také komentáře k jednotlivým volbám.

    +
  2. +
+
# Naslouchejte také na portu 443 pro tls.
+alt-tls-listening-port=443
+# Použijte otisky prstů ve zprávách TURN
+fingerprint
+# Použijte mechanismus dlouhodobých pověření
+lt-cred-mech
+# Vaše pověření
+user=$YOUR_LOGIN:$YOUR_PASSWORD
+# Vaše doména serveru
+server-name=$YOUR_DOMAIN
+# Výchozí sféra, která bude použita pro uživatele, pokud nebyl nalezen explicitní vztah origin/realm
+realm=$YOUR_DOMAIN
+# Cesta k vašim certifikátům. Ujistěte se, že jsou čitelné pro proces cotun user/group
+cert=/var/lib/turn/cert.pem
+pkey=/var/lib/turn/key.pem
+# Použijte 2066 bitů předdefinovaného DH klíče TLS
+dh2066
+# Přihlaste se do journalctl
+syslog
+# Uživatel/skupina, která bude provozovat službu coturn
+proc-user=turnserver
+proc-group=turnserver
+# Zakázat slabé šifrování
+no-tlsv1
+no-tlsv1_1
+no-tlsv1_2
+
+
    +
  1. Spusťte a povolte službu coturn:
  2. +
+
systemctl enable coturn && systemctl start coturn
+
+
    +
  1. Pokud používáte firewall ufw, otevřete případně příslušné porty:
  2. +
+
    +
  • 3478 - "obyčejný" TURN/STUN;
  • +
  • 5349 - TURN/STUN přes TLS;
  • +
  • 443 - TURN/STUN přes TLS, který může obejít brány firewall;
  • +
  • 49152:65535 - rozsah portů, který bude společnost Coturn ve výchozím nastavení používat pro přenos TURN.
  • +
+
ufw allow 3478 && \
+ufw allow 443 && \
+ufw allow 5349 && \
+ufw allow 49152:65535/tcp && \
+ufw allow 49152:65535/udp
+
+

Konfigurace mobilních aplikací

+

Konfigurace mobilní aplikace pro použití vašeho serveru:

+
    +
  1. +

    Otevřete Nastavení / Síť a servery / WebRTC ICE servery a přepněte přepínač Konfigurovat ICE servery.

    +
  2. +
  3. +

    Do pole zadejte všechny adresy serverů, jednu na řádek, například pokud máte servery na portu 5349:

    +
  4. +
+
stun:stun.example.com:5349
+turn:username:password@turn.example.com:5349
+
+

To je vše - nyní můžete uskutečňovat audio a video hovory prostřednictvím vlastního serveru, aniž byste s našimi servery sdíleli jakákoli data (kromě výměny klíčů s kontaktem v šifrovaných zprávách E2E).

+

Řešení problémů

+
    +
  • +

    Zjistěte, zda je server dostupný:

    +

    Spusťte tento příkaz v terminálu:

    +
    ping <vaše_ip_nebo_doména>
    +
    +

    Pokud jsou pakety přenášeny, server je v provozu!

    +
  • +
  • +

    Zjistěte, zda jsou otevřené porty:

    +

    Spusťte tento příkaz v terminálu:

    +
    nc -zvw10 <vaše_ip_nebo_doména> 443 5349
    +
    +

    Měli byste vidět:

    +
    Připojení k portu <vaše_ip_nebo_doména> 443 [tcp/https] se podařilo!
    +Připojení k <vaše_ip_nebo_doména> 5349 port [tcp/*] uspělo!
    +
    +
  • +
  • +

    Test připojení STUN/TURN:

    +
      +
    1. +

      Přejděte na IceTest.

      +
    2. +
    3. +

      Do části Sestavit seznam serverů ICE přidejte:

      +

      .

      +
        +
      • STUN: stun:<vaše_ip_nebo_doména>:<port> a stiskněte Add STUN.
      • +
      • TURN: turn:<vaše_ip_nebo_doména>:<port>, Username: <vaše_přihlašovací jméno>, Credential: <vaš_pas> a stiskněte Add TURN
      • +
      +

      Kde <port> je 443 nebo 5349.

      +
    4. +
    5. +

      Měli byste vidět své servery v sekci ICE server list. Pokud je vše správně nastaveno, stiskněte Start test:

      + +
    6. +
    7. +

      V části Výsledky byste měli vidět něco takového:

      + +

      Pokud výsledky zobrazují kandidáty srflx a relay, je vše nastaveno správně!

      +
    8. +
    +
  • +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/android.html b/docs/lang/fr/android.html new file mode 100644 index 0000000000..3c7f6d2253 --- /dev/null +++ b/docs/lang/fr/android.html @@ -0,0 +1,813 @@ + + + + + + + + + Accès aux fichiers dans l'application Android + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 07.02.2023 | FR, EN, CZ |

+

Accès aux fichiers dans l'application Android

+

SimpleX utilise des bases de données et stocke ses préférences dans le répertoire de données privées d'Android. Ce répertoire contient

+
    +
  • des bases de données
  • +
  • les fichiers envoyés et reçus
  • +
  • les fichiers temporaires qui seront supprimés lorsqu'ils ne sont pas nécessaires
  • +
  • les préférences de l'utilisateur.
  • +
+

Si vous voulez voir ce qui est stocké dans le répertoire de données de SimpleX, vous devez avoir :

+
    +
  • Un système d'exploitation Unix (ou MinGW sous Windows)
  • +
  • l'outil ADB (Android Debug Bridge) installé sur un ordinateur (téléchargez-le ici et installez-le)
  • +
  • votre appareil connecté via USB ou Wi-Fi à l'ordinateur.
  • +
+

La procédure :

+
    +
  • Ouvrez SimpleX, allez dans Phrase secrète et exportation de la base de données, activez Sauvegarde des données de l'app. Cela permettra aux autres étapes de fonctionner
  • +
  • optionnel_ : si vous voulez voir le contenu de la base de données, changez la phrase secrète de la base de données aléatoire pour la vôtre. Pour ce faire, arrêtez le chat dans le menu "Phrase secrète et exportation de la base de données", ouvrez "Phrase secrète de la base de données", entrez la nouvelle phrase secrète et confirmez-la, puis mettez-la à jour. Ne l'oubliez pas, sinon vous perdrez toutes vos données au cas où la phrase d'authentification vous serait redemandée plus tard.
  • +
  • ouvrez un émulateur de terminal (Windows CMD/Powershell ne fonctionnera pas) et changez de répertoire pour celui que vous voulez utiliser pour stocker la sauvegarde :
  • +
+
cd /tmp  # juste un exemple
+
+

Exécutez ensuite la méthode suivante :

+
adb -d backup -f chat.ab -noapk chat.simplex.app && 
+tail -n +5 chat.ab > chat.dat && 
+printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - chat.dat > chat.gz && 
+tar -xvzf chat.gz
+
+

Déverrouillez maintenant l'appareil et confirmez une opération de sauvegarde sans utiliser de mot de passe pour le chiffrement, sinon les commandes ne fonctionneront pas.

+

Ensuite, la sauvegarde doit être terminée. Si vous voyez une erreur disant tar : Error is not recoverable : exiting now mais qu'avant cela vous avez enregistré quelques noms de fichiers, ne vous inquiétez pas, tout va bien.

+

Maintenant les fichiers sauvegardés seront dans ./apps/chat.simplex.app/.

+

Veuillez noter que si vous utilisez une version récente de SimpleX, les bases de données seront chiffrées, et vous ne pourrez pas en voir le contenu sans utiliser l'application sqlcipher et sans connaître la phrase secrète de déchiffrement (vous devez d'abord la changer pour la vôtre à partir de celle qui est générée aléatoirement dans l'application).

+

Veuillez suivre le guide SQL.md pour plus d'informations sur la manière de déchiffrer vos bases de données et d'y effectuer des requêtes.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/cli.html b/docs/lang/fr/cli.html new file mode 100644 index 0000000000..52156af70f --- /dev/null +++ b/docs/lang/fr/cli.html @@ -0,0 +1,957 @@ + + + + + + + + + Application de terminal + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 31.01.2023 | FR, EN, CZ |

+

Application de terminal (console) SimpleX Chat pour Linux/MacOS/Windows

+

Table des matières

+ +

Fonctionnalités du terminal de chat

+
    +
  • Chat individuel avec plusieurs personnes dans la même fenêtre de terminal.
  • +
  • Messagerie de groupe.
  • +
  • Envoi de fichiers aux contacts et aux groupes.
  • +
  • Adresses de contact des utilisateurs - établissez des connexions via des liens de contact à usage multiple.
  • +
  • Les messages sont conservés dans une base de données SQLite locale.
  • +
  • Nom du destinataire auto-rempli - il suffit de taper vos messages pour répondre à l'expéditeur une fois la connexion établie.
  • +
  • Des serveurs SMP de démonstration sont disponibles et préconfigurés dans l'application - ou vous pouvez déployer votre propre serveur.
  • +
  • Pas d'identité globale ni de noms visibles par le.s serveur.s, ce qui garantit la confidentialité totale de vos contacts et de vos conversations.
  • +
  • Deux couches de chiffrement E2E (double ratchet pour les connexions duplex, utilisant un accord de clé X3DH avec des clés Curve448 éphémères, et NaCl crypto_box pour les files d'attente SMP, utilisant des clés Curve25519) et transmission hors bande des clés des destinataires (voir Comment utiliser SimpleX chat).
  • +
  • Validation de l'intégrité du message (en incluant les résumés des messages précédents).
  • +
  • Authentification de chaque commande/message par les serveurs SMP avec des clés Ed448 générées automatiquement.
  • +
  • Chiffrement de transport TLS 1.3.
  • +
  • Chiffrement supplémentaire des messages du serveur SMP au destinataire pour réduire la corrélation du trafic.
  • +
+

Les clés publiques impliquées dans l'échange de clés ne sont pas utilisées comme identité, elles sont générées aléatoirement pour chaque contact.

+

Voir les primitives de chiffrement utilisées pour les détails techniques.

+

+

🚀 Installation

+

Télécharger le client de chat

+

Linux et MacOS

+

Pour installer ou mettre à jour simplex-chat, vous devez exécuter le script d'installation. Pour ce faire, utilisez la commande cURL ou Wget suivante :

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+
wget -qO- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+

Une fois le client de chat téléchargé, vous pouvez le lancer avec la commande simplex-chat dans votre terminal.

+

Vous pouvez également télécharger manuellement une version binary de chat pour votre système à partir de la [dernière version stable] (https://github.com/simplex-chat/simplex-chat/releases) et le rendre exécutable comme indiqué ci-dessous.

+
chmod +x <binary>
+mv <binary> ~/.local/bin/simplex-chat
+
+

(ou tout autre emplacement préféré sur PATH).

+

Sous MacOS, vous devez également autoriser Gatekeeper à l'exécuter.

+

Windows

+
move <binary> %APPDATA%/local/bin/simplex-chat.exe
+
+

Compiler depuis la source

+
+

Veuillez noter : pour compiler l'application, utilisez le code source de la branche stable.

+
+

Utiliser Docker

+

Sous Linux, vous pouvez compiler l'exécutable du chat en utilisant docker build with custom output :

+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+DOCKER_BUILDKIT=1 docker build --output ~/.local/bin .
+
+
+

Veuillez noter : Si vous rencontrez l'erreur version `GLIBC_2.28' non trouvée, reconstruisez-le avec l'image de base haskell:8.10.7-stretch(changez-la dans votre Dockerfile local).

+
+

Utiliser Haskell stack

+

(sur n'importe quel OS)

+
    +
  1. Installer Haskell GHCup, GHC 8.10.7 et cabal :
  2. +
+
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
+
+
    +
  1. Compiler le projet :
  2. +
+
git clone git@github.com:simplex-chat/simplex-chat.git
+cd simplex-chat
+git checkout stable
+# sur Linux
+apt-get update && apt-get install -y build-essential libgmp3-dev zlib1g-dev
+cp scripts/cabal.project.local.linux cabal.project.local
+# ou sur MacOS:
+# brew install openssl@1.1
+# cp scripts/cabal.project.local.mac cabal.project.local
+# vous devrez peut-être modifier cabal.project.local pour indiquer l'emplacement réel d'openssl
+cabal update
+cabal install
+
+

Utilisation

+

Lancement du client de chat

+

Pour démarrer le client de chat, exécutez simplex-chat depuis le terminal.

+

Par défaut, le répertoire de données de l'application est créé dans le répertoire personnel (~/.simplex, ou %APPDATA%/simplex sous Windows), et deux fichiers de base de données SQLite simplex_v1_chat.db et simplex_v1_agent.db y sont initialisés.

+

Pour spécifier un préfixe de chemin de fichier différent pour les fichiers de la base de données, utilisez l'option de ligne de commande -d :

+
$ simplex-chat -d alice
+
+

L'exécution ci-dessus, par exemple, créera les fichiers de base de données alice_v1_chat.db et alice_v1_agent.db dans le répertoire actuel.

+

Trois serveurs SMP par défaut sont hébergés sur Linode - ils sont pré-configurés dans l'application.

+

Si vous avez déployé votre propre serveur SMP, vous pouvez configurer le client via l'option -s :

+
$ simplex-chat -s smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@smp.example.com
+
+

La chaîne encodée en Base64url qui précède l'adresse du serveur est l'empreinte du certificat hors ligne du serveur qui est validée par le client lors du handshake TLS.

+

Vous pouvez toujours parler aux gens en utilisant le serveur par défaut ou tout autre serveur - cela n'affecte que l'emplacement de la file d'attente des messages lorsque vous initiez la connexion (et la file d'attente des réponses peut se trouver sur un autre serveur, comme défini par le client de l'autre coté).

+

Exécutez simplex-chat -h pour voir toutes les options disponibles.

+

Accéder aux serveurs de messagerie via Tor

+

Installez Tor et exécutez-le en tant que proxy SOCKS5 sur le port 9050, par exemple sur Mac vous pouvez :

+
brew install tor
+brew services start tor
+
+

Utilisez l'option -x pour accéder aux serveurs via Tor :

+
simplex-chat -x
+
+

Vous pouvez également utiliser l'option --socks-proxy=ipv4:port ou --socks-proxy=:port pour configurer l'hôte et le port de votre proxy SOCKS5, par exemple si vous l'exécutez sur un autre hôte ou port.

+

Comment utiliser SimpleX chat

+

Une fois que vous aurez lancé le chat, vous serez invité à indiquer un "nom d'affichage" et un "nom complet" facultatif pour créer un profil de chat local. Votre nom d'affichage est un alias par lequel vos contacts peuvent se référer à vous. Il n'est pas unique et ne sert pas d'identité globale. Si certains de vos contacts ont choisi le même nom d'affichage, le client de chat ajoute un suffixe numérique à leur nom d'affichage local.

+

Le schéma ci-dessous montre comment connecter et envoyer un message à un contact :

+
+ +
+

Une fois que vous avez configuré votre profil local, entrez /c (pour /connect) pour créer une nouvelle connexion et générer une invitation. Envoyez cette invitation à votre contact via n'importe quel autre canal.

+

Vous pouvez créer plusieurs invitations en saisissant plusieurs fois la commande /connect et en envoyant ces invitations aux contacts correspondants avec lesquels vous souhaitez vous connecter.

+

L'invitation ne peut être utilisée qu'une seule fois et même si elle est interceptée, l'attaquant ne pourra pas l'utiliser pour vous envoyer les messages via cette file d'attente une fois que votre contact aura confirmé que la connexion est établie. Voir le protocole de l'agent pour une explication du format d'invitation.

+

Le contact qui a reçu l'invitation doit saisir /c <invitation> pour accepter la connexion. La connexion est alors établie, et les deux parties sont notifiées.

+

Ils utiliseraient alors les commandes @<name> <message> pour envoyer des messages. Vous pouvez aussi simplement commencer à taper un message pour l'envoyer au contact qui était le dernier.

+

Utilisez /help dans le chat pour voir la liste des commandes disponibles.

+

Groupes

+

Pour créer un groupe, utilisez /g <groupe>, puis ajoutez-y des contacts avec /a <groupe> <nom>. Vous pouvez ensuite envoyer des messages au groupe en entrant #<groupe> <message>. Utilisez /help groups pour d'autres commandes.

+

simplex-chat

+
+

Veuillez noter : les groupes ne sont pas stockés sur un serveur, ils sont conservés comme une liste de membres dans la base de données de l'application à qui les messages seront envoyés.

+
+

Envoi de fichiers

+

Vous pouvez envoyer un fichier à votre contact avec /f @<contact> <chemin_du_fichier> - le destinataire devra l'accepter avant qu'il ne soit envoyé. Utilisez /help files pour les autres commandes.

+

simplex-chat

+

Vous pouvez envoyer des fichiers à un groupe avec /f #<group> <chemin_du_fichier>.

+

Adresses de contact d'utilisateur

+

Comme alternative aux liens d'invitation unique, vous pouvez créer une adresse à long terme avec /ad (pour /address). L'adresse créée peut ensuite être partagée via n'importe quel canal, et utilisée par d'autres utilisateurs comme lien pour faire une demande de contact avec /c <adresse_de_contact_de_l'utilisateur>.

+

Vous pouvez accepter ou rejeter les demandes entrantes avec les commandes /ac <nom> et /rc <nom>.

+

L'adresse de l'utilisateur est "à long terme" dans le sens où il s'agit d'un lien de connexion à usage multiple - elle peut être utilisée jusqu'à ce qu'elle soit supprimée par l'utilisateur, auquel cas toutes les connexions établies resteront actives (contrairement à ce qui se passe avec le courrier électronique, où le changement d'adresse empêche les gens de vous envoyer des messages).

+

Utilisez /help address pour les autres commandes.

+

simplex-chat

+

Accéder à l'historique des chats

+

SimpleX chat stocke tous vos contacts et conversations dans une base de données SQLite locale, ce qui la rend privée et portable par définition, appartenant et contrôlée par l'utilisateur.

+

Vous pouvez visualiser et rechercher votre historique de chat en interrogeant votre base de données. Exécutez le script ci-dessous pour créer des aperçus de messages dans votre base de données.

+
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/scripts/message_views.sql | sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

Ouvrir un terminal de commande SQLite :

+
sqlite3 ~/.simplex/simplex_v1_chat.db
+
+

Voir les requêtes de message à titre d'exemple.

+
+

Veuillez noter : Les contraintes de clé étrangère SQLite sont désactivées par défaut, et doivent être activé séparément pour chaque connexion de base de données. Cette dernière peut être réalisée en exécutant la commande PRAGMA foreign_keys = ON; sur une connexion de base de données ouverte. En exécutant des requêtes modifiant les données sans activer les clés étrangères au préalable, vous risquez de mettre votre base de données dans un état inconsistant.

+
+

Requêtes de commodité

+

Pour recevoir tous les messages du jour (chat_dt est en UTC) :

+
select * from all_messages_plain where date(chat_dt) > date('now', '-1 day') order by chat_dt;
+
+

Pour recevoir les messages de la nuit dans la matinée :

+
select * from all_messages_plain where chat_dt > datetime('now', '-15 hours') order by chat_dt;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/contributing.html b/docs/lang/fr/contributing.html new file mode 100644 index 0000000000..618f6035c7 --- /dev/null +++ b/docs/lang/fr/contributing.html @@ -0,0 +1,791 @@ + + + + + + + + + Guide pour contribuer + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 31.01.2023 | FR, EN, CZ |

+

Guide pour contribuer

+

Compiler avec le chiffrement SQLCipher activé

+

Ajoutez cabal.project.local à la racine du projet avec les emplacements des en-têtes et des bibliothèques OpenSSL ainsi que le paramètre définissant le mode de chiffrement :

+
cp scripts/cabal.project.local.mac cabal.project.local
+# or
+# cp scripts/cabal.project.local.linux cabal.project.local
+
+

OpenSSL sur MacOS

+

LibreSSL est fourni par défaut sur MacOS, OpenSSL doit être installé pour compiler SimpleX à partir de la source.

+

OpenSSL peut être installé avec brew install openssl@1.1

+

Vous devez ajouter /opt/homebrew/opt/openssl@1.1/bin à votre PATH pour que tout fonctionne correctement.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/server.html b/docs/lang/fr/server.html new file mode 100644 index 0000000000..40e14ece34 --- /dev/null +++ b/docs/lang/fr/server.html @@ -0,0 +1,1067 @@ + + + + + + + + + Héberger votre propre serveur SMP + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 31.01.2023 | FR, EN, CZ |

+

Héberger votre propre serveur SMP

+

Présentation générale

+

Un serveur SMP est un serveur relais utilisé pour transmettre les messages sur le réseau SimpleX. Les apps SimpleX Chat ont des serveurs prédéfinis (pour les apps mobiles, smp8, smp9 et smp10.simplex.im), mais vous pouvez facilement modifier la configuration de l'app pour utiliser d'autres serveurs.

+

Seuls les utilisateurs de SimpleX déterminent quel serveur est utilisé pour recevoir les messages, séparément pour chaque contact (ou pour chaque connexion à un membre d'un groupe), et ces serveurs ne sont que temporaires, car l'adresse de réception peut changer.

+

Veuillez noter : lorsque vous modifiez les serveurs dans la configuration de l'app, cela n'affecte que les serveurs qui seront utilisés pour les nouveaux contacts. Les contacts existants ne seront pas automatiquement déplacés vers les nouveaux serveurs, mais vous pouvez les déplacer manuellement à l'aide du bouton "Changer d'adresse de réception" sur les fiches d'information de contact/membre – ce sera bientôt automatisé.

+

Installation

+
    +
  1. +

    Tout d'abord, installez smp-server:

    + +
  2. +
+

L'installation manuelle nécessite quelques actions préalables :

+
    +
  1. +

    Créer un utilisateur et un groupe pour votre smp-server:

    +
    sudo useradd -m smp
    +
    +
  2. +
  3. +

    Créer les répertoires nécessaires et y attribuer les permissions :

    +
    sudo mkdir -p /var/opt/simplex /etc/opt/simplex
    +sudo chown smp:smp /var/opt/simplex /etc/opt/simplex
    +
    +
  4. +
  5. +

    Autoriser le port du smp-server dans le pare-feu:

    +
    # Pour Ubuntu
    +ufw allow 5223
    +
    +
  6. +
  7. +

    Optionnel - Si vous utilisez une distribution avec systemd, créez le fichier /etc/systemd/system/smp-server.service avec le contenu suivant :

    +
    [Unit]
    +Description=Serveur SMP
    +[Service]
    +User=smp
    +Group=smp
    +Type=simple
    +ExecStart=smp-server start
    +ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex/smp-server-store.log" ] && cp "/var/opt/simplex/smp-server-store.log" "/var/opt/simplex/smp-server-store.log.bak"'
    +KillSignal=SIGINT
    +TimeoutStopSec=infinity
    +Restart=always
    +RestartSec=10
    +LimitNOFILE=65535
    +[Install]
    +WantedBy=multi-user.target
    +
    +

    Et exécutez sudo systemctl daemon-reload.

    +
  8. +
+

Configuration

+

Pour voir les options disponibles, exécutez smp-server sans paramètres :

+
sudo su smp -c smp-server
+
+...
+Available commands:
+  init                     Initialize server - creates /etc/opt/simplex and
+                           /var/opt/simplex directories and configuration files
+  start                    Start server (configuration:
+                           /etc/opt/simplex/smp-server.ini)
+  delete                   Delete configuration and log files
+
+

Vous pouvez obtenir de l'aide supplémentaire en exécutant sudo su smp -c "smp-server <command> -h"

+

Ensuite, nous devons configurer smp-server:

+

Interactif

+

Exécutez la commande suivante :

+
sudo su smp -c "smp-server init"
+
+

Il y a plusieurs options disponibles :

+
    +
  • +

    Enable store log to restore queues and messages on server restart (Yn):

    +

    Entrez y pour permettre la sauvegarde et la restauration des connexions et des messages lorsque le serveur est redémarré.

    +

    Veuillez noter : il est important d'utiliser SIGINT pour redémarrer le serveur, sinon les messages non distribués ne seront pas restaurés. Les connexions seront restaurées indépendamment de la façon dont le serveur est redémarré, car contrairement aux messages, elles sont ajoutées aux logs (append-only) seulement à chaque changement.

    +
  • +
  • +

    Enable logging daily statistics (yN):

    +

    Entrez y pour activer l'enregistrement des statistiques au format CSV, par exemple, elles peuvent être utilisées pour afficher des graphiques d'utilisation globale dans Grafana.

    +
  • +
+

Ces statistiques incluent le nombre quotidien de files d'attente créées, sécurisées et supprimées, de messages envoyés et reçus, ainsi que le nombre quotidien, hebdomadaire et mensuel de files d'attente actives (c'est-à-dire les files d'attente qui ont été utilisées pour des messages). Nous estimons que ces informations ne comportent aucun élément permettant de corréler différentes files d'attente comme appartenant aux mêmes utilisateurs, mais si vous pensez que cela peut être exploité de quelque manière que ce soit, veuillez nous le faire savoir, de manière confidentielle.

+
    +
  • +

    Require a password to create new messaging queues?

    +

    Entrez r ou votre mot de passe pour protéger votre smp-server, ou n pour désactiver la protection par mot de passe.

    +
  • +
  • +

    Enter server FQDN or IP address for certificate (127.0.0.1):

    +

    Entrez votre domaine ou l'adresse IP sur laquelle votre serveur smp fonctionne - elle sera incluse dans les certificats du serveur et également indiquée dans l'adresse du serveur.

    +
  • +
+

Option via ligne de commande

+

Exécutez la commande suivante :

+
sudo su smp -c "smp-server init -h"
+
+...
+Available options:
+  -l,--store-log           Enable store log for persistence
+  -s,--daily-stats         Enable logging daily server statistics
+  -a,--sign-algorithm ALG  Signature algorithm used for TLS certificates:
+                           ED25519, ED448 (default: ED448)
+  --ip IP                  Server IP address, used as Common Name for TLS online
+                           certificate if FQDN is not supplied
+                           (default: "127.0.0.1")
+  -n,--fqdn FQDN           Server FQDN used as Common Name for TLS online
+                           certificate
+  --no-password            Allow creating new queues without password
+  --password PASSWORD      Set password to create new messaging queues
+  -y,--yes                 Non-interactive initialization using command-line
+                           options
+  -h,--help                Show this help text
+
+

Vous devriez déterminer quels paramètres sont nécessaires pour votre cas d'utilisation et ensuite exécuter smp-server init avec le paramètre -y pour une initialisation non-interactive :

+
sudo su smp -c "smp-server init -y -<your flag> <your option>"
+
+

Par exemple, exécutez :

+
sudo su smp -c "smp-server init -y -l --ip 192.168.1.5 --password test"
+
+

pour initialiser votre smp-server avec comme configuration :

+
    +
  • restauration des connexions et des messages lors du redémarrage du serveur (paramètre -l),
  • +
  • adresse IP 192.168.1.5,
  • +
  • protection du smp-server avec comme mot de passe test.
  • +
+
+

Après cela, votre installation est terminée et vous devriez voir dans votre teminal quelque chose comme ceci :

+
Certificate request self-signature ok
+subject=CN = 127.0.0.1
+Server initialized, you can modify configuration in /etc/opt/simplex/smp-server.ini.
+Run `smp-server start` to start server.
+----------
+You should store CA private key securely and delete it from the server.
+If server TLS credential is compromised this key can be used to sign a new one, keeping the same server identity and established connections.
+CA private key location: /etc/opt/simplex/ca.key
+----------
+SMP server v3.4.0
+Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+
+

L'adresse du serveur ci-dessus doit être utilisée dans la configuration de votre client et si vous avez ajouté le mot de passe du serveur, il ne doit être partagé qu'avec les personnes que vous souhaitez autoriser à utiliser votre serveur pour recevoir les messages (tous vos contacts pourront envoyer des messages, car cela ne nécessite pas de mot de passe). Si vous avez fourni une adresse IP ou un nom d'hôte lors de l'initialisation, ils seront indiqués dans l'adresse du serveur, sinon remplacez <hostnames> par les adresses réelles du serveur.

+

Documentation

+

Tous les fichiers requis pour smp-server sont situés dans le dossier /etc/opt/simplex/.

+

Les messages stockés, les connexions, les statistiques et les logs du serveur sont situés dans le dossier /var/opt/simplex/.

+

Adresse de serveur SMP

+

Une adresse de serveur SMP a le format suivant :

+
smp://<fingerprint>[:<password>]@<public_hostname>[,<onion_hostname>]
+
+
    +
  • +

    <fingerprint>

    +

    Empreinte du certificat de votre smp-server. Vous pouvez vérifier l'empreinte de votre certificat dans /etc/opt/simplex/fingerprint.

    +
  • +
  • +

    optionnel <password>

    +

    Votre mot de passe configuré pour smp-server. Vous pouvez vérifier votre mot de passe configuré dans /etc/opt/simplex/smp-server.ini, sous la section [AUTH] dans le champ create_password:.

    +
  • +
  • +

    <public_hostname>, optionnel <onion_hostname>

    +

    Votre(vos) nom(s) d'hôte configuré(s) de smp-server. Vous pouvez vérifier vos hôtes configurés dans /etc/opt/simplex/smp-server.ini, dans la section [AUTH] dans le champ host:.

    +
  • +
+

Systemd commandes

+

Pour démarrer smp-server au démarrage de l'hôte, exécutez :

+
sudo systemctl enable smp-server.service
+
+Created symlink /etc/systemd/system/multi-user.target.wants/smp-server.service → /etc/systemd/system/smp-server.service.
+
+

Pour démarrer smp-server, exécutez :

+
sudo systemctl start smp-server.service
+
+

Pour vérifier l'état du smp-server, exécutez :

+
sudo systemctl status smp-server.service
+
+● smp-server.service - SMP server
+     Loaded: loaded (/etc/systemd/system/smp-server.service; enabled; vendor preset: enabled)
+     Active: active (running) since Sat 2022-11-23 19:23:21 UTC; 1min 48s ago
+   Main PID: 30878 (smp-server)
+     CGroup: /docker/5588ab759e80546b4296a7c50ffebbb1fb7b55b8401300e9201313b720989aa8/system.slice/smp-server.service
+             └─30878 smp-server start
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Started SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Store log: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Listening on port 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: not expiring inactive clients
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: creating new queues requires password
+
+

Pour arrêter smp-server, exécutez :

+
sudo systemctl stop smp-server.service
+
+

Pour vérifier la "tail" de smp-server des logs, exécutez :

+
sudo journalctl -fu smp-server.service
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Started SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Store log: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Listening on port 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: not expiring inactive clients
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: creating new queues requires password
+
+

Suivi de l'activité

+

Vous pouvez activer les statistiques de smp-server sur le tableau de bord Grafana en mettant la valeur on dans /etc/opt/simplex/smp-server.ini, sous la section [STORE_LOG] dans le champ log_stats:.

+

Les journaux seront stockés dans un fichier csv dans /var/opt/simplex/smp-server-stats.daily.log. Les champs pour le fichier csv sont :

+
fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,monthMsgQueues
+
+
    +
  • +

    fromTime - horodatage; date et heure de l'événement

    +
  • +
  • +

    qCreated - int; files d'attente créées

    +
  • +
  • +

    qSecured - int; files d'attente établies

    +
  • +
  • +

    qDeleted - int; files d'attente supprimées

    +
  • +
  • +

    msgSent - int; messages envoyés

    +
  • +
  • +

    msgRecv - int; messages reçus

    +
  • +
  • +

    dayMsgQueues - int; files d'attente actives en un jour

    +
  • +
  • +

    weekMsgQueues - int; files d'attente actives en une semaine

    +
  • +
  • +

    monthMsgQueues - int; files d'attente actives en un mois

    +
  • +
+

Pour importer du csv dans Grafana il faut :

+
    +
  1. +

    Installer le plugin Grafana : Grafana - CSV datasource

    +
  2. +
  3. +

    Autoriser le mode local en ajoutant ce qui suit :

    +
    [plugin.marcusolsson-csv-datasource]
    +allow_local_mode = true
    +
    +

    ... to /etc/grafana/grafana.ini

    +
  4. +
  5. +

    Ajouter une source de données CSV :

    +
      +
    • Dans le menu latéral, cliquez sur l'onglet Configuration (icône en forme de rouage).
    • +
    • Cliquez sur Ajouter une source de données dans le coin supérieur droit de l'onglet Sources de données.
    • +
    • Entrez "CSV" dans le champ de recherche pour trouver la source de données CSV.
    • +
    • Cliquez sur le résultat de la recherche qui indique "CSV".
    • +
    • Dans URL, entrez un fichier qui pointe vers le contenu CSV.
    • +
    +
  6. +
  7. +

    C'est fait ! Vous devriez être en mesure de créer votre propre tableau de bord avec des statistiques.

    +
  8. +
+

Pour plus de documentation, voir : CSV Data Source pour Grafana - Documentation

+

Configurer l'app pour utiliser le serveur

+

Pour configurer l'app afin d'utiliser votre serveur de messagerie, copiez son adresse complète, y compris le mot de passe, et ajoutez-la à l'application. Vous avez la possibilité d'utiliser votre serveur avec les serveurs prédéfinis ou sans eux - vous pouvez les supprimer ou les désactiver.

+

Il est également possible de partager l'adresse de votre serveur avec vos amis en leur permettant de scanner le code QR dans les paramètres du serveur. Ce code inclura le mot de passe du serveur, ce qui leur permettra aussi de recevoir des messages via votre serveur.

+

Veuillez noter : vous avez besoin de la version 4.0 du serveur SMP pour avoir le support du mot de passe. Si vous avez déjà déployé un serveur, vous pouvez ajouter le mot de passe en l'ajoutant au fichier INI du serveur.

+

     

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/simplex.html b/docs/lang/fr/simplex.html new file mode 100644 index 0000000000..e80e54dc29 --- /dev/null +++ b/docs/lang/fr/simplex.html @@ -0,0 +1,890 @@ + + + + + + + + + Plateforme SimpleX + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 07.02.2023 | FR, EN, CZ |

+

Plateforme SimpleX - motivation et comparaison

+

Problèmes

+

Les plateformes et protocoles de chat existants présentent une partie ou la totalité des problèmes suivants :

+
    +
  • Absence de confidentialité du profil et des contacts de l'utilisateur (confidentialité des métadonnées).
  • +
  • Aucune protection (ou seulement une protection optionnelle) des implémentations E2EE contre les attaques MITM via le fournisseur.
  • +
  • Messages non sollicités (spam et abus).
  • +
  • Absence de propriété et de protection des données.
  • +
  • Complexité d'utilisation de tous les protocoles non centralisés pour les utilisateurs non techniques.
  • +
+

La concentration de la communication dans un petit nombre de plateformes centralisées rend la résolution de ces problèmes assez difficile.

+

Solutions

+

Les différents protocoles proposés résolvent ces problèmes en faisant en sorte que les messages comme les contacts soit stockés exclusivement sur l'appareil client, tout en réduisant le rôle des serveurs à de simples relais de message qui ne nécessite que l'autorisation des messages envoyés dans les files d'attentes, mais qui NE nécessite PAS une authentification utilisateur - les message ne sont pas les seuls à être protégé, les métadonnées le sont aussi car l'utilisateur n'est pas lié à un identifiant - contrairement aux autres platformes.

+

Voir le livre blanc de SimpleX pour plus d'information sur les objectifs de la platforme et ses détails techniques.

+

Pourquoi utiliser SimpleX

+

SimpleX une approche unique en terme de confidentialité et de sécurité

+

Tout le monde devrait se soucier de la confidentialité et de la sécurité de ses communications - même une conversation lambda peut vous mettre en danger.

+

Protection complète de votre identité, profil, contacts et métadonnées

+

Contrairement aux autres platformes de messagerie, SimpleX ne lie pas d'identifiant à l'utilisateur - il n'y a pas besoin de numéro de télèphone (comme Signal ou WhatsApp), d'adresses basés sur des noms de domaines (comme les e-mails, XMPP ou Matrix), de noms d'utilisateurs (comme Telegram), ou de clés publiques ou même de nombres aléatoires pour identifié les utilisateurs - on ne sait même pas combiens de personnes utilise SimpleX.

+

Pour distribuer les messages au lieu d'utiliser des identifiants d'utilisateur que toute les autres platformes utilisent, SimpleX utilise des adresses unidirectionnelles (simplex) de files d'attentes de messages. Utiliser SimpleX c'est comme avoir une adresse e-mail différentes ou un numéro de télèphone différent par contact, sans les inconvenients qui viennent avec. Dans un futur proche les apps SimpleX changeront automatiquement les files d'attentes, déplacant les conversations d'un serveur à un autre, pour une meilleure confidentialité.

+

Cette approche protège la vie privé de la personne avec qui vous communiquez, elle est masquée des serveurs SimpleX et de n'importe quel autre observateur. Vous pouvez encore améliorer votre protection en configurant votre réseau pour qu'il passe via des réseaux superposé comme, par exemple Tor.

+

La meilleure protection contre le spam et les abus

+

Comme vous n'avez pas d'identifiant sur la plateforme SimpleX, vous ne pouvez pas être contacté, sauf si vous partagez un lien d'invitation unique ou une adresse d'utilisateur temporaire facultative. Même avec les adresses d'utilisateur facultatives, bien qu'elles puissent être utilisées pour envoyer des demandes de contact non sollicitées, vous pouvez les modifier ou les supprimer complètement sans perdre aucune de vos connexions.

+

Propriété, contrôle et sécurité totale de vos données

+

SimpleX stocke toutes les données de l'utilisateur sur les appareils clients, les messages ne sont conservés que temporairement sur les serveurs relais SimpleX jusqu'à leur réception.

+

Nous utilisons un format de base de données portable qui peut être utilisé sur tous les appareils pris en charge. Nous ajouterons bientôt la possibilité d'exporter la base de données de chat depuis l'application mobile afin qu'elle puisse être utilisée sur un autre appareil.

+

Contrairement aux serveurs des réseaux fédérés (e-mail, XMPP ou Matrix), les serveurs SimpleX ne stockent pas les comptes des utilisateurs, ils se contentent de relayer les messages aux destinataires, protégeant ainsi la vie privée des deux parties. Il n'y a aucun identifiant ou message chiffré en commun entre le trafic envoyé et reçu du serveur, grâce à la couche de chiffrement supplémentaire pour les messages délivrés. Par conséquent, si quelqu'un observe le trafic du serveur, il ne peut pas facilement déterminer qui communique avec qui (Voir le livre blanc de SimpleX pour les attaques connues de corrélation réseau).

+

Les utilisateurs sont maîtres du réseau SimpleX

+

Vous pouvez utiliser SimpleX avec vos propres serveurs et continuer à communiquer avec les personnes utilisant les serveurs préconfigurés dans les applications ou tout autre serveur SimpleX.

+

La plateforme SimpleX utilise un protocole ouvert et fournit un SDK pour créer des chatbot, permettant la mise en œuvre de services avec lesquels les utilisateurs peuvent interagir via les applications SimpleX Chat - nous sommes vraiment impatients de voir quels services SimpleX peuvent être créés.

+

Si vous envisagez de développer avec la plateforme SimpleX, que ce soit pour des services de chatbot pour les utilisateurs de l'application SimpleX ou pour intégrer la bibliothèque de chat SimpleX dans vos applications mobiles, n'hésitez pas à nous contacter pour tout conseil et assistance.

+

Comparaison avec d'autres protocoles

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SimpleX chatSignal et autres...XMPP, MatrixProtocoles P2P
Identifiants d'utilisateur nécessaireNon = privéOui1Oui2Oui3
Risque d'attaque MITMNon = securiséOui4OuiOui
Dépendance au DNSNon = résistantOuiOuiNon
Un opérateur ou un réseau uniqueNon = décentraliséOuiNonOui5
Attaque à l'échelle du réseauNon = résistantOuiOui2Oui6
+
    +
  1. Généralement basé sur un numéro de téléphone, dans certains cas sur des noms d'utilisateur.
  2. +
  3. Basé sur le DNS.
  4. +
  5. Clé publique ou tout autre identifiant global unique.
  6. +
  7. Si les serveurs de l'opérateur sont compromis.
  8. +
  9. Si les réseaux P2P et les réseaux basés sur les crypto-monnaies sont distribués, ils ne sont pas décentralisés : ils fonctionnent comme un seul réseau, avec un seul espace de noms des adresses des utilisateurs.
  10. +
  11. Les réseaux P2P ont soit une autorité centrale, soit l'ensemble du réseau peut être compromis - voir la section suivante.
  12. +
+

Comparaison avec les protocoles de messagerie P2P

+

Il existe plusieurs protocoles et implémentations de chat/messagerie P2P qui visent à résoudre le problème de la protection de la vie privée et de la centralisation, mais ils ont leur propre série de problèmes qui les rendent moins fiables que la forme proposée, plus complexes à mettre en œuvre et à analyser et plus vulnérables aux attaques.

+
    +
  1. +

    Les réseaux P2P utilisent une variante de DHT pour acheminer les messages/demandes à travers le réseau. Les implémentations du DHT ont des designs complexes qui doivent équilibrer la fiabilité, la garantie de livraison et la latence. La méthode proposée offre à la fois de meilleures garanties de livraison et une latence plus faible (le message est transmis plusieurs fois en parallèle, à travers un nœud à chaque fois, en utilisant des serveurs choisis par le destinataire, alors que dans les réseaux P2P, le message est transmis à travers O(log N) nœuds séquentiellement, en utilisant des nœuds choisis par un algorithme).

    +
  2. +
  3. +

    Le modèle proposé, contrairement à la plupart des réseaux P2P, ne comporte aucun identifiant global d'utilisateur, même temporaire.

    +
  4. +
  5. +

    Le P2P en lui-même ne résout pas le problème des attaques MITM, et la plupart des solutions existantes n'utilisent pas de messages hors bande pour l'échange initial de clés. La conception proposée utilise des messages hors bande ou, dans certains cas, des connexions sécurisées et fiables préexistantes pour l'échange initial de clés.

    +
  6. +
  7. +

    Les implémentations P2P peuvent être bloquées par certains fournisseurs d'accès à Internet (comme BitTorrent). Le modèle proposée est indépendant des moyens de transport : il peut fonctionner avec des protocoles web standard et les serveurs peuvent être déployés sur les mêmes domaines que les sites web.

    +
  8. +
  9. +

    Tous les réseaux P2P connus sont susceptibles d'être vulnérables à une attaque Sybil, car chaque nœud peut être découvert et le réseau fonctionne comme un tout. Les mesures connues pour réduire la probabilité de l'attaque Sybil nécessitent soit un composant centralisé, soit des preuves de travail coûteuses. Le modèle proposée, au contraire, ne permet pas de découvrir les serveurs - les serveurs ne sont pas connectés, ni connus les uns des autres, ni de tous les clients. Le réseau SimpleX est fragmenté et fonctionne comme de multiples connexions isolées. Cela rend impossible les attaques à l'échelle du réseau SimpleX - même si certains serveurs sont compromis, d'autres parties du réseau peuvent fonctionner normalement, et les clients affectés peuvent passer à l'utilisation d'autres serveurs sans perdre de contacts ou de messages.

    +
  10. +
  11. +

    Les réseaux P2P sont susceptibles d'être vulnérables aux attaques DRDoS. Dans la conception proposée, les clients ne relaient que le trafic provenant de connexions de confiance connues et ne peuvent pas être utilisés pour refléter et amplifier le trafic dans l'ensemble du réseau.

    +
  12. +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/sql.html b/docs/lang/fr/sql.html new file mode 100644 index 0000000000..fb487f8354 --- /dev/null +++ b/docs/lang/fr/sql.html @@ -0,0 +1,825 @@ + + + + + + + + + Accès aux messages de la base de données + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 31.01.2023 | FR, EN, CZ |

+

Accès aux messages de la base de données

+

Déchiffrer les bases de données

+

Afin de visualiser les données de la base de données, vous devez d'abord les déchiffrer. Installez sqlcipher en utilisant votre gestionnaire de paquets préféré et exécutez les commandes suivantes dans le répertoire contenant les bases de données :

+
sqlcipher files_chat.db
+pragma key="youDecryptionPassphrase";
+# S'assurer qu'il fonctionne bien
+select * from users;
+
+

Si vous voyez Parse error : no such table : users, assurez-vous que vous avez entré la bonne phrase secrète, et que vous avez changé la phrase secrète au hasard dans l'application Android (si vous avez obtenu cette base de données à partir d'un appareil Android, bien sûr).

+

Requêtes SQL

+

Vous pouvez exécuter des requêtes direct_messages, group_messages et all_messages (ou leurs alternatives plus simples direct_messages_plain, group_messages_plain et all_messages_plain), par exemple :

+
-- vous pouvez mettre ces paramètres ou ceux que vous préférez dans ~/.sqliterc
+-- pour maintenir les sessions du client sqlite3
+.mode column
+.headers on
+.nullvalue NULL
+
+-- vues simples pour direct, group et all_messages
+-- avec les messages de l'utilisateur dédupliqués pour group et all_messages ;
+-- seuls les événements de chat "x.msg.new" ("nouveau message") - filtre les événements de service ;
+-- msg_sent est 0 pour reçu, 1 pour envoyé
+select * from direct_messages_plain;
+select * from group_messages_plain;
+select * from all_messages_plain;
+
+-- demander d'autres détails de votre historique de chat avec le SQL régulier, par exemple :
+-- les fichiers que vous avez soumis pour l'envoi
+select * from direct_messages where msg_sent = 1 and chat_msg_event = 'x.file';
+-- tout ce que Catherine a envoyé lié aux chats
+select * from direct_messages where msg_sent = 0 and contact = 'catherine' and msg_body like '%cats%';
+-- toute correspondance avec alice dans #team
+select * from group_messages where group_name = 'team' and contact = 'alice';
+
+-- regrouper vos données de chat
+select contact_or_group, num_messages from (
+  select
+    contact as contact_or_group, count(1) as num_messages
+    from direct_messages_plain group by contact
+  union
+  select
+    group_name as contact_or_group, count(1) as num_messages
+    from group_messages_plain group by group_name
+)
+order by num_messages desc;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/translations.html b/docs/lang/fr/translations.html new file mode 100644 index 0000000000..cceb4037ae --- /dev/null +++ b/docs/lang/fr/translations.html @@ -0,0 +1,843 @@ + + + + + + + + + Contribuer aux traductions de SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 19.03.2023 | FR, EN, CZ |

+

Contribuer aux traductions de SimpleX Chat

+

Un grand merci pour votre intérêt pour la traduction de SimpleX Chat - cela nous aide beaucoup à rendre l'application accessible à un plus grand nombre d'utilisateurs, et nous vous remercions de votre aide.

+

Cela demande un investissement en temps considérable - la plupart des gens le sous-estiment au départ - et une maintenance continue au fur et à mesure que nous développons l'application.

+

Ce document est créé pour accélérer ce processus, et partager quelques astuces importantes que nous avons découverts en travaillant avec Weblate - la plateforme que nous utilisons pour les traductions d'interface.

+

Avant de commencer la traduction

+
    +
  1. +

    Créez un compte sur Weblate, en utilisant le même e-mail que celui que vous utilisez sur GitHub - cela permettra d'associer vos contributions à votre compte GitHub, et pourra vous aider dans certains cas. Une fois la traduction publiée pour les utilisateurs, nous ajouterons le nom de votre compte à la liste des traducteurs.

    +
  2. +
  3. +

    Avant de commencer la traduction, il y a un simple accord de licence pour les contributeurs à signer via Weblate - ceci afin d'éviter tout conflit autour des droits de propriété intellectuelle. La copie de cet accord est également disponible ici.

    +
  4. +
  5. +

    Nous pouvons également vous ajouter au groupe de traducteurs pour toute question et mise à jour - veuillez vous connecter à moi via le chat.

    +
  6. +
+

Avancement de la traduction

+
    +
  1. +

    Veuillez commencer par l'app Android, à la fois lorsque vous effectuez la traduction initiale la plus longue, et que vous ajoutez les chaînes de caractères plus tard. Premièrement, les chaînes iOS peuvent être un peu retardées dans leur apparition dans Weblate, car elles nécessitent une étape manuelle de notre part avant d'être visibles. Deuxièmement, l'application Android est configurée comme un glossaire pour l'application iOS, et 2/3 de toutes les chaînes ne nécessitent que quelques clics pour les transférer d'Android à iOS (cela prend toujours un certain temps, Weblate ne l'automatise pas, malheureusement).

    +
  2. +
  3. +

    Certaines des chaînes n'ont pas besoin d'être traduites, mais elles doivent quand même être copiées - il y a un bouton dans l'interface weblate pour cela :

    +
  4. +
+weblate: copy source to translation +
    +
  1. +

    Weblate propose également des suggestions automatiques qui peuvent accélérer le processus. Parfois, elles peuvent être utilisées telles quelles, parfois elles nécessitent quelques retouches - cliquez pour les utiliser dans les traductions.

    +
  2. +
  3. +

    Une fois que toutes les chaînes de caractères de l'application Android sont traduites, veuillez les réviser pour vous assurer de la cohérence du style et de la langue, afin que les mêmes mots soient systématiquement utilisés pour des actions similaires de l'utilisateur, comme en anglais. Parfois, vous devrez utiliser des mots différents dans des cas où l'anglais n'en a qu'un seul. Veuillez essayer d'utiliser ces choix de manière cohérente dans des contextes similaires, afin de faciliter la tâche des utilisateurs finaux.

    +
  4. +
  5. +

    Quand vous traduisez l'app iOS, la plupart des chaînes de caractères sont identiques, elles peuvent être copiées en un clic dans la section Glossaire. L'indice visuel que cela est possible est que la chaîne source entière est surlignée en jaune. De nombreuses autres chaînes sont très similaires, elles ne diffèrent que par la syntaxe d'interpolation ou la façon dont la police en gras est utilisée - elles ne nécessitent qu'une édition minimale. Certaines chaînes sont propres à la plate-forme iOS. Elles doivent être traduites séparément.

    +
  6. +
+weblate: automatic suggestions +

Une fois la traduction terminée

+

Une fois que les applications Android et iOS sont traduites, veuillez nous en informer.

+

Nous allons ensuite :

+
    +
  • revoir toutes les traductions et suggérer des corrections - cela prend aussi un peu de temps :)
  • +
  • les fusionner avec le code source - pendant que nous le ferons, weblate sera verrouillé pour les changements.
  • +
  • créer des versions bêta des applications iOS et Android - nous pouvons également vous ajouter aux groupes de testeurs internes, afin que vous puissiez installer les applications avant tout le monde.
  • +
  • diffuser l'application auprès de nos utilisateurs bêta - ce sont plus d'un millier de personnes qui utilisent nos versions bêta.
  • +
  • publier l'application et inclure la nouvelle langue dans l'annonce.
  • +
+

Remarque : nous souhaitons que les fonctions de l'application restent cohérentes entre les plateformes Android et iOS, dans la mesure du possible. Nous publierons et annoncerons donc une nouvelle langue une fois que les deux plateformes auront été traduites. Cela ne signifie pas que vous devez le faire, mais nous devrons attendre que quelqu'un d'autre traduise la deuxième plateforme. Mais si vous commencez par Android, l'ajout d'iOS prend généralement 3 à 4 fois moins de temps.

+

La suite

+
    +
  1. +

    Lorsque nous mettons l'application à jour, nous publions les mises à jour dans le groupe de traducteurs. Vous n'avez absolument aucune obligation de traduire ces chaînes supplémentaires. Nous apprécions énormément que vous le fassiez, car l'expérience des utilisateurs est bien meilleure, ils dépendent de vos traductions, si une nouvelle partie de l'application n'est pas traduite.

    +
  2. +
  3. +

    Vous pouvez également aider à promouvoir l'application dans votre pays / groupe linguistique en traduisant nos documents - nous venons de commencer - ainsi que le contenu de notre site web. Il y a eu beaucoup de demandes pour le faire et nous sommes en train d'ajouter le cadre de traduction pour le site web.

    +
  4. +
  5. +

    De plus, si vous souhaitez être modérateur/administrateur du groupe d'utilisateurs dans votre langue, une fois l'application traduite, nous pourrons héberger un tel groupe. Nous sommes en train de préparer des règles de conduite pour la communauté et d'ajouter des outils de modération à l'application qui sortira dans la v5 en mars.

    +
  6. +
+

Encore une fois un grand merci de nous aider à développer SimpleX Chat !

+

Evgeny, fondateur de SimpleX Chat.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/lang/fr/webrtc.html b/docs/lang/fr/webrtc.html new file mode 100644 index 0000000000..82235b7ce9 --- /dev/null +++ b/docs/lang/fr/webrtc.html @@ -0,0 +1,912 @@ + + + + + + + + + Utilisation de serveurs WebRTC ICE personnalisés dans SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 31.01.2023 | FR, EN, CZ |

+

Utilisation de serveurs WebRTC ICE personnalisés dans SimpleX Chat

+

Déployer un serveur STUN/TURN

+

Pour ce guide, nous utiliserons l'implémentation de serveur STUN/TURN la plus complète et la plus testée - coturn et la distribution Linux Ubuntu 20.04 LTS.

+
    +
  1. +

    Obtenez les certificats stun.$VOTRE_DOMAINE et turn.$VOTRE_DOMAINE.

    +

    Nous utilisons Let's Encrypt.

    +
  2. +
  3. +

    Installez le package coturn depuis le dépôt principal.

    +
  4. +
+
apt update && apt install coturn`
+
+
    +
  1. Décommentez TURNSERVER_ENABLED=1 de /etc/default/coturn :
  2. +
+
sed -i '/TURN/s/^#//g' /etc/default/coturn
+
+
    +
  1. +

    Configurez coturn dans /etc/turnserver.conf :

    +

    Veuillez également consulter les commentaires relatifs pour chacune des options.

    +
  2. +
+
# tls sur le port 443
+alt-tls-listening-port=443
+# Utiliser les empreintes dans les messages TURN
+fingerprint
+# Utiliser le mécanisme d'identification à long terme
+lt-cred-mech
+# Vos informations d'identification
+user=$VOTRE_LOGIN:$VOTRE_MOT_DE_PASSE
+# Le domaine de votre serveur
+server-name=$VOTRE_DOMAINE
+# Le domaine par défaut à utiliser pour les utilisateurs lorsqu'aucune relation explicite origine/domaine n'a été trouvée
+realm=$VOTRE_DOMAINE
+# Chemin vers vos certificats. Assurez-vous qu'ils sont lisibles par l'utilisateur/groupe du processus cotun
+cert=/var/lib/turn/cert.pem
+pkey=/var/lib/turn/key.pem
+# Utiliser la clé DH TLS prédéfinie de 2066 bits
+dh2066
+# Log sur journalctl
+syslog
+# Utilisateur/groupe qui exécutera le service coturn
+proc-user=turnserver
+proc-group=turnserver
+# Désactiver le chiffrement faible
+no-tlsv1
+no-tlsv1_1
+no-tlsv1_2
+
+
    +
  1. Démarrez et activez le service coturn :
  2. +
+
systemctl enable coturn && systemctl start coturn
+
+
    +
  1. Optionnellement, si vous utilisez le pare-feu ufw, ouvrez les ports appropriés :
  2. +
+
    +
  • 3478 – "simple" TURN/STUN;
  • +
  • 5349 – TURN/STUN over TLS;
  • +
  • 443 – TURN/STUN over TLS, qui peuvent contourner les pare-feu;
  • +
  • 49152:65535 – plage de ports que Coturn utilisera par défaut pour le relais TURN.
  • +
+
ufw allow 3478 && \
+ufw allow 443 && \
+ufw allow 5349 && \
+ufw allow 49152:65535/tcp && \
+ufw allow 49152:65535/udp
+
+

Configurer l'app mobile

+

Pour configurer votre application mobile afin d'utiliser votre serveur :

+
    +
  1. +

    Ouvrez Paramètres / Réseau & Serveurs / Serveurs WebRTC ICE et activez la case Configurer les serveurs ICE.

    +
  2. +
  3. +

    Entrez toutes les adresses des serveurs dans le champ, une par ligne, par exemple si vos serveurs sont sur le port 5349 :

    +
  4. +
+
stun:stun.example.com:5349
+turn:username:password@turn.example.com:5349
+
+

Voilà, vous pouvez désormais passer des appels audio et vidéo via votre propre serveur, sans partager aucune donnée avec nos serveurs (autre que l'échange de clés avec votre contact dans les messages cryptés E2E).

+

Dépannage

+
    +
  • +

    Déterminer si un serveur est disponible :

    +

    Exécutez cette commande dans votre terminal :

    +
    ping <votre_ip_ou_domaine>
    +
    +

    Si des paquets sont transmis, le serveur est opérationnel !

    +
  • +
  • +

    Déterminez si les ports sont ouverts :

    +

    Exécutez cette commande dans votre terminal :

    +
    nc -zvw10 <votre_ip_ou_domaine> 443 5349
    +
    +

    Vous devriez voir :

    +
    Connection to <votre_ip_ou_domaine> 443 port [tcp/https] succeeded!
    +Connection to <votre_ip_ou_domaine> 5349 port [tcp/*] succeeded!
    +
    +
  • +
  • +

    Testez la connectivité STUN/TURN :

    +
      +
    1. +

      Allez sur IceTest.

      +
    2. +
    3. +

      Dans la section Build up ICE Server List, ajoutez :

      + +
        +
      • STUN: stun:<votre_ip_ou_domaine>:<port> et appuyez sur Add STUN
      • +
      • TURN: turn:<votre_ip_ou_domaine>:<port>, Username: <votre_login>, Credential: <votre_pass> et appuyez sur Add TURN
      • +
      +

      <port> est 443 ou 5349.

      +
    4. +
    5. +

      Vous devriez voir vos serveurs dans la section ICE server list. Si tout est correctement configuré, cliquez sur Start test :

      + +
    6. +
    7. +

      Dans la section Results, vous devriez obtenir quelque chose comme ceci :

      + +

      Si les résultats montrent des candidats srflx et relay, tout est correctement configuré !

      +
    8. +
    +
  • +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/protocol/diagrams/group.mmd b/docs/protocol/diagrams/group.mmd new file mode 100644 index 0000000000..c331b46100 --- /dev/null +++ b/docs/protocol/diagrams/group.mmd @@ -0,0 +1,26 @@ +sequenceDiagram + participant M as N existing
members + participant A as Alice + participant B as Bob + participant C as Existing
contact + + note over A, B: 1. send and accept group invitation + A ->> B: x.grp.inv
invite Bob to group
(via contact connection) + B ->> A: x.grp.acpt
accept invitation
(via member connection) + B ->> A: establish group member connection + + note over M, B: 2. introduce new member Bob to all existing members + A ->> M: x.grp.mem.new
"announce" Bob
to existing members
(via member connections) + A ->> B: x.grp.mem.intro * N
"introduce" members
(via member connection) + B ->> A: x.grp.mem.inv * N
"invitations" to connect
for all members
(via member connection) + A ->> M: x.grp.mem.fwd
forward "invitations"
to all members
(via member connections) + + note over M, B: 3. establish direct and group member connections + M ->> B: establish group member connection + M ->> B: establish direct connection + + note over M, C: 4. deduplicate new contact + B ->> M: x.info.probe
"probe" is sent to all new members + B ->> C: x.info.probe.check
"probe" hash,
in case contact and
member profiles match + C ->> B: x.info.probe.ok
original "probe",
in case contact and member
are the same user + note over B: merge existing and new contacts if received and sent probe hashes match diff --git a/docs/protocol/diagrams/group.svg b/docs/protocol/diagrams/group.svg new file mode 100644 index 0000000000..d66b560b21 --- /dev/null +++ b/docs/protocol/diagrams/group.svg @@ -0,0 +1 @@ +N existingmembersAliceBobExistingcontact1. send and accept group invitation2. introduce new member Bob to all existing members3. establish direct and group member connections4. deduplicate new contactmerge existing and new contacts if received and sent probe hashes matchx.grp.invinvite Bob to group(via contact connection)x.grp.acptestablish group member connectionx.grp.mem.new"announce" Bobto existing members(via member connections)x.grp.mem.intro * N"introduce" members(via member connection)x.grp.mem.inv * N"invitations" to connectfor all members(via member connection)x.grp.mem.fwdforward "invitations"to all members(via member connections)establish group member connectionestablish direct connectionx.info.probe"probe" is sent to all new membersx.info.probe.check"probe" hash,in case contact andmember profiles matchx.info.probe.ok original "probe", in case contact and memberare the same userN existingmembersAliceBobExistingcontact \ No newline at end of file diff --git a/docs/protocol/diagrams/xftp.mmd b/docs/protocol/diagrams/xftp.mmd new file mode 100644 index 0000000000..af45952075 --- /dev/null +++ b/docs/protocol/diagrams/xftp.mmd @@ -0,0 +1,42 @@ +sequenceDiagram + participant A as Alice + participant AC as Alice Chat + participant AA as Alice Agent + participant XFTP as Alice's XFTP relay(s) + participant SMP as Bob's SMP relay + participant BA as Bob Agent + participant BC as Bob Chat + participant B as Bob + + A ->> AC: APISendMessage + AC ->> AA: sendMessage(x.msg.new) /
CIFSSndStored + AA ->> SMP: SEND + SMP ->> BA: MSG + BA ->> BC: MSG + BC ->> B: CRNewChatItem
(file not ready) + B ->> BC: ReceiveFile + BC ->> B: error: no file description + AC ->> AA: sendFile + AC ->> A: CRSndFileStart + AA ->> XFTP: chunk (FNEW, FPUT) + AA ->> AC: SFPROG /
CIFSSndTransfer + AC ->> A: CRSndFileProgress (new) + AA ->> XFTP: chunks + AA ->> AC: SFDONE sd rds + AC ->> AA: sendMessage(x.msg.file.descr) /
FSComplete / CIFSSndComplete + AC ->> A: CRSndFileComplete (?) + AA ->> SMP: SEND + SMP ->> BA: MSG + BA ->> BC: MSG + BC ->> B: CRChatItemUpdated
(file is ready) + BC ->> B: CRFileReady (TBC) + B ->> BC: ReceiveFile + BC ->> BA: getFile + BC ->> B: CRRcvFileStart + XFTP ->> BA: chunk (FGET / FRFile) + BA ->> BC: RFPROG + BC ->> B: CRRcvFileProgress (new) + XFTP ->> BA: chunks + BA ->> BC: RFDONE + BC ->> B: CRNewChatItem
(file received) + BC ->> B: CRRcvFileComplete diff --git a/docs/protocol/simplex-chat.html b/docs/protocol/simplex-chat.html new file mode 100644 index 0000000000..eea5862ac6 --- /dev/null +++ b/docs/protocol/simplex-chat.html @@ -0,0 +1,889 @@ + + + + + + + + + SimpleX Chat Protocol + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

DRAFT Revision 0.1, 2022-08-08

+

Evgeny Poberezkin

+

SimpleX Chat Protocol

+

Abstract

+

SimpleX Chat Protocol is a protocol used to by SimpleX Chat clients to exchange messages. This protocol relies on lower level SimpleX protocols - SimpleX Messaging Protocol (SMP) and SimpleX Messaging Agent protocol. SimpleX Chat Protocol describes the format of messages and the client operations that should be performed when receiving such messages.

+

Scope

+

The scope of SimpleX Chat Protocol is application level messages, both for chat functionality, related to the conversations between the clients, and extensible for any other application functions. Currently supported chat functions:

+
    +
  • direct and group messages,
  • +
  • message replies (quoting), forwarded messages and message deletions,
  • +
  • message attachments: images and files,
  • +
  • creating and managing chat groups,
  • +
  • invitation and signalling for audio/video WebRTC calls.
  • +
+

General message format

+

SimpleX Chat protocol supports two message formats:

+
    +
  • JSON-based format for chat and application messages.
  • +
  • binary format for sending files or any other binary data.
  • +
+

JSON format for chat and application messages

+

This document uses JTD schemas RFC 8927 to define the properties of chat messages, with some additional restrictions on message properties included in metadata member of JTD schemas. In case of any contradiction between JSON examples and JTD schema the latter MUST be considered correct.

+

Whitespace is used in JSON examples for readability, SimpleX Chat Protocol clients MUST avoid using whitespace when encoding JSON messages.

+

General message format is defined by this JTD schema:

+
{
+  "properties": {
+    "event": {
+      "type": "string"
+    },
+    "msgId": {
+      "type": "string",
+      "metadata": {
+        "format": "base64url-encoded 12 bytes random message ID"
+      }
+    },
+    "params": {
+      "optionalProperties": {}
+    }
+  }
+}
+
+

For example, this message defines a simple text message "hello!":

+
{
+  "event": "x.msg.new",
+  "msgId": "abcd",
+  "params": {
+    "content": {
+      "type": "text",
+      "text": "hello!"
+    }
+  }
+}
+
+

msgId property is a 12 bytes base64url-encoded random message ID that the clients can use to reference the message in the future, e.g. when editing, quoting or deleting it.

+

event property is the type of the message that defines the semantics of the message and the allowed format of params property.

+

params property includes message data, depending on event, as defined below and in JTD schema.

+

Binary format for sending files

+

SimpleX Chat clients use separate connections to send files using a binary format. File chunk size send in each message MUST NOT be bigger than 15,780 bytes to fit into 16kb (16384 bytes) transport block.

+

The syntax of each message used to send files is defined by the following ABNF notation:

+
fileMessage = fileChunk / cancelFile
+fileChunk = %s"F" chunkNo chunk
+cancelFile = %s"C"
+chunkNo = 4*4 OCTET ; 32bit word sequential chunk number, starting from 1, in network byte order
+chunk = 1*15780 OCTET ; file data, up to 15,780 bytes
+
+

The first chunk number MUST be 1.

+

Messages and chat items

+

While users usually use the term "message" to refer to the objects presented in the conversation, the expected functionality of these objects makes it a wrong term. "Messages" are supposed to be immutable; they cannot be modified or deleted once sent. The objects in the conversation are expected to be mutable. This document and implementation use the term "chat item" to refer to these objects to differentiate them from the messages sent between the clients.

+

Supported JSON message types and SimpleX Chat sub-protocols

+

Message types are sent as a string in event property of JSON messages. General syntax of event string is defined by this ABNF:

+
event = namespace "." subprotocol *("." eventWord)
+namespace = eventWord ; 1-letter recommended
+subprotocol = eventWord
+eventWord = 1* ALPHA
+
+

All SimpleX Chat Protocol messages related to chat functions are defined in x namespace.

+

Sub-protocol is a group of messages for related message functions - e.g. sending files, managing groups or negotiating WebRTC calls.

+

SimpleX Chat Protocol supports the following message types passed in event property:

+
    +
  • x.contact - contact profile and additional data sent as part of contact request to a long-term contact address.
  • +
  • x.info* - messages to send, update and de-duplicate contact profiles.
  • +
  • x.msg.* - messages to create, update and delete content chat items.
  • +
  • x.file.* - messages to accept and cancel sending files (see files sub-protocol).
  • +
  • x.grp.* - messages used to manage groups and group members (see group sub-protocol).
  • +
  • x.call.* - messages to invite to WebRTC calls and send signalling messages.
  • +
  • x.ok - message sent during connection handshake.
  • +
+

JTD schema defining messages for all chat functions is available in this file – please refer to this document for all properties of the message params.

+

x.contact - sending connection request

+

The message is sent as part of the connection request to the long-term user address. contactReqId property is used to identify a duplicate contact request - the receiving client MAY put repeated request on top of the list in the UI.

+

Sub-protocol for contact profile

+

x.info - contact profile

+

This message is sent by both sides of the connection during the connection handshake, and can be sent later as well when contact profile is updated.

+

Probing for duplicate contacts

+

As there are no globally unique user identitifiers, when the contact a user is already connected to is added to the group by some other group member, this contact will be added to user's list of contacts as a new contact. To allow merging such contacts, "a probe" (random base64url-encoded 32 bytes) SHOULD be sent to all new members as part of x.info.probe message and, in case there is a contact with the same profile, the hash of the probe MAY be sent to it as part of x.info.probe.check message. In case both the new member and the existing contact are the same user (they would receive both the probe and its hash), the contact would send back the original probe as part of x.info.probe.ok message via the previously existing contact connection – proving to the sender that this new member and the existing contact are the same user, in which case the sender SHOULD merge these two contacts.

+

Sending clients MAY disable this functionality, and receiving clients MAY ignore probe messages.

+

If the sending client uses x.info.probe messages, it MUST send them to all new members, rather than only when there is a matching contact profile. This is to avoid leaking information that the matching contact profile exists.

+

Sub-protocol for content messages

+

x.msg.new - a new content message

+

When chat clients receive or send this message, they MUST create a new chat item in the conversation. Top level msgId property is defined to allow referencing this chat item or message in the future, e.g. to delete, update or quote chat item, or to accept file.

+

This message uses params property of the message as content message container, without any top level properties for the container. Message container (params) includes message content property, an optional "invitation" to receive file or image attachment in file property (that is interpreted depending on message content type) and optional indication whether this message is forwarded ("forward": true property of container) or sent in reply to other message ("quote": {<quoted message>}). See /definition/msgContainer in JTD schema for message container format.

+

Message content can be one of four types:

+
    +
  • text - no file attachment is expected for this format, text property MUST be non-empty.
  • +
  • file - attached file is required, text property MAY be empty.
  • +
  • image - attached file is required, text property MAY be empty.
  • +
  • link - no file attachment is expected, text property MUST be non-empty. preview property contains information about link preview.
  • +
+

See /definition/msgContent in JTD schema for message container format.

+

x.msg.update - update of the previously sent message

+

This message is used to update previously created chat item. Its params property contains msgId of the previously sent message that this one is updating and content with the message content that the clients must use to replace the content of the original chat item.

+

If the referenced message does not exist, the clients MUST create a new chat item with the ID of the referenced message. If the referenced message is not a content message, the clients MUST ignore this message.

+

x.msg.del - request to delete previously sent message

+

This message is used to delete previously sent chat items. Receiving clients MUST implement it as soft-delete, replacing the original chat item with a special chat item indicating that "message is deleted" that can be fully deleted by the user. If the referenced message does not exist or was sent by the different user than the one sending x.msg.del, the receiving clients MUST ignore this message. Clients are also RECOMMENDED to limit the time during which message deletion is allowed, both for senders and for the recipients.

+

Sub-protocol for sending and receiving files

+

When content message x.msg.new contains file attachment (the invitation to receive the file), this sub-protocol is used to accept this file or to notify the recipient that sending the file was cancelled.

+

File attachement can optionally include connection address to receive the file - clients MUST include it when sending files to direct connections, and MUST NOT include it when sending file attachment to the group (as different members would need different connections to receive the file).

+

x.file.acpt message is used to accept the file in case when file connection address was included in the message (that is the case when the file invitation was sent in direct message). It is sent as part of file connection handshake via file connection, that is why this message contains no reference to the file - the used connection provides sufficient context for the sender.

+

x.file.acpt.inv message is used to accept the file in group conversations, it includes the connection address. It is sent in the same connection where the file was offered and must reference the original message.

+

x.file.cancel message is sent to notify the recipient that sending of the file was cancelled. It is sent in response to accepting the file with x.file.acpt.inv message. It is sent in the same connection where the file was offered.

+

Sub-protocol for chat groups

+

Decentralized design for chat groups

+

SimpleX Chat groups are fully decentralized and do not have any globally unique group identifiers - they are only defined on client devices as a group profile and a set of bi-directional SimpleX connections with other group members. When a new member accepts group invitation, the inviting member introduces a new member to all existing members and forwards the connection addresses so that they can establish direct and group member connections.

+

There is a possibility of the attack here: as the introducing member forwards the addresses, they can substitute them with other addresses, performing MITM attack on the communication between existing and introduced members - this is similar to the communication operator being able to perform MITM on any connection between the users. To mitigate this attack this group sub-protocol will be extended to allow validating security of the connection by sending connection verification out-of-band.

+

Clients are RECOMMENDED to indicate in the UI whether the connection to a group member or contact was made directly or via annother user.

+

Each member in the group is identified by a group-wide unique identifier used by all members in the group. This is to allow referencing members in the messages and to allow group message integrity validation.

+

The diagram below shows the sequence of messages sent between the users' clients to add the new member to the group.

+

Adding member to the group

+

Member roles

+

Currently members can have one of three roles - owner, admin and member. The user that created the group is self-assigned owner role, the new members are assigned role by the member who adds them - only owner and admin members can add new members; only owner members can add members with owner role.

+

Messages to manage groups and add members

+

x.grp.inv message is sent to invite contact to the group via contact's direct connection and includes group member connection address. This message MUST only be sent by members with admin or owner role. Optional groupLinkId is included when this message is sent to contacts connected via the user's group link. This identifier is a random byte sequence, with no global or even local uniqueness - it is only used for the user's invitations to a given group to provide confirmation to the contact that the group invitation is for the same group the contact was connecting to via the group link, so that the invitation can be automatically accepted by the contact - the contact compares it with the group link id contained in the group link uri's data field.

+

x.grp.acpt message is sent as part of group member connection handshake, only to the inviting user.

+

x.grp.mem.new message is sent by the inviting user to all connected members (and scheduled as pending to all announced but not yet connected members) to announce a new member to the existing members. This message MUST only be sent by members with admin or owner role. Receiving clients MUST ignore this message if it is received from member with member role.

+

x.grp.mem.intro messages are sent by the inviting user to the invited member, via their group member connection, one message for each existing member. When this message is sent by any other member than the one who invited the recipient it MUST be ignored.

+

x.grp.mem.inv messages are sent by the invited user to the inviting user, one message for each existing member previously introduced with x.grp.mem.intro message. When this message is sent by any other member than the one who was invited by the recipient it MUST be ignored.

+

x.grp.mem.fwd message is used by the inviting user to forward the invitations received from invited member in x.grp.mem.inv messages to all other members. This message can only be sent by the member who previously announced the new member, otherwise the recipients MUST ignore it.

+

x.grp.mem.info this message is sent as part of member connection handshake - it includes group member profile.

+

x.grp.mem.role message is sent to update group member role - it is sent to all members by the member who updated the role of the member referenced in this message. This message MUST only be sent by members with admin or owner role. Receiving clients MUST ignore this message if it is received from member with role less than admin.

+

x.grp.mem.del message is sent to delete a member - it is sent to all members by the member who deletes the member referenced in this message. This message MUST only be sent by members with admin or owner role. Receiving clients MUST ignore this message if it is received from member with member role.

+

x.grp.leave message is sent to all members by the member leaving the group. If the only group owner leaves the group, it will not be possible to delete it with x.grp.del message - but all members can still leave the group with x.grp.leave message and then delete a local copy of the group.

+

x.grp.del message is sent to all members by the member who deletes the group. Clients who received this message SHOULD keep a local copy of the deleted group, until it is deleted by the user. This message MUST only be sent by members with owner role. Receiving clients MUST ignore this message if it is received from member other than with owner role.

+

x.grp.info message is sent to all members by the member who updated group profile. Only group owners can update group profiles. Clients MAY implement some conflict resolution strategy - it is currently not implemented by SimpleX Chat client. This message MUST only be sent by members with owner role. Receiving clients MUST ignore this message if it is received from member other than with owner role.

+

Sub-protocol for WebRTC audio/video calls

+

This sub-protocol is used to send call invitations and to negotiate end-to-end encryption keys and pass WebRTC signalling information.

+

These message are used for WebRTC calls:

+
    +
  1. +

    x.call.inv: the client initiating the call sends x.call.inv message in direct connection to invite another client to the call. At this point WebRTC session is not initialized yet, this message only contains call type and DH key for key agreement.

    +
  2. +
  3. +

    x.call.offer: to accept the call, the receiving client sends x.call.offer message. This message contains WebRTC offer and collected ICE candidates. Additional ICE candidates can be sent in x.call.extra message.

    +
  4. +
  5. +

    x.call.answer: to continue with call connection the initiating clients must reply with x.call.answer message. This message contains WebRTC answer and collected ICE candidates. Additional ICE candidates can be sent in x.call.extra message.

    +
  6. +
  7. +

    x.call.end message is sent to notify the other party that the call is terminated.

    +
  8. +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/protocol/simplex-chat.schema.json b/docs/protocol/simplex-chat.schema.json new file mode 100644 index 0000000000..a9738190bd --- /dev/null +++ b/docs/protocol/simplex-chat.schema.json @@ -0,0 +1,496 @@ +{ + "metadata": { + "description": "JTD schema for SimpleX Chat Protocol messages for chat functions" + }, + "definitions": { + "profile": { + "properties": { + "displayName": { + "type": "string", + "metadata": { + "format": "non-empty string without spaces, the first character must not be # or @" + } + }, + "fullName": {"type": "string"} + }, + "optionalProperties": { + "image": { + "type": "string", + "metadata": { + "format": "data URI format for base64 encoded image" + } + } + }, + "additionalProperties": true + }, + "msgContainer": { + "properties": { + "content": {"ref": "msgContent"} + }, + "optionalProperties": { + "file": {"ref": "fileInvitation"}, + "quote": { + "properties": { + "msgRef": {"ref": "msgRef"}, + "content": {"ref": "msgContent"} + } + }, + "forward": {"type": "boolean"} + }, + "metadata": { + "comment": "optional properties `quote` and `forward` are mutually exclusive" + } + }, + "msgContent": { + "discriminator": "type", + "mapping": { + "text": { + "properties": { + "text": {"type": "string", "metadata": {"comment": "non-empty"}} + } + }, + "link": { + "properties": { + "text": {"type": "string", "metadata": {"comment": "non-empty"}}, + "preview": {"ref": "linkPreview"} + } + }, + "image": { + "text": {"type": "string", "metadata": {"comment": "can be empty"}}, + "image": {"ref": "base64url"} + }, + "file": { + "text": {"type": "string", "metadata": {"comment": "can be empty"}} + } + }, + "metadata": { + "comment": "it is RECOMMENDED that the clients support other values in `type` properties showing them as text messages in case `text` property is present" + } + }, + "msgRef": { + "properties": { + "msgId": {"ref": "base64url"}, + "sentAt": { + "type": "string", + "metadata": { + "format": "ISO8601 UTC time of the message" + } + }, + "sent": {"type": "boolean"} + }, + "optionalProperties": { + "memberId": {"ref": "base64url"}, + "metadata": { + "comment": "memberId must be present in all group message references, both for sent and received" + } + } + }, + "fileInvitation": { + "properties": { + "fileName": {"type": "string"}, + "fileSize": {"type": "uint32"} + }, + "optionalProperties": { + "fileConnReq": {"ref": "connReqUri"} + } + }, + "linkPreview": { + "properties": { + "uri": {"type": "string"}, + "title": {"type": "string"}, + "description": {"type": "string"}, + "image": {"ref": "base64url"} + } + }, + "groupInvitation": { + "properties": { + "fromMember": {"ref": "memberIdRole"}, + "invitedMember": {"ref": "memberIdRole"}, + "connRequest": {"ref": "connReqUri"}, + "groupProfile": {"ref": "profile"} + }, + "optionalProperties": { + "groupLinkId": {"ref": "base64url"}, + "metadata": { + "comment": "used to identify invitation via group link" + } + } + }, + "memberIdRole": { + "properties": { + "memberId": {"ref": "base64url"}, + "memberRole": {"ref": "groupMemberRole"} + } + }, + "memberInfo": { + "properties": { + "memberId": {"ref": "base64url"}, + "memberRole": {"ref": "groupMemberRole"}, + "profile": {"ref": "profile"} + } + }, + "introInvitation": { + "properties": { + "groupConnReq": {"ref": "connReqUri"}, + "directConnReq": {"ref": "connReqUri"} + } + }, + "groupMemberRole": { + "enum": ["author", "member", "admin", "owner"] + }, + "callInvitation": { + "properties": { + "callType": {"ref": "callType"} + }, + "optionalProperties": { + "callDhPubKey": {"ref": "base64url"} + } + }, + "callOffer": { + "properties": { + "callType": {"ref": "callType"}, + "rtcSession": {"ref": "webRTCSession"} + }, + "optionalProperties": { + "callDhPubKey": {"ref": "base64url"} + } + }, + "callAnswer": { + "properties": { + "rtcSession": {"ref": "webRTCSession"} + } + }, + "callExtraInfo": { + "properties": { + "rtcExtraInfo": { + "properties": { + "rtcIceCandidates": {"type": "string"} + } + } + } + }, + "callType": { + "properties": { + "media": {"enum": ["audio", "video"]}, + "capabilities": { + "properties": { + "encryption": {"type": "boolean"} + } + } + } + }, + "webRTCSession": { + "properties": { + "rtcSession": {"type": "string"}, + "rtcIceCandidates": {"type": "string"} + } + }, + "base64url": { + "type": "string", + "metadata": { + "format": "base64url encoded string" + } + }, + "connReqUri": { + "type": "string", + "metadata": { + "format": "URI for connection request" + } + } + }, + "discriminator": "event", + "mapping": { + "x.contact": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "profile": {"ref": "profile"}, + "contactReqId": {"ref": "base64url"} + } + } + } + }, + "x.info": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "profile": {"ref": "profile"} + } + } + } + }, + "x.info.probe": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "probe": {"ref": "base64url"} + } + } + } + }, + "x.info.probe.check": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "probeHash": {"ref": "base64url"} + } + } + } + }, + "x.info.probe.ok": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "probe": {"ref": "base64url"} + } + } + } + }, + "x.msg.new": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": {"ref": "msgContainer"} + } + }, + "x.msg.update": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "msgId": {"ref": "base64url"}, + "content": {"ref": "msgContent"} + } + } + } + }, + "x.msg.del": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "msgId": {"ref": "base64url"} + } + } + } + }, + "x.file.acpt": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "fileName": {"type": "string"} + } + } + } + }, + "x.file.acpt.inv": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "msgId": {"ref": "base64url"}, + "fileConnReq": {"ref": "connReqUri"}, + "fileName": {"type": "string"} + } + } + } + }, + "x.file.cancel": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "msgId": {"ref": "base64url"} + } + } + } + }, + "x.grp.inv": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "groupInvitation": {"ref": "groupInvitation"} + } + } + } + }, + "x.grp.acpt": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberId": {"ref": "base64url"} + } + } + } + }, + "x.grp.mem.new": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberInfo": {"ref": "memberInfo"} + } + } + } + }, + "x.grp.mem.intro": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberInfo": {"ref": "memberInfo"} + } + } + } + }, + "x.grp.mem.inv": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberId": {"ref": "base64url"}, + "memberIntro": {"ref": "introInvitation"} + } + } + } + }, + "x.grp.mem.fwd": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberInfo": {"ref": "memberInfo"}, + "memberIntro": {"ref": "introInvitation"} + } + } + } + }, + "x.grp.mem.info": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberId": {"ref": "base64url"}, + "profile": {"ref": "profile"} + } + } + } + }, + "x.grp.mem.role": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberId": {"ref": "base64url"}, + "role": {"ref": "groupMemberRole"} + } + } + } + }, + "x.grp.mem.del": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "memberId": {"ref": "base64url"} + } + } + } + }, + "x.grp.leave": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": {} + } + } + }, + "x.grp.del": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": {} + } + } + }, + "x.grp.info": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "groupProfile": {"ref": "profile"} + } + } + } + }, + "x.call.inv": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "callId": {"ref": "base64url"}, + "invitation": {} + } + } + } + }, + "x.call.offer": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "callId": {"ref": "base64url"}, + "offer": {"ref": "callOffer"} + } + } + } + }, + "x.call.answer": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "callId": {"ref": "base64url"}, + "answer": {"ref": "callAnswer"} + } + } + } + }, + "x.call.extra": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "callId": {"ref": "base64url"}, + "extra": {"ref": "callExtraInfo"} + } + } + } + }, + "x.call.end": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": { + "callId": {"ref": "base64url"} + } + } + } + }, + "x.ok": { + "properties": { + "msgId": {"ref": "base64url"}, + "params": { + "properties": {} + } + } + } + } +} diff --git a/docs/server.html b/docs/server.html new file mode 100644 index 0000000000..2d91269918 --- /dev/null +++ b/docs/server.html @@ -0,0 +1,1083 @@ + + + + + + + + + Hosting your own SMP Server + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 31.01.2023 | Languages: EN, FR, CZ |

+

Hosting your own SMP Server

+

Overview

+

SMP server is the relay server used to pass messages in SimpleX network. SimpleX Chat apps have preset servers (for mobile apps these are smp8, smp9 and smp10.simplex.im), but you can easily change app configuration to use other servers.

+

SimpleX clients only determine which server is used to receive the messages, separately for each contact (or group connection with a group member), and these servers are only temporary, as the delivery address can change.

+

Please note: when you change the servers in the app configuration, it only affects which server will be used for the new contacts, the existing contacts will not automatically move to the new servers, but you can move them manually using "Change receiving address" button in contact/member information pages – it will be automated soon.

+

Installation

+
    +
  1. +

    First, install smp-server:

    + +
  2. +
+

Manual installation requires some preliminary actions:

+
    +
  1. +

    Create user and group for smp-server:

    +
    sudo useradd -m smp
    +
    +
  2. +
  3. +

    Create necessary directories and assign permissions:

    +
    sudo mkdir -p /var/opt/simplex /etc/opt/simplex
    +sudo chown smp:smp /var/opt/simplex /etc/opt/simplex
    +
    +
  4. +
  5. +

    Allow smp-server port in firewall:

    +
    # For Ubuntu
    +ufw allow 5223
    +
    +
  6. +
  7. +

    Optional — If you're using distribution with systemd, create /etc/systemd/system/smp-server.service file with the following content:

    +
    [Unit]
    +Description=SMP server
    +[Service]
    +User=smp
    +Group=smp
    +Type=simple
    +ExecStart=smp-server start
    +ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex/smp-server-store.log" ] && cp "/var/opt/simplex/smp-server-store.log" "/var/opt/simplex/smp-server-store.log.bak"'
    +KillSignal=SIGINT
    +TimeoutStopSec=infinity
    +Restart=always
    +RestartSec=10
    +LimitNOFILE=65535
    +[Install]
    +WantedBy=multi-user.target
    +
    +

    And execute sudo systemctl daemon-reload.

    +
  8. +
+

Configuration

+

To see which options are available, execute smp-server without flags:

+
sudo su smp -c smp-server
+
+...
+Available commands:
+  init                     Initialize server - creates /etc/opt/simplex and
+                           /var/opt/simplex directories and configuration files
+  start                    Start server (configuration:
+                           /etc/opt/simplex/smp-server.ini)
+  delete                   Delete configuration and log files
+
+

You can get further help by executing sudo su smp -c "smp-server <command> -h"

+

After that, we need to configure smp-server:

+

Interactively

+

Execute the following command:

+
sudo su smp -c "smp-server init"
+
+

There are several options to consider:

+
    +
  • +

    Enable store log to restore queues and messages on server restart (Yn):

    +

    Enter y to enable saving and restoring connections and messages when the server is restarted.

    +

    Please note: it is important to use SIGINT to restart the server, as otherwise the undelivered messages will not be restored. The connections will be restored irrespective of how the server is restarted, as unlike messages they are added to append-only log on every change.

    +
  • +
  • +

    Enable logging daily statistics (yN):

    +

    Enter y to enable logging statistics in CSV format, e.g. they can be used to show aggregate usage charts in Grafana.

    +
  • +
+

These statistics include daily counts of created, secured and deleted queues, sent and received messages, and also daily, weekly, and monthly counts of active queues (that is, the queues that were used for any messages). We believe that this information does not include anything that would allow correlating different queues as belonging to the same users, but please let us know, confidentially, if you believe that this can be exploited in any way.

+
    +
  • +

    Require a password to create new messaging queues?

    +

    Enter r or your arbitrary password to password-protect smp-server, or n to disable password protection.

    +
  • +
  • +

    Enter server FQDN or IP address for certificate (127.0.0.1):

    +

    Enter your domain or ip address that your smp-server is running on - it will be included in server certificates and also printed as part of server address.

    +
  • +
+

Via command line options

+

Execute the following command:

+
sudo su smp -c "smp-server init -h"
+
+...
+Available options:
+  -l,--store-log           Enable store log for persistence
+  -s,--daily-stats         Enable logging daily server statistics
+  -a,--sign-algorithm ALG  Signature algorithm used for TLS certificates:
+                           ED25519, ED448 (default: ED448)
+  --ip IP                  Server IP address, used as Common Name for TLS online
+                           certificate if FQDN is not supplied
+                           (default: "127.0.0.1")
+  -n,--fqdn FQDN           Server FQDN used as Common Name for TLS online
+                           certificate
+  --no-password            Allow creating new queues without password
+  --password PASSWORD      Set password to create new messaging queues
+  -y,--yes                 Non-interactive initialization using command-line
+                           options
+  -h,--help                Show this help text
+
+

You should determine which flags are needed for your use-case and then execute smp-server init with -y flag for non-interactive initialization:

+
sudo su smp -c "smp-server init -y -<your flag> <your option>"
+
+

For example, run:

+
sudo su smp -c "smp-server init -y -l --ip 192.168.1.5 --password test"
+
+

to initialize your smp-server configuration with:

+
    +
  • restoring connections and messages when the server is restarted (-l flag),
  • +
  • IP address 192.168.1.5,
  • +
  • protect smp-server with a password test.
  • +
+
+

After that, your installation is complete and you should see in your teminal output something like this:

+
Certificate request self-signature ok
+subject=CN = 127.0.0.1
+Server initialized, you can modify configuration in /etc/opt/simplex/smp-server.ini.
+Run `smp-server start` to start server.
+----------
+You should store CA private key securely and delete it from the server.
+If server TLS credential is compromised this key can be used to sign a new one, keeping the same server identity and established connections.
+CA private key location: /etc/opt/simplex/ca.key
+----------
+SMP server v3.4.0
+Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+
+

The server address above should be used in your client configuration and if you added server password it should only be shared with the other people when you want to allow them to use your server to receive the messages (all your contacts will be able to send messages, as it does not require a password). If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace <hostnames> with the actual server addresses.

+

Documentation

+

All necessary files for smp-server are located in /etc/opt/simplex/ folder.

+

Stored messages, connections, statistics and server log are located in /var/opt/simplex/ folder.

+

SMP server address

+

SMP server address has the following format:

+
smp://<fingerprint>[:<password>]@<public_hostname>[,<onion_hostname>]
+
+
    +
  • +

    <fingerprint>

    +

    Your smp-server fingerprint of certificate. You can check your certificate fingerprint in /etc/opt/simplex/fingerprint.

    +
  • +
  • +

    optional <password>

    +

    Your configured password of smp-server. You can check your configured pasword in /etc/opt/simplex/smp-server.ini, under [AUTH] section in create_password: field.

    +
  • +
  • +

    <public_hostname>, optional <onion_hostname>

    +

    Your configured hostname(s) of smp-server. You can check your configured hosts in /etc/opt/simplex/smp-server.ini, under [TRANSPORT] section in host: field.

    +
  • +
+

Systemd commands

+

To start smp-server on host boot, run:

+
sudo systemctl enable smp-server.service
+
+Created symlink /etc/systemd/system/multi-user.target.wants/smp-server.service → /etc/systemd/system/smp-server.service.
+
+

To start smp-server, run:

+
sudo systemctl start smp-server.service
+
+

To check status of smp-server, run:

+
sudo systemctl status smp-server.service
+
+● smp-server.service - SMP server
+     Loaded: loaded (/etc/systemd/system/smp-server.service; enabled; vendor preset: enabled)
+     Active: active (running) since Sat 2022-11-23 19:23:21 UTC; 1min 48s ago
+   Main PID: 30878 (smp-server)
+     CGroup: /docker/5588ab759e80546b4296a7c50ffebbb1fb7b55b8401300e9201313b720989aa8/system.slice/smp-server.service
+             └─30878 smp-server start
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Started SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Store log: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Listening on port 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: not expiring inactive clients
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: creating new queues requires password
+
+

To stop smp-server, run:

+
sudo systemctl stop smp-server.service
+
+

To check tail of smp-server log, run:

+
sudo journalctl -fu smp-server.service
+
+Nov 23 19:23:21 5588ab759e80 systemd[1]: Started SMP server.
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: SMP server v3.4.0
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Fingerprint: d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Server address: smp://d5fcsc7hhtPpexYUbI2XPxDbyU2d3WsVmROimcL90ss=:V8ONoJ6ICwnrZnTC_QuSHfCEYq53uLaJKQ_oIC6-ve8=@<hostnames>
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Store log: /var/opt/simplex/smp-server-store.log
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: Listening on port 5223 (TLS)...
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: not expiring inactive clients
+Nov 23 19:23:21 5588ab759e80 smp-server[30878]: creating new queues requires password
+
+

Monitoring

+

You can enable smp-server statistics for Grafana dashboard by setting value on in /etc/opt/simplex/smp-server.ini, under [STORE_LOG] section in log_stats: field.

+

Logs will be stored as csv file in /var/opt/simplex/smp-server-stats.daily.log. Fields for the csv file are:

+
fromTime,qCreated,qSecured,qDeleted,msgSent,msgRecv,dayMsgQueues,weekMsgQueues,monthMsgQueues
+
+
    +
  • +

    fromTime - timestamp; date and time of event

    +
  • +
  • +

    qCreated - int; created queues

    +
  • +
  • +

    qSecured - int; established queues

    +
  • +
  • +

    qDeleted - int; deleted queues

    +
  • +
  • +

    msgSent - int; sent messages

    +
  • +
  • +

    msgRecv - int; received messages

    +
  • +
  • +

    dayMsgQueues - int; active queues in a day

    +
  • +
  • +

    weekMsgQueues - int; active queues in a week

    +
  • +
  • +

    monthMsgQueues - int; active queues in a month

    +
  • +
+

To import csv to Grafana one should:

+
    +
  1. +

    Install Grafana plugin: Grafana - CSV datasource

    +
  2. +
  3. +

    Allow local mode by appending following:

    +
    [plugin.marcusolsson-csv-datasource]
    +allow_local_mode = true
    +
    +

    ... to /etc/grafana/grafana.ini

    +
  4. +
  5. +

    Add a CSV data source:

    +
      +
    • In the side menu, click the Configuration tab (cog icon)
    • +
    • Click Add data source in the top-right corner of the Data Sources tab
    • +
    • Enter "CSV" in the search box to find the CSV data source
    • +
    • Click the search result that says "CSV"
    • +
    • In URL, enter a file that points to CSV content
    • +
    +
  6. +
  7. +

    You're done! You should be able to create your own dashboard with statistics.

    +
  8. +
+

For further documentation, see: CSV Data Source for Grafana - Documentation

+

Configuring the app to use the server

+

To configure the app to use your messaging server copy it's full address, including password, and add it to the app. You have an option to use your server together with preset servers or without them - you can remove or disable them.

+

It is also possible to share the address of your server with your friends by letting them scan QR code from server settings - it will include server password, so they will be able to receive messages via your server as well.

+

Please note: you need SMP server version 4.0 to have password support. If you already have a deployed server, you can add password by adding it to server INI file.

+

     

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/server_config_1.png b/docs/server_config_1.png new file mode 100644 index 0000000000..701fa502ab Binary files /dev/null and b/docs/server_config_1.png differ diff --git a/docs/server_config_2.png b/docs/server_config_2.png new file mode 100644 index 0000000000..7a7a3d7279 Binary files /dev/null and b/docs/server_config_2.png differ diff --git a/docs/server_config_3.png b/docs/server_config_3.png new file mode 100644 index 0000000000..4793f99f1a Binary files /dev/null and b/docs/server_config_3.png differ diff --git a/docs/simplex.html b/docs/simplex.html new file mode 100644 index 0000000000..122cd79aa1 --- /dev/null +++ b/docs/simplex.html @@ -0,0 +1,906 @@ + + + + + + + + + SimpleX platform + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 07.02.2023 | Languages: EN, FR, CZ |

+

SimpleX platform - motivation and comparison

+

Problems

+

Existing chat platforms and protocols have some or all of the following problems:

+
    +
  • Lack of privacy of the user profile and contacts (meta-data privacy).
  • +
  • No protection (or only optional protection) of E2EE implementations from MITM attacks via provider.
  • +
  • Unsolicited messages (spam and abuse).
  • +
  • Lack of data ownership and protection.
  • +
  • Complexity of usage for all non-centralized protocols to non-technical users.
  • +
+

The concentration of the communication in a small number of centralized platforms makes resolving these problems quite difficult.

+

Proposed solution

+

Proposed stack of protocols solves these problems by making both messages and contacts stored only on client devices, reducing the role of the servers to simple message relays that only require authorization of messages sent to the queues, but do NOT require user authentication - not only the messages but also the metadata is protected because users do not have any identifiers assigned to them - unlike with any other platforms.

+

See SimpleX whitepaper for more information on platform objectives and technical design.

+

Why use SimpleX

+

SimpleX unique approach to privacy and security

+

Everyone should care about privacy and security of their communications - even ordinary conversations can put you in danger.

+

Full privacy of your identity, profile, contacts and metadata

+

Unlike any other existing messaging platform, SimpleX has no identifiers assigned to the users - it does not use phone numbers (like Signal or WhatsApp), domain-based addresses (like email, XMPP or Matrix), usernames (like Telegram), public keys or even random numbers (like all other messengers) to identify its users - we do not even know how many people use SimpleX.

+

To deliver the messages instead of user identifiers that all other platforms use, SimpleX uses the addresses of unidirectional (simplex) message queues. Using SimpleX is like having a different email address or a phone number for each contact you have, but without the hassle of managing all these addresses. In the near future SimpleX apps will also change the message queues automatically, moving the conversations from one server to another, to provide even better privacy to the users.

+

This approach protects the privacy of who are you communicating with, hiding it from SimpleX platform servers and from any observers. You can further improve your privacy by configuring your network access to connect to SimpleX servers via some overlay transport network, e.g. Tor.

+

The best protection against spam and abuse

+

As you have no identifier on SimpleX platform, you cannot be contacted unless you share a one-time invitation link or an optional temporary user address. Even with the optional user addresses, while they can be used to send spam contact requests, you can change or completely delete it without losing any of your connections.

+

Complete ownership, control and security of your data

+

SimpleX stores all user data on client devices, the messages are only held temporarily on SimpleX relay servers until they are received.

+

We use portable database format that can be used on all supported devices - we will soon add the ability to export the chat database from the mobile app so it can be used on another device.

+

Unlike servers of federated networks (email, XMPP or Matrix), SimpleX servers do not store user accounts, they simply relay messages to the recipients, protecting the privacy of both parties. There are no identifiers or encrypted messages in common between sent and received traffic of the server, thanks to the additional encryption layer for delivered messages. So if anybody is observing server traffic, they cannot easily determine who is communicating with whom (see SimpleX whitepaper for the known traffic correlation attacks).

+

Users own SimpleX network

+

You can use SimpleX with your own servers and still communicate with people using the servers that are pre-configured in the apps or any other SimpleX servers.

+

SimpleX platform uses an open protocol and provides SDK to create chat bots, allowing implementation of services that users can interact with via SimpleX Chat apps – we are really looking forward to see what SimpleX services can be built.

+

If you are considering developing with the SimpleX platform, whether for chat bot services for SimpleX app users or to integrate the SimpleX Chat library into your mobile apps, please get in touch for any advice and support.

+

Comparison with other protocols

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SimpleX chatSignal, big platformsXMPP, MatrixP2P protocols
Requires user identifiersNo = privateYes1Yes2Yes3
Possibility of MITMNo = secureYes4YesYes
Dependence on DNSNo = resilientYesYesNo
Single operator or networkNo = decentralizedYesNoYes5
Central component or other network-wide attackNo = resilientYesYes2Yes6
+
    +
  1. Usually based on a phone number, in some cases on usernames.
  2. +
  3. DNS based.
  4. +
  5. Public key or some other globally unique ID.
  6. +
  7. If operator’s servers are compromised.
  8. +
  9. While P2P networks and cryptocurrency-based networks are distributed, they are not decentralized - they operate as a single network, with a single namespace of user addresses.
  10. +
  11. P2P networks either have a central authority or the whole network can be compromised - see the next section.
  12. +
+

Comparison with P2P messaging protocols

+

There are several P2P chat/messaging protocols and implementations that aim to solve privacy and centralisation problem, but they have their own set of problems that makes them less reliable than the proposed design, more complex to implement and analyse and more vulnerable to attacks.

+
    +
  1. +

    P2P networks use some variant of DHT to route messages/requests through the network. DHT implementations have complex designs that have to balance reliability, delivery guarantee and latency. The proposed design has both better delivery guarantees and lower latency (the message is passed multiple times in parallel, through one node each time, using servers chosen by the recipient, while in P2P networks the message is passed through O(log N) nodes sequentially, using nodes chosen by the algorithm).

    +
  2. +
  3. +

    The proposed design, unlike most P2P networks, has no global user identifiers of any kind, even temporary.

    +
  4. +
  5. +

    P2P itself does not solve MITM attack problem, and most existing solutions do not use out-of-band messages for the initial key exchange. The proposed design uses out-of-band messages or, in some cases, pre-existing secure and trusted connections for the initial key exchange.

    +
  6. +
  7. +

    P2P implementations can be blocked by some Internet providers (like BitTorrent). The proposed design is transport agnostic - it can work over standard web protocols, and the servers can be deployed on the same domains as the websites.

    +
  8. +
  9. +

    All known P2P networks are likely to be vulnerable to Sybil attack, because each node is discoverable, and the network operates as a whole. Known measures to reduce the probability of the Sybil attack either require a centralized component or expensive proof of work. The proposed design, on the opposite, has no server discoverability - servers are not connected, not known to each other and to all clients. The SimpleX network is fragmented and operates as multiple isolated connections. It makes network-wide attacks on SimpleX network impossible - even if some servers are compromised, other parts of the network can operate normally, and affected clients can switch to using other servers without losing contacts or messages.

    +
  10. +
  11. +

    P2P networks are likely to be vulnerable to DRDoS attack. In the proposed design clients only relay traffic from known trusted connection and cannot be used to reflect and amplify the traffic in the whole network.

    +
  12. +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/sql.html b/docs/sql.html new file mode 100644 index 0000000000..ebf9cb4f15 --- /dev/null +++ b/docs/sql.html @@ -0,0 +1,841 @@ + + + + + + + + + Accessing messages in the database + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 31.01.2023 | Languages: EN, FR, CZ |

+

Accessing messages in the database

+

Decrypting databases

+

In order to view database data you need to decrypt it first. Install sqlcipher using your favorite package manager and run the following commands in the directory with databases:

+
sqlcipher files_chat.db
+pragma key="youDecryptionPassphrase";
+# Ensure it works fine
+select * from users;
+
+

If you see Parse error: no such table: users, make sure you entered correct passphrase, and you have changed passphrase from random in Android app (if you got this database from Android device, of course).

+

SQL queries

+

You can run queries against direct_messages, group_messages and all_messages (or their simpler alternatives direct_messages_plain, group_messages_plain and all_messages_plain), for example:

+
-- you can put these or your preferred settings into ~/.sqliterc
+-- to persist across sqlite3 client sessions
+.mode column
+.headers on
+.nullvalue NULL
+
+-- simple views into direct, group and all_messages
+-- with user's messages deduplicated for group and all_messages;
+-- only 'x.msg.new' ("new message") chat events - filters out service events;
+-- msg_sent is 0 for received, 1 for sent
+select * from direct_messages_plain;
+select * from group_messages_plain;
+select * from all_messages_plain;
+
+-- query other details of your chat history with regular SQL, for example:
+-- files you offered for sending
+select * from direct_messages where msg_sent = 1 and chat_msg_event = 'x.file';
+-- everything catherine sent related to cats
+select * from direct_messages where msg_sent = 0 and contact = 'catherine' and msg_body like '%cats%';
+-- all correspondence with alice in #team
+select * from group_messages where group_name = 'team' and contact = 'alice';
+
+-- aggregate your chat data
+select contact_or_group, num_messages from (
+  select
+    contact as contact_or_group, count(1) as num_messages
+    from direct_messages_plain group by contact
+  union
+  select
+    group_name as contact_or_group, count(1) as num_messages
+    from group_messages_plain group by group_name
+)
+order by num_messages desc;
+
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/stun_1.png b/docs/stun_1.png new file mode 100644 index 0000000000..d40db4bbdd Binary files /dev/null and b/docs/stun_1.png differ diff --git a/docs/stun_2.png b/docs/stun_2.png new file mode 100644 index 0000000000..4bc2319c58 Binary files /dev/null and b/docs/stun_2.png differ diff --git a/docs/stun_3.png b/docs/stun_3.png new file mode 100644 index 0000000000..4b3728da51 Binary files /dev/null and b/docs/stun_3.png differ diff --git a/docs/translations.html b/docs/translations.html new file mode 100644 index 0000000000..af0e8aa3c6 --- /dev/null +++ b/docs/translations.html @@ -0,0 +1,863 @@ + + + + + + + + + Contributing translations to SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| 19.03.2023 | EN, CZ, FR |

+

Contributing translations to SimpleX Chat

+

Huge thanks for your interest in translating SimpleX Chat - it helps a lot to make it accessible to a wider range of users, and we really appreciate your help.

+

It requires a substantial time investment - most people underestimate it initially - and ongoing maintenance as we develop the application.

+

This document is created to speed up this process, and share some important "gotchas" we've discovered while working with Weblate - the platform we use for interface translations.

+

Before you start translation

+
    +
  1. +

    Create an account in Weblate, using the same email that you use in GitHub - it will make your contributions associated with your GitHub account, and might help you in some cases. Once translation is released to the users we will add your account name to the list of translators.

    +
  2. +
  3. +

    Before you start the translation there is a simple contributor license agreement to sign via Weblate - this is to avoid any conflicts around IP rights. The copy of this agreement is also available here.

    +
  4. +
  5. +

    We can also add you to the group of translators for any questions and updates - please connect to me via chat.

    +
  6. +
+

Translation progress

+
    +
  1. +

    Please start from Android app, both when you do the most time-consuming initial translation, and add any strings later. Firstly, iOS strings can be a bit delayed from appearing in Weblate, as it requires a manual step from us before they are visible. Secondary, Android app is set up as a glossary for iOS app, and 2/3 of all strings require just to clicks to transfer them from Android to iOS (it still takes some time, Weblate doesn't automate it, unfortunately).

    +
  2. +
  3. +

    Some of the strings do not need translations, but they still need to be copied over - there is a button in weblate UI for that:

    +
  4. +
+weblate: copy source to translation +
    +
  1. +

    Weblate also has automatic suggestions that can speed up the process. Sometimes they can be used as is, sometimes they need some editing - click to use them in translations.

    +
  2. +
  3. +

    Once all strings in Android app are translated, please review it to ensure consistent style and language, so that the same words are consistently used for similar user actions, same as in English. Sometimes, you will have to use different words in cases when English has just one, please try to use these choices consistently in similar contexts, to make it easier for the end users.

    +
  4. +
  5. +

    When you translate iOS app, a large part of the strings are exactly the same - they can be copied over in one click in glossary section. The visual hint that it can be done is that the whole source string is highlighted in yellow. Many other strings are very similar, they only differ in interpolation syntax or how bold font is used - they require minimal editing. There are some strings that are unique to iOS platform - they need to be translated separately.

    +
  6. +
+weblate: automatic suggestions +

Once translation is completed

+

Once both Android and iOS apps are translated, please let us know.

+

We will then:

+
    +
  • review all the translations and suggest any corrections - it also takes a bit of time :)
  • +
  • merge them to the source code - while we do it weblate will be locked for changes.
  • +
  • create beta releases of both iOS and Android apps - we can also add you to the internal tester groups, so you can install the apps before anybody else.
  • +
  • release it to our beta users - it's more than a thousand people who use our beta versions.
  • +
  • release the app and include the new language in the announcement.
  • +
+

Please note: we aim to keep app functions consistent between Android and iOS platforms, when possible, so we will release and announce a new language once both platforms have been translated. It doesn't mean you have to do it, but we will have to wait until somebody else translates the second platform. But if you start from Android, iOS usually takes 3-4x less time to add.

+

How we review the translations

+

To validate the correctness of the translations we review reverse translations by browsing Weblate pages in Google Chrome browser in "Translate to English" mode. E.g., to review the German translations of Android interface somebody from our team scrolled through these 49 pages.

+

We are not looking for reverse translation being exactly the same as the original, it is rarely the case, only that it is generally correct.

+

You would make the review much easier if you could review it in advance in the same way, and comment on any cases where reverse translations are completely different (there may be valid cases for that).

+

What is next

+
    +
  1. +

    As we update the app, we post the updates in the group of translators. You are absolutely under no obligation to translate these additional strings. We hugely appreciate if you do though, as it makes the users experience so much better when they depend on your translations, than if some new part of the app is not translated.

    +
  2. +
  3. +

    You can further help SimpleX adoption in your country / language group by translating our website (also via weblate) and/or GitHub documents (this is only possible via git)!

    +
  4. +
  5. +

    Also, if you want to be a moderator/admin of the users group in your language, once the app is translated we can host such group - we are preparing community guidelines and adding some moderation tools to the app to be released in v4.6 in March.

    +
  6. +
+

Thank you very much again for helping us grow SimpleX Chat!

+

Evgeny, SimpleX Chat founder.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/webrtc.html b/docs/webrtc.html new file mode 100644 index 0000000000..bd79745ff2 --- /dev/null +++ b/docs/webrtc.html @@ -0,0 +1,928 @@ + + + + + + + + + Using custom WebRTC ICE servers in SimpleX Chat + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

| Updated 31.01.2023 | Languages: EN, FR, CZ |

+

Using custom WebRTC ICE servers in SimpleX Chat

+

Deploy STUN/TURN server

+

For this guide, we'll be using the most featureful and battle-tested STUN/TURN server implementation – coturn and Ubuntu 20.04 LTS Linux distribution.

+
    +
  1. +

    Obtain stun.$YOUR_DOMAIN and turn.$YOUR_DOMAIN certificates.

    +

    We're using Let's Encrypt.

    +
  2. +
  3. +

    Install coturn package from the main repository.

    +
  4. +
+
apt update && apt install coturn`
+
+
    +
  1. Uncomment TURNSERVER_ENABLED=1 from /etc/default/coturn:
  2. +
+
sed -i '/TURN/s/^#//g' /etc/default/coturn
+
+
    +
  1. +

    Configure coturn in /etc/turnserver.conf:

    +

    Also, please see comments for each individual option.

    +
  2. +
+
# Also listen to 443 port for tls
+alt-tls-listening-port=443
+# Use fingerprints in the TURN messages
+fingerprint
+# Use long-term credentials mechanism
+lt-cred-mech
+# Your credentials
+user=$YOUR_LOGIN:$YOUR_PASSWORD
+# Your server domain
+server-name=$YOUR_DOMAIN
+# The default realm to be used for the users when no explicit origin/realm relationship was found
+realm=$YOUR_DOMAIN
+# Path to your certificates. Make sure they're readable by cotun process user/group
+cert=/var/lib/turn/cert.pem
+pkey=/var/lib/turn/key.pem
+# Use 2066 bits predefined DH TLS key
+dh2066
+# Log to journalctl
+syslog
+# User/group which will be running coturn service
+proc-user=turnserver
+proc-group=turnserver
+# Disable weak encryption
+no-tlsv1
+no-tlsv1_1
+no-tlsv1_2
+
+
    +
  1. Start and enable coturn service:
  2. +
+
systemctl enable coturn && systemctl start coturn
+
+
    +
  1. Optionally, if using ufw firewall, open relevant ports:
  2. +
+
    +
  • 3478 – "plain" TURN/STUN;
  • +
  • 5349 – TURN/STUN over TLS;
  • +
  • 443 – TURN/STUN over TLS, which can bypass firewalls;
  • +
  • 49152:65535 – port range that Coturn will use by default for TURN relay.
  • +
+
ufw allow 3478 && \
+ufw allow 443 && \
+ufw allow 5349 && \
+ufw allow 49152:65535/tcp && \
+ufw allow 49152:65535/udp
+
+

Configure mobile apps

+

To configure your mobile app to use your server:

+
    +
  1. +

    Open Settings / Network & Servers / WebRTC ICE servers and switch toggle Configure ICE servers.

    +
  2. +
  3. +

    Enter all server addresses in the field, one per line, for example if you servers are on the port 5349:

    +
  4. +
+
stun:stun.example.com:5349
+turn:username:password@turn.example.com:5349
+
+

This is it - you now can make audio and video calls via your own server, without sharing any data with our servers (other than the key exchange with your contact in E2E encrypted messages).

+

Troubleshoot

+
    +
  • +

    Determine if server is available:

    +

    Run this command in your terminal:

    +
    ping <your_ip_or_domain>
    +
    +

    If packets being transmitted, server is up!

    +
  • +
  • +

    Determine if ports are open:

    +

    Run this command in your terminal:

    +
    nc -zvw10 <your_ip_or_domain> 443 5349
    +
    +

    You should see:

    +
    Connection to <your_ip_or_domain> 443 port [tcp/https] succeeded!
    +Connection to <your_ip_or_domain> 5349 port [tcp/*] succeeded!
    +
    +
  • +
  • +

    Test STUN/TURN connectivity:

    +
      +
    1. +

      Go to IceTest.

      +
    2. +
    3. +

      In Build up ICE Server List section, add:

      + +
        +
      • STUN: stun:<your_ip_or_domain>:<port> and hit Add STUN
      • +
      • TURN: turn:<your_ip_or_domain>:<port>, Username: <your_login>, Credential: <your_pass> and hit Add TURN
      • +
      +

      Where <port> is 443 or 5349.

      +
    4. +
    5. +

      You should see your servers in ICE server list section. If everything is set up correctly, hit Start test:

      + +
    6. +
    7. +

      In Results section, you should see something like this:

      + +

      If results show srflx and relay candidates, everything is set up correctly!

      +
    8. +
    +
  • +
+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/xftp-server.html b/docs/xftp-server.html new file mode 100644 index 0000000000..ccb86ce748 --- /dev/null +++ b/docs/xftp-server.html @@ -0,0 +1,1009 @@ + + + + + + + + + Hosting your own XFTP Server + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+
+ +
+ + + +
+
+ + + +
+
+

Hosting your own XFTP Server

+

Overview

+

XFTP is a new file transfer protocol focussed on meta-data protection - it is based on the same principles as SimpleX Messaging Protocol used in SimpleX Chat messenger:

+
    +
  • asynchronous file delivery - the sender does not need to be online for file to be received, it is stored on XFTP relays for a limited time (currently, it is 48 hours) or until deleted by the sender.
  • +
  • padded e2e encryption of file content.
  • +
  • content padding and fixed size chunks sent via different XFTP relays, assembled back into the original file by the receiving client.
  • +
  • efficient sending to multiple recipients (the file needs to be uploaded only once).
  • +
  • no identifiers or ciphertext in common between sent and received relay traffic, same as for messages delivered by SMP relays.
  • +
  • protection of sender IP address from the recipients.
  • +
+

Installation

+
    +
  1. +

    Download xftp-server binary:

    +
    sudo curl -L https://github.com/simplex-chat/simplexmq/releases/latest/download/xftp-server-ubuntu-20_04-x86-64 -o /usr/local/bin/xftp-server && sudo chmod +x /usr/local/bin/xftp-server
    +
    +
  2. +
  3. +

    Create user and group for xftp-server:

    +
    sudo useradd -m xftp
    +
    +
  4. +
  5. +

    Create necessary directories and assign permissions:

    +
    sudo mkdir -p /var/opt/simplex-xftp /etc/opt/simplex-xftp /srv/xftp
    +sudo chown xftp:xftp /var/opt/simplex-xftp /etc/opt/simplex-xftp /srv/xftp
    +
    +
  6. +
  7. +

    Allow xftp-server port in firewall:

    +
    # For Ubuntu
    +sudo ufw allow 443
    +
    +
  8. +
  9. +

    Optional — If you're using distribution with systemd, create /etc/systemd/system/xftp-server.service file with the following content:

    +
    [Unit]
    +Description=XFTP server systemd service
    +
    +[Service]
    +User=xftp
    +Group=xftp
    +Type=simple
    +ExecStart=/usr/local/bin/xftp-server start +RTS -N -RTS
    +ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex-xftp/file-server-store.log" ] && cp "/var/opt/simplex-xftp/file-server-store.log" "/var/opt/simplex-xftp/file-server-store.log.$(date +'%FT%T')"'
    +LimitNOFILE=65535
    +KillSignal=SIGINT
    +TimeoutStopSec=infinity
    +AmbientCapabilities=CAP_NET_BIND_SERVICE
    +   
    +[Install]
    +WantedBy=multi-user.target
    +
    +

    And execute sudo systemctl daemon-reload.

    +
  10. +
+

Configuration

+

To see which options are available, execute xftp-server without flags:

+
sudo su xftp -c xftp-server
+
+...
+Available commands:
+  init                     Initialize server - creates /etc/opt/simplex-xftp and
+                           /var/opt/simplex-xftp directories and configuration
+                           files
+  start                    Start server (configuration:
+                           /etc/opt/simplex-xftp/file-server.ini)
+  delete                   Delete configuration and log files
+
+
+

You can get further help by executing su xftp -c "xftp-server <command> -h"

+

After that, we need to configure xftp-server:

+
sudo su xftp -c "xftp-server init -h"
+
+...
+Available options:
+  -l,--store-log           Enable store log for persistence
+  -a,--sign-algorithm ALG  Signature algorithm used for TLS certificates:
+                           ED25519, ED448 (default: ED448)
+  --ip IP                  Server IP address, used as Common Name for TLS online
+                           certificate if FQDN is not supplied
+                           (default: "127.0.0.1")
+  -n,--fqdn FQDN           Server FQDN used as Common Name for TLS online
+                           certificate
+  -p,--path PATH           Path to the directory to store files
+  -q,--quota QUOTA         File storage quota (e.g. 100gb)
+  -h,--help                Show this help text
+
+

You should determine which flags are needed for your use-case and then execute xftp-server init:

+
sudo su xftp -c "xftp-server init -<your flag> <your option>"
+
+

For example, run:

+
sudo su xftp -c "xftp-server init -l --ip 192.168.1.5 -q '20gb' -p /srv/xftp/"
+
+

to initialize your xftp-server configuration with:

+
    +
  • restoring connections when the server is restarted (-l flag),
  • +
  • IP address 192.168.1.5 (--ip flag),
  • +
  • set overall storage quota to 10Gb (-q flag),
  • +
  • store files in /srv/xftp directory (-p flag).
  • +
+

To password-protect your xftp-server, change it in the configuration:

+
    +
  1. +

    Open configuration with:

    +
    sudo su xftp -c "vim /etc/opt/simplex-xftp/file-server.ini"
    +
    +
  2. +
  3. +

    Under [AUTH] section uncomment create_password and change it:

    +
    ...
    +[AUTH]
    +# Set new_files option to off to completely prohibit uploading new files.
    +# This can be useful when you want to decommission the server, but still allow downloading the existing files.
    +new_files: on
    +
    +# Use create_password option to enable basic auth to upload new files.
    +# The password should be used as part of server address in client configuration:
    +# xftp://fingerprint:password@host1,host2
    +# The password will not be shared with file recipients, you must share it only
    +# with the users who you want to allow uploading files to your server.
    +create_password: your_very_secure_password
    +...
    +
    +
  4. +
+
+

After that, your installation is complete and you should see in your teminal output something like this:

+
Certificate request self-signature ok
+subject=CN = 192.168.1.5
+Server initialized, you can modify configuration in /etc/opt/simplex-xftp/file-server.ini.
+Run `file-server start` to start server.
+----------
+You should store CA private key securely and delete it from the server.
+If server TLS credential is compromised this key can be used to sign a new one, keeping the same server identity and established connections.
+CA private key location:
+/etc/opt/simplex-xftp/ca.key
+----------
+SimpleX XFTP server v0.1.0
+Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@<hostnames>
+
+

The server address above should be used in your client configuration and if you added server password it should only be shared with the other people when you want to allow them to use your server to upload files. If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace <hostnames> with the actual server addresses.

+

Documentation

+

All necessary files for xftp-server are located in /etc/opt/simplex-xftp/ folder.

+

Stored messages, connections, statistics and server log are located in /var/opt/simplex-xftp/ folder.

+

Location of uploaded files is configured by the user. In our guide we're using /srv/xftp/

+

XFTP server address

+

XFTP server address has the following format:

+
xftp://<fingerprint>[:<password>]@<public_hostname>[,<onion_hostname>]
+
+
    +
  • +

    <fingerprint>

    +

    Your xftp-server fingerprint of certificate. You can check your certificate fingerprint in /etc/opt/simplex-xftp/fingerprint.

    +
  • +
  • +

    optional <password>

    +

    Your configured password of xftp-server. You can check your configured pasword in /etc/opt/simplex-xftp/file-server.ini, under [AUTH] section in create_password: field.

    +
  • +
  • +

    <public_hostname>, optional <onion_hostname>

    +

    Your configured hostname(s) of xftp-server. You can check your configured hosts in /etc/opt/simplex-xftp/file-server.ini, under [TRANSPORT] section in host: field.

    +
  • +
+

Systemd commands

+

To start xftp-server on host boot, run:

+
sudo systemctl enable xftp-server.service
+
+Created symlink /etc/systemd/system/multi-user.target.wants/xftp-server.service → /etc/systemd/system/xftp-server.service.
+
+

To start xftp-server, run:

+
sudo systemctl start xftp-server.service
+
+

To check status of xftp-server, run:

+
sudo systemctl status xftp-server.service
+
+● xftp-server.service - XFTP server systemd service
+     Loaded: loaded (/etc/systemd/system/xftp-server.service; enabled; vendor preset: enabled)
+     Active: active (running) since Sat 2023-03-11 13:11:55 UTC; 1 months 10 days ago
+   Main PID: 110770 (xftp-server)
+      Tasks: 14 (limit: 4611)
+     Memory: 2.4G
+     CGroup: /system.slice/xftp-server.service
+             └─110770 /usr/local/bin/xftp-server start +RTS -N -RTS
+
+Feb 27 19:21:11 localhost systemd[1]: Started XFTP server systemd service.
+Feb 27 19:21:11 localhost xftp-server[2350]: SimpleX XFTP server v0.1.0
+Feb 27 19:21:11 localhost xftp-server[2350]: Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Feb 27 19:21:11 localhost xftp-server[2350]: Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@<hostnames>
+Feb 27 19:21:11 localhost xftp-server[2350]: Store log: /var/opt/simplex-xftp/file-server-store.log
+Feb 27 19:21:11 localhost xftp-server[2350]: Uploading new files allowed.
+Feb 27 19:21:11 localhost xftp-server[2350]: Listening on port 443...
+Feb 27 19:21:11 localhost xftp-server[2350]: [INFO 2023-02-27 19:21:11 +0000 src/Simplex/FileTransfer/Server/Env.hs:85] Total / available storage: 64424509440 / 64424509440
+
+

To stop xftp-server, run:

+
sudo systemctl stop xftp-server.service
+
+

To check tail of xftp-server log, run:

+
sudo journalctl -fu xftp-server.service
+
+Feb 27 19:21:11 localhost systemd[1]: Started XFTP server systemd service.
+Feb 27 19:21:11 localhost xftp-server[2350]: SimpleX XFTP server v0.1.0
+Feb 27 19:21:11 localhost xftp-server[2350]: Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Feb 27 19:21:11 localhost xftp-server[2350]: Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@<hostnames>
+Feb 27 19:21:11 localhost xftp-server[2350]: Store log: /var/opt/simplex-xftp/file-server-store.log
+Feb 27 19:21:11 localhost xftp-server[2350]: Uploading new files allowed.
+Feb 27 19:21:11 localhost xftp-server[2350]: Listening on port 443...
+Feb 27 19:21:11 localhost xftp-server[2350]: [INFO 2023-02-27 19:21:11 +0000 src/Simplex/FileTransfer/Server/Env.hs:85] Total / available storage: 64424509440 / 64424509440
+
+

Monitoring

+

You can enable xftp-server statistics for Grafana dashboard by setting value on in /etc/opt/simplex-xftp/file-server.ini, under [STORE_LOG] section in log_stats: field.

+

Logs will be stored as csv file in /var/opt/simplex-xftp/file-server-stats.daily.log. Fields for the csv file are:

+
fromTime,filesCreated,fileRecipients,filesUploaded,filesDeleted,dayCount,weekCount,monthCount,fileDownloads,fileDownloadAcks,filesCount,filesSize
+
+
    +
  • +

    fromTime - timestamp; date and time of event

    +
  • +
  • +

    filesCreated - int; chunks created

    +
  • +
  • +

    fileRecipients - int; number of file chunks recipients

    +
  • +
  • +

    filesUploaded - int; chunks uploaded

    +
  • +
  • +

    filesDeleted - int; chunks deleted

    +
  • +
  • +

    dayCount - int; uploaded chunks in a day

    +
  • +
  • +

    weekCount - int; uploaded chunks in a week

    +
  • +
  • +

    monthCount - int; uploaded chunks in a month

    +
  • +
  • +

    fileDownloads - int; chunks downloaded

    +
  • +
  • +

    filesCount - int; count of stored file chunks

    +
  • +
  • +

    filesSize - int; total size of uploaded file chunks

    +
  • +
+

To import csv to Grafana one should:

+
    +
  1. +

    Install Grafana plugin: Grafana - CSV datasource

    +
  2. +
  3. +

    Allow local mode by appending following:

    +
    [plugin.marcusolsson-csv-datasource]
    +allow_local_mode = true
    +
    +

    ... to /etc/grafana/grafana.ini

    +
  4. +
  5. +

    Add a CSV data source:

    +
      +
    • In the side menu, click the Configuration tab (cog icon)
    • +
    • Click Add data source in the top-right corner of the Data Sources tab
    • +
    • Enter "CSV" in the search box to find the CSV data source
    • +
    • Click the search result that says "CSV"
    • +
    • In URL, enter a file that points to CSV content
    • +
    +
  6. +
  7. +

    You're done! You should be able to create your own dashboard with statistics.

    +
  8. +
+

For further documentation, see: CSV Data Source for Grafana - Documentation

+

Configuring the app to use the server

+

Please see: SMP Server: Configuring the app to use the server.

+
+
+
+
+
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/en/contact/index.html b/en/contact/index.html index 990aea593c..31e9af37d9 100644 --- a/en/contact/index.html +++ b/en/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/en/index.html b/en/index.html index b9d35be08e..75cdfda652 100644 --- a/en/index.html +++ b/en/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/en/invitation/index.html b/en/invitation/index.html index e7901a9e29..1829ba34e7 100644 --- a/en/invitation/index.html +++ b/en/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/es/contact/index.html b/es/contact/index.html index 52008bfc03..aadbf2fbdc 100644 --- a/es/contact/index.html +++ b/es/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocolo de SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocolo de SimpleX Chat + + - Términos y Política de Privacidad + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Términos y Política de Privacidad + + - Donar + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donar + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/es/index.html b/es/index.html index 475ed41dd8..c7815aa118 100644 --- a/es/index.html +++ b/es/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocolo de SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocolo de SimpleX Chat + + - Términos y Política de Privacidad + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Términos y Política de Privacidad + + - Donar + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donar + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/es/invitation/index.html b/es/invitation/index.html index b562d44237..2a1f6defcc 100644 --- a/es/invitation/index.html +++ b/es/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocolo de SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocolo de SimpleX Chat + + - Términos y Política de Privacidad + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Términos y Política de Privacidad + + - Donar + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donar + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/fr/contact/index.html b/fr/contact/index.html index 0a8c7340d3..f53d70a1ba 100644 --- a/fr/contact/index.html +++ b/fr/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocole SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocole SimpleX Chat + + - Conditions et politique de confidentialité + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Conditions et politique de confidentialité + + - Faire un don + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Faire un don + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/fr/index.html b/fr/index.html index 2dd7f74aac..572958c587 100644 --- a/fr/index.html +++ b/fr/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocole SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocole SimpleX Chat + + - Conditions et politique de confidentialité + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Conditions et politique de confidentialité + + - Faire un don + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Faire un don + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/fr/invitation/index.html b/fr/invitation/index.html index f37be1459b..6c1b974ded 100644 --- a/fr/invitation/index.html +++ b/fr/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocole SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocole SimpleX Chat + + - Conditions et politique de confidentialité + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Conditions et politique de confidentialité + + - Faire un don + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Faire un don + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/img/heise-dark.png b/img/heise-dark.png new file mode 100644 index 0000000000..c87546720e Binary files /dev/null and b/img/heise-dark.png differ diff --git a/img/heise-light.png b/img/heise-light.png new file mode 100644 index 0000000000..8f5dd51635 Binary files /dev/null and b/img/heise-light.png differ diff --git a/img/kuketz-blog-dark.png b/img/kuketz-blog-dark.png new file mode 100644 index 0000000000..6a7ef79711 Binary files /dev/null and b/img/kuketz-blog-dark.png differ diff --git a/img/kuketz-blog-light.png b/img/kuketz-blog-light.png new file mode 100644 index 0000000000..5940c21993 Binary files /dev/null and b/img/kuketz-blog-light.png differ diff --git a/img/optout.jpg b/img/optout.jpg new file mode 100644 index 0000000000..3500e4d6db Binary files /dev/null and b/img/optout.jpg differ diff --git a/img/privacy-guides-dark.png b/img/privacy-guides-dark.png new file mode 100644 index 0000000000..9fbf9400e3 Binary files /dev/null and b/img/privacy-guides-dark.png differ diff --git a/img/privacy-guides-light.png b/img/privacy-guides-light.png new file mode 100644 index 0000000000..7a7acfe28e Binary files /dev/null and b/img/privacy-guides-light.png differ diff --git a/img/trail-of-bits-dark.png b/img/trail-of-bits-dark.png new file mode 100644 index 0000000000..46f4e8a91a Binary files /dev/null and b/img/trail-of-bits-dark.png differ diff --git a/img/trail-of-bits-light.png b/img/trail-of-bits-light.png new file mode 100644 index 0000000000..872133fe48 Binary files /dev/null and b/img/trail-of-bits-light.png differ diff --git a/index.html b/index.html index f67b6b98b9..75cdfda652 100644 --- a/index.html +++ b/index.html @@ -52,7 +52,35 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -60,11 +88,11 @@
-
+ +
@@ -1766,30 +1871,42 @@ window.addEventListener("load", function () {
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/invitation/index.html b/invitation/index.html index 84fbca1ffa..1829ba34e7 100644 --- a/invitation/index.html +++ b/invitation/index.html @@ -52,7 +52,35 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -60,11 +88,11 @@
-
+ +
@@ -604,30 +684,42 @@ window.addEventListener('scroll',changeHeaderBg);
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/it/contact/index.html b/it/contact/index.html index 743fe98a1b..421149bb3a 100644 --- a/it/contact/index.html +++ b/it/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocollo di SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocollo di SimpleX Chat + + - Termini e Informativa sulla privacy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Termini e Informativa sulla privacy + + - Dona + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Dona + +
- Terminale CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminale CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/it/index.html b/it/index.html index cbcc2ca61e..b831f427e8 100644 --- a/it/index.html +++ b/it/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocollo di SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocollo di SimpleX Chat + + - Termini e Informativa sulla privacy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Termini e Informativa sulla privacy + + - Dona + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Dona + +
- Terminale CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminale CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/it/invitation/index.html b/it/invitation/index.html index 6a03a00e84..1d260cb145 100644 --- a/it/invitation/index.html +++ b/it/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protocollo di SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protocollo di SimpleX Chat + + - Termini e Informativa sulla privacy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Termini e Informativa sulla privacy + + - Dona + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Dona + +
- Terminale CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminale CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/js/docs.js b/js/docs.js new file mode 100644 index 0000000000..4535fb5ea9 --- /dev/null +++ b/js/docs.js @@ -0,0 +1,91 @@ +document.addEventListener("DOMContentLoaded", function () { + const imgs = document.querySelectorAll('p img') + imgs.forEach(img => { + console.log(img.height) + img.style.height = `${img.getAttribute('height')}px` + }) + + const allParagraphs = document.querySelectorAll("p") + allParagraphs.forEach((paragraph) => { + if (paragraph.querySelector("img")) { + paragraph.style.display = "flex" + } + }) + + const docMain = document.querySelector('#doc main') + const menuBtn = document.querySelector('#doc main button.menu') + docMain.addEventListener('click', () => { + docMain.classList.remove("overlay") + document.body.classList.remove('lock-scroll') + }) + + menuBtn.addEventListener('click', (e) => { + docMain.classList.add("overlay") + document.body.classList.add('lock-scroll') + e.stopPropagation() + }) + + const headerWithIds = document.querySelectorAll('h1[id], h2[id]') + const hashList = document.querySelector('.hash-list') + + headerWithIds.forEach(header => { + const id = header.getAttribute('id') + + const listItem = document.createElement('li') + const anchor = document.createElement('a') + anchor.href = `#${id}` + anchor.textContent = header.textContent + listItem.appendChild(anchor) + hashList.appendChild(listItem) + + const hashLink = document.createElement('a') + hashLink.href = `#${id}` + hashLink.textContent = '#' + hashLink.classList.add('hash-link') + header.appendChild(hashLink) + }) + + function scrollToIdWithTopOffset(id, topOffset) { + const element = document.getElementById(id) + if (element) { + const elementRect = element.getBoundingClientRect() + const absoluteElementTop = elementRect.top + window.scrollY + const scrollToPosition = absoluteElementTop - topOffset + window.scrollTo({ top: scrollToPosition, behavior: 'smooth' }) + } + } + + function scrollToHashWithTopOffset() { + const topOffset = window.innerWidth <= 1024 ? 104 : 66 // Adjust the top offset value as needed + const hash = window.location.hash.substring(1) + + if (hash) { + setTimeout(() => { + scrollToIdWithTopOffset(hash, topOffset) + }, 0) + } + } + + document.addEventListener('click', (event) => { + const target = event.target + if (target.tagName.toLowerCase() === 'a' && target.getAttribute('href').startsWith('#')) { + event.preventDefault() + const id = target.getAttribute('href').substring(1) + + const topOffset = window.innerWidth <= 1024 ? 104 : 66 // Adjust the top offset value as needed + history.pushState(null, null, '#' + id) + + scrollToIdWithTopOffset(id, topOffset) + } + }) + + window.addEventListener('load', () => { + scrollToHashWithTopOffset() + }) + + const backToTop = document.getElementById('back-to-top') + backToTop.addEventListener('click', function (event) { + event.preventDefault() + window.scrollTo({ top: 0, behavior: 'smooth' }) + }) +}) \ No newline at end of file diff --git a/js/prism.min.js b/js/prism.min.js new file mode 100644 index 0000000000..597c2aaf7d --- /dev/null +++ b/js/prism.min.js @@ -0,0 +1,49 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+csharp+cpp+css-extras+dart+docker+ejs+git+linker-script+gradle+haskell+http+java+javadoclike+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+kotlin+makefile+markdown+markup-templating+n1ql+nginx+plsql+powerquery+powershell+python+sql+swift+typescript+typoscript+xml-doc+xquery+yaml&plugins=normalize-whitespace+toolbar+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],char:Prism.languages.c.char,comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}}}),Prism.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Prism.languages.c.boolean; +!function(e){function n(e,n){return e.replace(/<<(\d+)>>/g,(function(e,s){return"(?:"+n[+s]+")"}))}function s(e,s,a){return RegExp(n(e,s),a||"")}function a(e,n){for(var s=0;s>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var t="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var d=l(r),p=RegExp(l(t+" "+r+" "+i+" "+o)),c=l(r+" "+i+" "+o),u=l(t+" "+r+" "+o),g=a("<(?:[^<>;=+\\-*/%&|^]|<>)*>",2),b=a("\\((?:[^()]|<>)*\\)",2),h="@?\\b[A-Za-z_]\\w*\\b",f=n("<<0>>(?:\\s*<<1>>)?",[h,g]),m=n("(?!<<0>>)<<1>>(?:\\s*\\.\\s*<<1>>)*",[c,f]),k="\\[\\s*(?:,\\s*)*\\]",y=n("<<0>>(?:\\s*(?:\\?\\s*)?<<1>>)*(?:\\s*\\?)?",[m,k]),w=n("[^,()<>[\\];=+\\-*/%&|^]|<<0>>|<<1>>|<<2>>",[g,b,k]),v=n("\\(<<0>>+(?:,<<0>>+)+\\)",[w]),x=n("(?:<<0>>|<<1>>)(?:\\s*(?:\\?\\s*)?<<2>>)*(?:\\s*\\?)?",[v,m,k]),$={keyword:p,punctuation:/[<>()?,.:[\]]/},_="'(?:[^\r\n'\\\\]|\\\\.|\\\\[Uux][\\da-fA-F]{1,8})'",B='"(?:\\\\.|[^\\\\"\r\n])*"';e.languages.csharp=e.languages.extend("clike",{string:[{pattern:s("(^|[^$\\\\])<<0>>",['@"(?:""|\\\\[^]|[^\\\\"])*"(?!")']),lookbehind:!0,greedy:!0},{pattern:s("(^|[^@$\\\\])<<0>>",[B]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:s("(\\busing\\s+static\\s+)<<0>>(?=\\s*;)",[m]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+<<0>>\\s*=\\s*)<<1>>(?=\\s*;)",[h,x]),lookbehind:!0,inside:$},{pattern:s("(\\busing\\s+)<<0>>(?=\\s*=)",[h]),lookbehind:!0},{pattern:s("(\\b<<0>>\\s+)<<1>>",[d,f]),lookbehind:!0,inside:$},{pattern:s("(\\bcatch\\s*\\(\\s*)<<0>>",[m]),lookbehind:!0,inside:$},{pattern:s("(\\bwhere\\s+)<<0>>",[h]),lookbehind:!0},{pattern:s("(\\b(?:is(?:\\s+not)?|as)\\s+)<<0>>",[y]),lookbehind:!0,inside:$},{pattern:s("\\b<<0>>(?=\\s+(?!<<1>>|with\\s*\\{)<<2>>(?:\\s*[=,;:{)\\]]|\\s+(?:in|when)\\b))",[x,u,h]),inside:$}],keyword:p,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:s("([(,]\\s*)<<0>>(?=\\s*:)",[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:s("(\\b(?:namespace|using)\\s+)<<0>>(?:\\s*\\.\\s*<<0>>)*(?=\\s*[;{])",[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:s("(\\b(?:default|sizeof|typeof)\\s*\\(\\s*(?!\\s))(?:[^()\\s]|\\s(?!\\s)|<<0>>)*(?=\\s*\\))",[b]),lookbehind:!0,alias:"class-name",inside:$},"return-type":{pattern:s("<<0>>(?=\\s+(?:<<1>>\\s*(?:=>|[({]|\\.\\s*this\\s*\\[)|this\\s*\\[))",[x,m]),inside:$,alias:"class-name"},"constructor-invocation":{pattern:s("(\\bnew\\s+)<<0>>(?=\\s*[[({])",[x]),lookbehind:!0,inside:$,alias:"class-name"},"generic-method":{pattern:s("<<0>>\\s*<<1>>(?=\\s*\\()",[h,g]),inside:{function:s("^<<0>>",[h]),generic:{pattern:RegExp(g),alias:"class-name",inside:$}}},"type-list":{pattern:s("\\b((?:<<0>>\\s+<<1>>|record\\s+<<1>>\\s*<<5>>|where\\s+<<2>>)\\s*:\\s*)(?:<<3>>|<<4>>|<<1>>\\s*<<5>>|<<6>>)(?:\\s*,\\s*(?:<<3>>|<<4>>|<<6>>))*(?=\\s*(?:where|[{;]|=>|$))",[d,f,h,x,p.source,b,"\\bnew\\s*\\(\\s*\\)"]),lookbehind:!0,inside:{"record-arguments":{pattern:s("(^(?!new\\s*\\()<<0>>\\s*)<<1>>",[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:p,"class-name":{pattern:RegExp(x),greedy:!0,inside:$},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var E=B+"|"+_,R=n("/(?![*/])|//[^\r\n]*[\r\n]|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>",[E]),z=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),S="\\b(?:assembly|event|field|method|module|param|property|return|type)\\b",j=n("<<0>>(?:\\s*\\(<<1>>*\\))?",[m,z]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:s("((?:^|[^\\s\\w>)?])\\s*\\[\\s*)(?:<<0>>\\s*:\\s*)?<<1>>(?:\\s*,\\s*<<1>>)*(?=\\s*\\])",[S,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:s("^<<0>>(?=\\s*:)",[S]),alias:"keyword"},"attribute-arguments":{pattern:s("\\(<<0>>*\\)",[z]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var A=":[^}\r\n]+",F=a(n("[^\"'/()]|<<0>>|\\(<>*\\)",[R]),2),P=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[F,A]),U=a(n("[^\"'/()]|/(?!\\*)|/\\*(?:[^*]|\\*(?!/))*\\*/|<<0>>|\\(<>*\\)",[E]),2),Z=n("\\{(?!\\{)(?:(?![}:])<<0>>)*<<1>>?\\}",[U,A]);function q(n,a){return{interpolation:{pattern:s("((?:^|[^{])(?:\\{\\{)*)<<0>>",[n]),lookbehind:!0,inside:{"format-string":{pattern:s("(^\\{(?:(?![}:])<<0>>)*)<<1>>(?=\\}$)",[a,A]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:s('(^|[^\\\\])(?:\\$@|@\\$)"(?:""|\\\\[^]|\\{\\{|<<0>>|[^\\\\{"])*"',[P]),lookbehind:!0,greedy:!0,inside:q(P,F)},{pattern:s('(^|[^@\\\\])\\$"(?:\\\\.|\\{\\{|<<0>>|[^\\\\"{])*"',[Z]),lookbehind:!0,greedy:!0,inside:q(Z,U)}],char:{pattern:RegExp(_),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(Prism); +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:import|module)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); +!function(e){var a,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:a={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=a,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},i={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:i,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:i})}(Prism); +!function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extends|extension|external|factory|final|finally|for|get|hide|if|implements|import|in|interface|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{"class-name":[s,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","string",{"string-literal":{pattern:/r?(?:("""|''')[\s\S]*?\1|(["'])(?:\\.|(?!\2)[^\\\r\n])*\2(?!\2))/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,lookbehind:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:e.languages.dart}}},string:/[\s\S]+/}},string:void 0}),e.languages.insertBefore("dart","class-name",{metadata:{pattern:/@\w+/,alias:"function"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); +!function(e){var n="(?:[ \t]+(?![ \t])(?:)?|)".replace(//g,(function(){return"\\\\[\r\n](?:\\s|\\\\[\r\n]|#.*(?!.))*(?![\\s#]|\\\\[\r\n])"})),r="\"(?:[^\"\\\\\r\n]|\\\\(?:\r\n|[^]))*\"|'(?:[^'\\\\\r\n]|\\\\(?:\r\n|[^]))*'",t="--[\\w-]+=(?:|(?![\"'])(?:[^\\s\\\\]|\\\\.)+)".replace(//g,(function(){return r})),o={pattern:RegExp(r),greedy:!0},i={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function a(e,r){return e=e.replace(//g,(function(){return t})).replace(//g,(function(){return n})),RegExp(e,r)}e.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:a("(^(?:ONBUILD)?\\w+)(?:)*","i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[o,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:a("(^(?:ONBUILD)?HEALTHCHECK(?:)*)(?:CMD|NONE)\\b","i"),lookbehind:!0,greedy:!0},{pattern:a("(^(?:ONBUILD)?FROM(?:)*(?!--)[^ \t\\\\]+)AS","i"),lookbehind:!0,greedy:!0},{pattern:a("(^ONBUILD)\\w+","i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:i,string:o,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:i},e.languages.dockerfile=e.languages.docker}(Prism); +!function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism); +!function(a){a.languages.ejs={delimiter:{pattern:/^<%[-_=]?|[-_]?%>$/,alias:"punctuation"},comment:/^#[\s\S]*/,"language-javascript":{pattern:/[\s\S]+/,inside:a.languages.javascript}},a.hooks.add("before-tokenize",(function(e){a.languages["markup-templating"].buildPlaceholders(e,"ejs",/<%(?!%)[\s\S]+?%>/g)})),a.hooks.add("after-tokenize",(function(e){a.languages["markup-templating"].tokenizePlaceholders(e,"ejs")})),a.languages.eta=a.languages.ejs}(Prism); +Prism.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m}; +Prism.languages["linker-script"]={comment:{pattern:/(^|\s)\/\*[\s\S]*?(?:$|\*\/)/,lookbehind:!0,greedy:!0},identifier:{pattern:/"[^"\r\n]*"/,greedy:!0},"location-counter":{pattern:/\B\.\B/,alias:"important"},section:{pattern:/(^|[^\w*])\.\w+\b/,lookbehind:!0,alias:"keyword"},function:/\b[A-Z][A-Z_]*(?=\s*\()/,number:/\b(?:0[xX][a-fA-F0-9]+|\d+)[KM]?\b/,operator:/>>=?|<<=?|->|\+\+|--|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?/,punctuation:/[(){},;]/},Prism.languages.ld=Prism.languages["linker-script"]; +!function(e){var n={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.gradle=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:apply|def|dependencies|else|if|implementation|import|plugin|plugins|project|repositories|repository|sourceSets|tasks|val)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("gradle","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}}}),e.languages.insertBefore("gradle","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("gradle","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),n.inside.expression.inside=e.languages.gradle}(Prism); +Prism.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\/].*|$)|\{-[\s\S]*?-\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\']|\\(?:[abfnrtv\\"'&]|\^[A-Z@[\]^_]|ACK|BEL|BS|CAN|CR|DC1|DC2|DC3|DC4|DEL|DLE|EM|ENQ|EOT|ESC|ETB|ETX|FF|FS|GS|HT|LF|NAK|NUL|RS|SI|SO|SOH|SP|STX|SUB|SYN|US|VT|\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:"string"},string:{pattern:/"(?:[^\\"]|\\(?:\S|\s+\\))*"/,greedy:!0},keyword:/\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b/,"import-statement":{pattern:/(^[\t ]*)import\s+(?:qualified\s+)?(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*(?:\s+as\s+(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:as|hiding|import|qualified)\b/,punctuation:/\./}},builtin:/\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0o[0-7]+|0x[0-9a-f]+)\b/i,operator:[{pattern:/`(?:[A-Z][\w']*\.)*[_a-z][\w']*`/,greedy:!0},{pattern:/(\s)\.(?=\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\/][-!#$%*+=?&@|~.:<>^\\\/]*|\.[-!#$%*+=?&@|~.:<>^\\\/]+/],hvariable:{pattern:/\b(?:[A-Z][\w']*\.)*[_a-z][\w']*/,inside:{punctuation:/\./}},constant:{pattern:/\b(?:[A-Z][\w']*\.)*[A-Z][\w']*/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:]/},Prism.languages.hs=Prism.languages.haskell; +!function(t){function a(t){return RegExp("(^(?:"+t+"):[ \t]*(?![ \t]))[^]+","i")}t.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},header:{pattern:/^[\w-]+:.+(?:(?:\r\n?|\n)[ \t].+)*/m,inside:{"header-value":[{pattern:a("Content-Security-Policy"),lookbehind:!0,alias:["csp","languages-csp"],inside:t.languages.csp},{pattern:a("Public-Key-Pins(?:-Report-Only)?"),lookbehind:!0,alias:["hpkp","languages-hpkp"],inside:t.languages.hpkp},{pattern:a("Strict-Transport-Security"),lookbehind:!0,alias:["hsts","languages-hsts"],inside:t.languages.hsts},{pattern:a("[^:]+"),lookbehind:!0}],"header-name":{pattern:/^[^:]+/,alias:"keyword"},punctuation:/^:/}}};var e,n=t.languages,s={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css,"text/plain":n.plain},i={"application/json":!0,"application/xml":!0};function r(t){var a=t.replace(/^[a-z]+\//,"");return"(?:"+t+"|\\w+/(?:[\\w.-]+\\+)+"+a+"(?![+\\w.-]))"}for(var p in s)if(s[p]){e=e||{};var l=i[p]?r(p):p;e[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+l+"(?:(?:\r\n?|\n)[\\w-].*)*(?:\r(?:\n|(?!\n))|\n))[^ \t\\w-][^]*","i"),lookbehind:!0,inside:s[p]}}e&&t.languages.insertBefore("http","header",e)}(Prism); +!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +!function(a){var e=a.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(e,"addSupport",{value:function(e,n){"string"==typeof e&&(e=[e]),e.forEach((function(e){!function(e,n){var t="doc-comment",r=a.languages[e];if(r){var o=r[t];if(o||(o=(r=a.languages.insertBefore(e,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[t]),o instanceof RegExp&&(o=r[t]={pattern:o}),Array.isArray(o))for(var i=0,s=o.length;i]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism); +!function(e){var a=e.languages.javascript,n="\\{(?:[^{}]|\\{(?:[^{}]|\\{[^{}]*\\})*\\})+\\}",t="(@(?:arg|argument|param|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(t+"(?:(?!\\s)[$\\w\\xA0-\\uFFFF.])+(?=\\s|$)"),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(t+"\\[(?:(?!\\s)[$\\w\\xA0-\\uFFFF.])+(?:=[^[\\]]+)?\\](?=\\s|$)"),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:a,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp("(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\\s+(?:\\s+)?)[A-Z]\\w*(?:\\.[A-Z]\\w*)*".replace(//g,(function(){return n}))),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{string:a.string,number:a.number,boolean:a.boolean,keyword:e.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:a,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(Prism); +!function(a){function e(a,e){return RegExp(a.replace(//g,(function(){return"(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*"})),e)}a.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+a.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),a.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+a.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),a.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),a.languages.insertBefore("javascript","keyword",{imports:{pattern:e("(\\bimport\\b\\s*)(?:(?:\\s*,\\s*(?:\\*\\s*as\\s+|\\{[^{}]*\\}))?|\\*\\s*as\\s+|\\{[^{}]*\\})(?=\\s*\\bfrom\\b)"),lookbehind:!0,inside:a.languages.javascript},exports:{pattern:e("(\\bexport\\b\\s*)(?:\\*(?:\\s*as\\s+)?(?=\\s*\\bfrom\\b)|\\{[^{}]*\\})"),lookbehind:!0,inside:a.languages.javascript}}),a.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),a.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),a.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:e("(\\.\\s*)#?"),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var t=["function","function-variable","method","method-variable","property-access"],r=0;r|.*(?:node_modules|\(\)|\(|$|\(internal\/|\(node\.js)).*/m,alias:"comment"},filename:{pattern:/(\bat\s+(?!\s)|\()(?:[a-zA-Z]:)?[^():]+(?=:)/,lookbehind:!0,alias:"url"},function:{pattern:/(\bat\s+(?:new\s+)?)(?!\s)[_$a-zA-Z\xA0-\uFFFF<][.$\w\xA0-\uFFFF<>]*/,lookbehind:!0,inside:{punctuation:/\./}},punctuation:/[()]/,keyword:/\b(?:at|new)\b/,alias:{pattern:/\[(?:as\s+)?(?!\s)[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\]/,alias:"variable"},"line-number":{pattern:/:\d+(?::\d+)?\b/,alias:"number",inside:{punctuation:/:/}}}}}; +!function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],i=r.pattern.source;function o(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function p(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function l(t){var n={};n["interpolation-punctuation"]=a;var i=e.tokenize(t,n);if(3===i.length){var o=[1,1];o.push.apply(o,p(i[1],e.languages.javascript,"javascript")),i.splice.apply(i,o)}return new e.Token("interpolation",i,r.alias,t)}function g(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(i),lookbehind:!0}}),o=0,g={},u=p(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=s(o++,r)););return g[n]=a,n})).join(""),n,r),c=Object.keys(g);return o=0,function e(t){for(var n=0;n=c.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=c[o],i="string"==typeof r?r:r.content,s=i.indexOf(a);if(-1!==s){++o;var p=i.substring(0,s),u=l(g[a]),f=i.substring(s+a.length),y=[];if(p&&y.push(p),y.push(u),f){var v=[f];e(v),y.push.apply(y,v)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(y)),n+=y.length-1):r.content=y}}else{var d=r.content;Array.isArray(d)?e(d):e([d])}}}(u),new e.Token(r,u,"language-"+r,t)}e.languages.javascript["template-string"]=[o("css","\\b(?:styled(?:\\([^)]*\\))?(?:\\s*\\.\\s*\\w+(?:\\([^)]*\\))*)*|css(?:\\s*\\.\\s*(?:global|resolve))?|createGlobalStyle|keyframes)"),o("html","\\bhtml|\\.\\s*(?:inner|outer)HTML\\s*\\+?="),o("svg","\\bsvg"),o("markdown","\\b(?:markdown|md)"),o("graphql","\\b(?:gql|graphql(?:\\s*\\.\\s*experimental)?)"),o("sql","\\bsql"),t].filter(Boolean);var u={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function c(e){return"string"==typeof e?e:Array.isArray(e)?e.map(c).join(""):c(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in u&&function t(n){for(var r=0,a=n.length;r]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism); +Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}; +!function(n){function e(n){return n=n.replace(//g,(function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"})),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var t="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",a="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,(function(){return t})),i="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+i+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+i+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(t),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(t),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:e("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:e("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:e("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:e('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(e){["url","bold","italic","strike","code-snippet"].forEach((function(t){e!==t&&(n.languages.markdown[e].inside.content.inside[t]=n.languages.markdown[t])}))})),n.hooks.add("after-tokenize",(function(n){"markdown"!==n.language&&"md"!==n.language||function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},l=String.fromCodePoint||String.fromCharCode;n.languages.md=n.languages.markdown}(Prism); +Prism.languages.n1ql={comment:{pattern:/\/\*[\s\S]*?(?:$|\*\/)|--.*/,greedy:!0},string:{pattern:/(["'])(?:\\[\s\S]|(?!\1)[^\\]|\1\1)*\1/,greedy:!0},identifier:{pattern:/`(?:\\[\s\S]|[^\\`]|``)*`/,greedy:!0},parameter:/\$[\w.]+/,keyword:/\b(?:ADVISE|ALL|ALTER|ANALYZE|AS|ASC|AT|BEGIN|BINARY|BOOLEAN|BREAK|BUCKET|BUILD|BY|CALL|CAST|CLUSTER|COLLATE|COLLECTION|COMMIT|COMMITTED|CONNECT|CONTINUE|CORRELATE|CORRELATED|COVER|CREATE|CURRENT|DATABASE|DATASET|DATASTORE|DECLARE|DECREMENT|DELETE|DERIVED|DESC|DESCRIBE|DISTINCT|DO|DROP|EACH|ELEMENT|EXCEPT|EXCLUDE|EXECUTE|EXPLAIN|FETCH|FILTER|FLATTEN|FLUSH|FOLLOWING|FOR|FORCE|FROM|FTS|FUNCTION|GOLANG|GRANT|GROUP|GROUPS|GSI|HASH|HAVING|IF|IGNORE|ILIKE|INCLUDE|INCREMENT|INDEX|INFER|INLINE|INNER|INSERT|INTERSECT|INTO|IS|ISOLATION|JAVASCRIPT|JOIN|KEY|KEYS|KEYSPACE|KNOWN|LANGUAGE|LAST|LEFT|LET|LETTING|LEVEL|LIMIT|LSM|MAP|MAPPING|MATCHED|MATERIALIZED|MERGE|MINUS|MISSING|NAMESPACE|NEST|NL|NO|NTH_VALUE|NULL|NULLS|NUMBER|OBJECT|OFFSET|ON|OPTION|OPTIONS|ORDER|OTHERS|OUTER|OVER|PARSE|PARTITION|PASSWORD|PATH|POOL|PRECEDING|PREPARE|PRIMARY|PRIVATE|PRIVILEGE|PROBE|PROCEDURE|PUBLIC|RANGE|RAW|REALM|REDUCE|RENAME|RESPECT|RETURN|RETURNING|REVOKE|RIGHT|ROLE|ROLLBACK|ROW|ROWS|SATISFIES|SAVEPOINT|SCHEMA|SCOPE|SELECT|SELF|SEMI|SET|SHOW|SOME|START|STATISTICS|STRING|SYSTEM|TIES|TO|TRAN|TRANSACTION|TRIGGER|TRUNCATE|UNBOUNDED|UNDER|UNION|UNIQUE|UNKNOWN|UNNEST|UNSET|UPDATE|UPSERT|USE|USER|USING|VALIDATE|VALUE|VALUES|VIA|VIEW|WHERE|WHILE|WINDOW|WITH|WORK|XOR)\b/i,function:/\b[a-z_]\w*(?=\s*\()/i,boolean:/\b(?:FALSE|TRUE)\b/i,number:/(?:\b\d+\.|\B\.)\d+e[+\-]?\d+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/%]|!=|==?|\|\||<[>=]?|>=?|\b(?:AND|ANY|ARRAY|BETWEEN|CASE|ELSE|END|EVERY|EXISTS|FIRST|IN|LIKE|NOT|OR|THEN|VALUED|WHEN|WITHIN)\b/i,punctuation:/[;[\](),.{}:]/}; +!function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;e.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(Prism); +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +Prism.languages.plsql=Prism.languages.extend("sql",{comment:{pattern:/\/\*[\s\S]*?\*\/|--.*/,greedy:!0},keyword:/\b(?:A|ACCESSIBLE|ADD|AGENT|AGGREGATE|ALL|ALTER|AND|ANY|ARRAY|AS|ASC|AT|ATTRIBUTE|AUTHID|AVG|BEGIN|BETWEEN|BFILE_BASE|BINARY|BLOB_BASE|BLOCK|BODY|BOTH|BOUND|BULK|BY|BYTE|C|CALL|CALLING|CASCADE|CASE|CHAR|CHARACTER|CHARSET|CHARSETFORM|CHARSETID|CHAR_BASE|CHECK|CLOB_BASE|CLONE|CLOSE|CLUSTER|CLUSTERS|COLAUTH|COLLECT|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPILED|COMPRESS|CONNECT|CONSTANT|CONSTRUCTOR|CONTEXT|CONTINUE|CONVERT|COUNT|CRASH|CREATE|CREDENTIAL|CURRENT|CURSOR|CUSTOMDATUM|DANGLING|DATA|DATE|DATE_BASE|DAY|DECLARE|DEFAULT|DEFINE|DELETE|DESC|DETERMINISTIC|DIRECTORY|DISTINCT|DOUBLE|DROP|DURATION|ELEMENT|ELSE|ELSIF|EMPTY|END|ESCAPE|EXCEPT|EXCEPTION|EXCEPTIONS|EXCLUSIVE|EXECUTE|EXISTS|EXIT|EXTERNAL|FETCH|FINAL|FIRST|FIXED|FLOAT|FOR|FORALL|FORCE|FROM|FUNCTION|GENERAL|GOTO|GRANT|GROUP|HASH|HAVING|HEAP|HIDDEN|HOUR|IDENTIFIED|IF|IMMEDIATE|IMMUTABLE|IN|INCLUDING|INDEX|INDEXES|INDICATOR|INDICES|INFINITE|INSERT|INSTANTIABLE|INT|INTERFACE|INTERSECT|INTERVAL|INTO|INVALIDATE|IS|ISOLATION|JAVA|LANGUAGE|LARGE|LEADING|LENGTH|LEVEL|LIBRARY|LIKE|LIKE2|LIKE4|LIKEC|LIMIT|LIMITED|LOCAL|LOCK|LONG|LOOP|MAP|MAX|MAXLEN|MEMBER|MERGE|MIN|MINUS|MINUTE|MOD|MODE|MODIFY|MONTH|MULTISET|MUTABLE|NAME|NAN|NATIONAL|NATIVE|NCHAR|NEW|NOCOMPRESS|NOCOPY|NOT|NOWAIT|NULL|NUMBER_BASE|OBJECT|OCICOLL|OCIDATE|OCIDATETIME|OCIDURATION|OCIINTERVAL|OCILOBLOCATOR|OCINUMBER|OCIRAW|OCIREF|OCIREFCURSOR|OCIROWID|OCISTRING|OCITYPE|OF|OLD|ON|ONLY|OPAQUE|OPEN|OPERATOR|OPTION|OR|ORACLE|ORADATA|ORDER|ORGANIZATION|ORLANY|ORLVARY|OTHERS|OUT|OVERLAPS|OVERRIDING|PACKAGE|PARALLEL_ENABLE|PARAMETER|PARAMETERS|PARENT|PARTITION|PASCAL|PERSISTABLE|PIPE|PIPELINED|PLUGGABLE|POLYMORPHIC|PRAGMA|PRECISION|PRIOR|PRIVATE|PROCEDURE|PUBLIC|RAISE|RANGE|RAW|READ|RECORD|REF|REFERENCE|RELIES_ON|REM|REMAINDER|RENAME|RESOURCE|RESULT|RESULT_CACHE|RETURN|RETURNING|REVERSE|REVOKE|ROLLBACK|ROW|SAMPLE|SAVE|SAVEPOINT|SB1|SB2|SB4|SECOND|SEGMENT|SELECT|SELF|SEPARATE|SEQUENCE|SERIALIZABLE|SET|SHARE|SHORT|SIZE|SIZE_T|SOME|SPARSE|SQL|SQLCODE|SQLDATA|SQLNAME|SQLSTATE|STANDARD|START|STATIC|STDDEV|STORED|STRING|STRUCT|STYLE|SUBMULTISET|SUBPARTITION|SUBSTITUTABLE|SUBTYPE|SUM|SYNONYM|TABAUTH|TABLE|TDO|THE|THEN|TIME|TIMESTAMP|TIMEZONE_ABBR|TIMEZONE_HOUR|TIMEZONE_MINUTE|TIMEZONE_REGION|TO|TRAILING|TRANSACTION|TRANSACTIONAL|TRUSTED|TYPE|UB1|UB2|UB4|UNDER|UNION|UNIQUE|UNPLUG|UNSIGNED|UNTRUSTED|UPDATE|USE|USING|VALIST|VALUE|VALUES|VARIABLE|VARIANCE|VARRAY|VARYING|VIEW|VIEWS|VOID|WHEN|WHERE|WHILE|WITH|WORK|WRAPPED|WRITE|YEAR|ZONE)\b/i,operator:/:=?|=>|[<>^~!]=|\.\.|\|\||\*\*|[-+*/%<>=@]/}),Prism.languages.insertBefore("plsql","operator",{label:{pattern:/<<\s*\w+\s*>>/,alias:"symbol"}}); +Prism.languages.powerquery={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},"quoted-identifier":{pattern:/#"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},string:{pattern:/(?:#!)?"(?:[^"\r\n]|"")*"(?!")/,greedy:!0},constant:[/\bDay\.(?:Friday|Monday|Saturday|Sunday|Thursday|Tuesday|Wednesday)\b/,/\bTraceLevel\.(?:Critical|Error|Information|Verbose|Warning)\b/,/\bOccurrence\.(?:All|First|Last)\b/,/\bOrder\.(?:Ascending|Descending)\b/,/\bRoundingMode\.(?:AwayFromZero|Down|ToEven|TowardZero|Up)\b/,/\bMissingField\.(?:Error|Ignore|UseNull)\b/,/\bQuoteStyle\.(?:Csv|None)\b/,/\bJoinKind\.(?:FullOuter|Inner|LeftAnti|LeftOuter|RightAnti|RightOuter)\b/,/\bGroupKind\.(?:Global|Local)\b/,/\bExtraValues\.(?:Error|Ignore|List)\b/,/\bJoinAlgorithm\.(?:Dynamic|LeftHash|LeftIndex|PairwiseHash|RightHash|RightIndex|SortMerge)\b/,/\bJoinSide\.(?:Left|Right)\b/,/\bPrecision\.(?:Decimal|Double)\b/,/\bRelativePosition\.From(?:End|Start)\b/,/\bTextEncoding\.(?:Ascii|BigEndianUnicode|Unicode|Utf16|Utf8|Windows)\b/,/\b(?:Any|Binary|Date|DateTime|DateTimeZone|Duration|Function|Int16|Int32|Int64|Int8|List|Logical|None|Number|Record|Table|Text|Time)\.Type\b/,/\bnull\b/],boolean:/\b(?:false|true)\b/,keyword:/\b(?:and|as|each|else|error|if|in|is|let|meta|not|nullable|optional|or|otherwise|section|shared|then|try|type)\b|#(?:binary|date|datetime|datetimezone|duration|infinity|nan|sections|shared|table|time)\b/,function:{pattern:/(^|[^#\w.])[a-z_][\w.]*(?=\s*\()/i,lookbehind:!0},"data-type":{pattern:/\b(?:any|anynonnull|binary|date|datetime|datetimezone|duration|function|list|logical|none|number|record|table|text|time)\b/,alias:"class-name"},number:{pattern:/\b0x[\da-f]+\b|(?:[+-]?(?:\b\d+\.)?\b\d+|[+-]\.\d+|(^|[^.])\B\.\d+)(?:e[+-]?\d+)?\b/i,lookbehind:!0},operator:/[-+*\/&?@^]|<(?:=>?|>)?|>=?|=>?|\.\.\.?/,punctuation:/[,;\[\](){}]/},Prism.languages.pq=Prism.languages.powerquery,Prism.languages.mscript=Prism.languages.powerquery; +!function(e){var i=e.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:null},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:false|true)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/};i.string[0].inside={function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:i},boolean:i.boolean,variable:i.variable}}(Prism); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +Prism.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp('(^|[^"#])(?:"(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^(])|[^\\\\\r\n"])*"|"""(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|[^(])|[^\\\\"]|"(?!""))*""")(?!["#])'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp('(^|[^"#])(#+)(?:"(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^#])|[^\\\\\r\n])*?"|"""(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|[^#])|[^\\\\])*?""")\\2'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp("#(?:(?:elseif|if)\\b(?:[ \t]*(?:![ \t]*)?(?:\\b\\w+\\b(?:[ \t]*\\((?:[^()]|\\([^()]*\\))*\\))?|\\((?:[^()]|\\([^()]*\\))*\\))(?:[ \t]*(?:&&|\\|\\|))?)+|(?:else|endif)\\b)"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Prism.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=Prism.languages.swift})); +!function(E){var n=/\b(?:ACT|ACTIFSUB|CARRAY|CASE|CLEARGIF|COA|COA_INT|CONSTANTS|CONTENT|CUR|EDITPANEL|EFFECT|EXT|FILE|FLUIDTEMPLATE|FORM|FRAME|FRAMESET|GIFBUILDER|GMENU|GMENU_FOLDOUT|GMENU_LAYERS|GP|HMENU|HRULER|HTML|IENV|IFSUB|IMAGE|IMGMENU|IMGMENUITEM|IMGTEXT|IMG_RESOURCE|INCLUDE_TYPOSCRIPT|JSMENU|JSMENUITEM|LLL|LOAD_REGISTER|NO|PAGE|RECORDS|RESTORE_REGISTER|TEMPLATE|TEXT|TMENU|TMENUITEM|TMENU_LAYERS|USER|USER_INT|_GIFBUILDER|global|globalString|globalVar)\b/;E.languages.typoscript={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:= \t]|(?:^|[^= \t])[ \t]+)\/\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^"'])#.*/,lookbehind:!0,greedy:!0}],function:[{pattern://,inside:{string:{pattern:/"[^"\r\n]*"|'[^'\r\n]*'/,inside:{keyword:n}},keyword:{pattern:/INCLUDE_TYPOSCRIPT/}}},{pattern:/@import\s*(?:"[^"\r\n]*"|'[^'\r\n]*')/,inside:{string:/"[^"\r\n]*"|'[^'\r\n]*'/}}],string:{pattern:/^([^=]*=[< ]?)(?:(?!\]\n).)*/,lookbehind:!0,inside:{function:/\{\$.*\}/,keyword:n,number:/^\d+$/,punctuation:/[,|:]/}},keyword:n,number:{pattern:/\b\d+\s*[.{=]/,inside:{operator:/[.{=]/}},tag:{pattern:/\.?[-\w\\]+\.?/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:|]/,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/},E.languages.tsconfig=E.languages.typoscript}(Prism); +!function(a){function e(e,n){a.languages[e]&&a.languages.insertBefore(e,"comment",{"doc-comment":n})}var n=a.languages.markup.tag,t={pattern:/\/\/\/.*/,greedy:!0,alias:"comment",inside:{tag:n}},g={pattern:/'''.*/,greedy:!0,alias:"comment",inside:{tag:n}};e("csharp",t),e("fsharp",t),e("vbnet",g)}(Prism); +!function(e){e.languages.xquery=e.languages.extend("markup",{"xquery-comment":{pattern:/\(:[\s\S]*?:\)/,greedy:!0,alias:"comment"},string:{pattern:/(["'])(?:\1\1|(?!\1)[\s\S])*\1/,greedy:!0},extension:{pattern:/\(#.+?#\)/,alias:"symbol"},variable:/\$[-\w:]+/,axis:{pattern:/(^|[^-])(?:ancestor(?:-or-self)?|attribute|child|descendant(?:-or-self)?|following(?:-sibling)?|parent|preceding(?:-sibling)?|self)(?=::)/,lookbehind:!0,alias:"operator"},"keyword-operator":{pattern:/(^|[^:-])\b(?:and|castable as|div|eq|except|ge|gt|idiv|instance of|intersect|is|le|lt|mod|ne|or|union)\b(?=$|[^:-])/,lookbehind:!0,alias:"operator"},keyword:{pattern:/(^|[^:-])\b(?:as|ascending|at|base-uri|boundary-space|case|cast as|collation|construction|copy-namespaces|declare|default|descending|else|empty (?:greatest|least)|encoding|every|external|for|function|if|import|in|inherit|lax|let|map|module|namespace|no-inherit|no-preserve|option|order(?: by|ed|ing)?|preserve|return|satisfies|schema|some|stable|strict|strip|then|to|treat as|typeswitch|unordered|validate|variable|version|where|xquery)\b(?=$|[^:-])/,lookbehind:!0},function:/[\w-]+(?::[\w-]+)*(?=\s*\()/,"xquery-element":{pattern:/(element\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"tag"},"xquery-attribute":{pattern:/(attribute\s+)[\w-]+(?::[\w-]+)*/,lookbehind:!0,alias:"attr-name"},builtin:{pattern:/(^|[^:-])\b(?:attribute|comment|document|element|processing-instruction|text|xs:(?:ENTITIES|ENTITY|ID|IDREFS?|NCName|NMTOKENS?|NOTATION|Name|QName|anyAtomicType|anyType|anyURI|base64Binary|boolean|byte|date|dateTime|dayTimeDuration|decimal|double|duration|float|gDay|gMonth|gMonthDay|gYear|gYearMonth|hexBinary|int|integer|language|long|negativeInteger|nonNegativeInteger|nonPositiveInteger|normalizedString|positiveInteger|short|string|time|token|unsigned(?:Byte|Int|Long|Short)|untyped(?:Atomic)?|yearMonthDuration))\b(?=$|[^:-])/,lookbehind:!0},number:/\b\d+(?:\.\d+)?(?:E[+-]?\d+)?/,operator:[/[+*=?|@]|\.\.?|:=|!=|<[=<]?|>[=>]?/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}],punctuation:/[[\](){},;:/]/}),e.languages.xquery.tag.pattern=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/,e.languages.xquery.tag.inside["attr-value"].pattern=/=(?:("|')(?:\\[\s\S]|\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}|(?!\1)[^\\])*\1|[^\s'">=]+)/,e.languages.xquery.tag.inside["attr-value"].inside.punctuation=/^="|"$/,e.languages.xquery.tag.inside["attr-value"].inside.expression={pattern:/\{(?!\{)(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])+\}/,inside:e.languages.xquery,alias:"language-xquery"};var t=function(e){return"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(t).join("")},n=function(a){for(var o=[],i=0;i0&&o[o.length-1].tagName===t(r.content[0].content[1])&&o.pop():"/>"===r.content[r.content.length-1].content||o.push({tagName:t(r.content[0].content[1]),openedBraces:0}):!(o.length>0&&"punctuation"===r.type&&"{"===r.content)||a[i+1]&&"punctuation"===a[i+1].type&&"{"===a[i+1].content||a[i-1]&&"plain-text"===a[i-1].type&&"{"===a[i-1].content?o.length>0&&o[o.length-1].openedBraces>0&&"punctuation"===r.type&&"}"===r.content?o[o.length-1].openedBraces--:"comment"!==r.type&&(s=!0):o[o.length-1].openedBraces++),(s||"string"==typeof r)&&o.length>0&&0===o[o.length-1].openedBraces){var l=t(r);i0&&("string"==typeof a[i-1]||"plain-text"===a[i-1].type)&&(l=t(a[i-1])+l,a.splice(i-1,1),i--),/^\s+$/.test(l)?a[i]=l:a[i]=new e.Token("plain-text",l,null,l)}r.content&&"string"!=typeof r.content&&n(r.content)}};e.hooks.add("after-tokenize",(function(e){"xquery"===e.language&&n(e.tokens)}))}(Prism); +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +!function(){if("undefined"!=typeof Prism){var e=Object.assign||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},t={"remove-trailing":"boolean","remove-indent":"boolean","left-trim":"boolean","right-trim":"boolean","break-lines":"number",indent:"number","remove-initial-line-feed":"boolean","tabs-to-spaces":"number","spaces-to-tabs":"number"};n.prototype={setDefaults:function(t){this.defaults=e(this.defaults,t)},normalize:function(t,n){for(var r in n=e(this.defaults,n)){var i=r.replace(/-(\w)/g,(function(e,t){return t.toUpperCase()}));"normalize"!==r&&"setDefaults"!==i&&n[r]&&this[i]&&(t=this[i].call(this,t,n[r]))}return t},leftTrim:function(e){return e.replace(/^\s+/,"")},rightTrim:function(e){return e.replace(/\s+$/,"")},tabsToSpaces:function(e,t){return t=0|t||4,e.replace(/\t/g,new Array(++t).join(" "))},spacesToTabs:function(e,t){return t=0|t||4,e.replace(RegExp(" {"+t+"}","g"),"\t")},removeTrailing:function(e){return e.replace(/\s*?$/gm,"")},removeInitialLineFeed:function(e){return e.replace(/^(?:\r?\n|\r)/,"")},removeIndent:function(e){var t=e.match(/^[^\S\n\r]*(?=\S)/gm);return t&&t[0].length?(t.sort((function(e,t){return e.length-t.length})),t[0].length?e.replace(RegExp("^"+t[0],"gm"),""):e):e},indent:function(e,t){return e.replace(/^[^\S\n\r]*(?=\S)/gm,new Array(++t).join("\t")+"$&")},breakLines:function(e,t){t=!0===t?80:0|t||80;for(var n=e.split("\n"),i=0;it&&(o[l]="\n"+o[l],a=s)}n[i]=o.join("")}return n.join("\n")}},"undefined"!=typeof module&&module.exports&&(module.exports=n),Prism.plugins.NormalizeWhitespace=new n({"remove-trailing":!0,"remove-indent":!0,"left-trim":!0,"right-trim":!0}),Prism.hooks.add("before-sanity-check",(function(e){var n=Prism.plugins.NormalizeWhitespace;if((!e.settings||!1!==e.settings["whitespace-normalization"])&&Prism.util.isActive(e.element,"whitespace-normalization",!0))if(e.element&&e.element.parentNode||!e.code){var r=e.element.parentNode;if(e.code&&r&&"pre"===r.nodeName.toLowerCase()){for(var i in null==e.settings&&(e.settings={}),t)if(Object.hasOwnProperty.call(t,i)){var o=t[i];if(r.hasAttribute("data-"+i))try{var a=JSON.parse(r.getAttribute("data-"+i)||"true");typeof a===o&&(e.settings[i]=a)}catch(e){}}for(var l=r.childNodes,s="",c="",u=!1,m=0;m
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Voorwaarden & Privacybeleid + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Voorwaarden & Privacybeleid + + - Doneer + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Doneer + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/nl/index.html b/nl/index.html index 3e9acc41c2..0796489552 100644 --- a/nl/index.html +++ b/nl/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Voorwaarden & Privacybeleid + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Voorwaarden & Privacybeleid + + - Doneer + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Doneer + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/nl/invitation/index.html b/nl/invitation/index.html index 9cba13813f..cc5f334aba 100644 --- a/nl/invitation/index.html +++ b/nl/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Voorwaarden & Privacybeleid + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Voorwaarden & Privacybeleid + + - Doneer + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Doneer + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pl/contact/index.html b/pl/contact/index.html index bc8c03ad12..7cec04e1e6 100644 --- a/pl/contact/index.html +++ b/pl/contact/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protokół SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protokół SimpleX Chat + + - Warunki i polityka prywatności + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Warunki i polityka prywatności + + - Darowizna + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darowizna + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pl/index.html b/pl/index.html index 30dd4b2834..a902ba7064 100644 --- a/pl/index.html +++ b/pl/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protokół SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protokół SimpleX Chat + + - Warunki i polityka prywatności + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Warunki i polityka prywatności + + - Darowizna + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darowizna + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pl/invitation/index.html b/pl/invitation/index.html index e832745244..1ece868766 100644 --- a/pl/invitation/index.html +++ b/pl/invitation/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - Protokół SimpleX Chat + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Protokół SimpleX Chat + + - Warunki i polityka prywatności + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Warunki i polityka prywatności + + - Darowizna + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Darowizna + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pt_BR/contact/index.html b/pt_BR/contact/index.html index 6eeb27a651..ca037a1fe7 100644 --- a/pt_BR/contact/index.html +++ b/pt_BR/contact/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pt_BR/index.html b/pt_BR/index.html index fae6eddab3..1cf6836e18 100644 --- a/pt_BR/index.html +++ b/pt_BR/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/pt_BR/invitation/index.html b/pt_BR/invitation/index.html index e3f732a301..07520af53a 100644 --- a/pt_BR/invitation/index.html +++ b/pt_BR/invitation/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/uk/contact/index.html b/uk/contact/index.html index 6470773cb1..07d22bafcf 100644 --- a/uk/contact/index.html +++ b/uk/contact/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/uk/index.html b/uk/index.html index 0f3df875c5..56a40e889c 100644 --- a/uk/index.html +++ b/uk/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/uk/invitation/index.html b/uk/invitation/index.html index c95535e859..207ec81e10 100644 --- a/uk/invitation/index.html +++ b/uk/invitation/index.html @@ -50,19 +50,45 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX Chat protocol + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Chat protocol + + - Terms & Privacy Policy + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terms & Privacy Policy + + - Donate + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Donate + +
- Terminal CLI + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + Terminal CLI + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/zh_Hans/contact/index.html b/zh_Hans/contact/index.html index a5c39108ec..94b4bdfdd6 100644 --- a/zh_Hans/contact/index.html +++ b/zh_Hans/contact/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX 聊天协议 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX 聊天协议 + + - 条款和隐私政策 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 条款和隐私政策 + + - 捐赠 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 捐赠 + +
- 终端命令行 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 终端命令行 + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/zh_Hans/index.html b/zh_Hans/index.html index ac4ea7f1be..6ca2141ad0 100644 --- a/zh_Hans/index.html +++ b/zh_Hans/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX 聊天协议 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX 聊天协议 + + - 条款和隐私政策 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 条款和隐私政策 + + - 捐赠 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 捐赠 + +
- 终端命令行 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 终端命令行 + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +
diff --git a/zh_Hans/invitation/index.html b/zh_Hans/invitation/index.html index a026aea615..ef4e00e8b7 100644 --- a/zh_Hans/invitation/index.html +++ b/zh_Hans/invitation/index.html @@ -52,19 +52,47 @@
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - + + + +
-
+ +
- logo - + logo +
- SimpleX Whitepaper + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX Whitepaper + + - SimpleX 聊天协议 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + SimpleX 聊天协议 + + - 条款和隐私政策 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 条款和隐私政策 + + - 捐赠 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 捐赠 + +
- 终端命令行 + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + 终端命令行 + + - TypeScript SDK + class="text-grey-black dark:text-white text-[14px] font-medium leading-[28px] tracking-[0.01em] mb-3 flex items-center gap-1"> + TypeScript SDK + +