Compare commits
53 Commits
v1.7.20
...
travis/thi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdd34120f0 | ||
|
|
0c6c0f32dd | ||
|
|
447db3df62 | ||
|
|
24a695e9a3 | ||
|
|
8c4b8f281c | ||
|
|
19a07bc4a2 | ||
|
|
438eef0acd | ||
|
|
e15d1c1501 | ||
|
|
92a5787528 | ||
|
|
af2da9d371 | ||
|
|
68c36ebb49 | ||
|
|
72e60efadc | ||
|
|
e91e513224 | ||
|
|
a500240d04 | ||
|
|
3e57378631 | ||
|
|
42e2ea877a | ||
|
|
2332cecb59 | ||
|
|
27a92a5c89 | ||
|
|
4ce13765f7 | ||
|
|
e562c54ddc | ||
|
|
993c2e50b5 | ||
|
|
11cc33c8d2 | ||
|
|
9f4d75f2ed | ||
|
|
52f469d7c9 | ||
|
|
29639bb0e6 | ||
|
|
0d4958319b | ||
|
|
dfd17fedfe | ||
|
|
cfadc616b2 | ||
|
|
816ea3d904 | ||
|
|
cefe8cf379 | ||
|
|
4acdb7c715 | ||
|
|
105d1c8c41 | ||
|
|
4f852f3d69 | ||
|
|
1b276c9e00 | ||
|
|
fb67a14486 | ||
|
|
ab828ac6d9 | ||
|
|
b22484d203 | ||
|
|
b617cb78e7 | ||
|
|
c6e94c61db | ||
|
|
9a32dd7071 | ||
|
|
8d604ced78 | ||
|
|
93f1cb6ecb | ||
|
|
1f71eb1b33 | ||
|
|
92d63579af | ||
|
|
59f82eaf0a | ||
|
|
50adc958c3 | ||
|
|
173ca66f29 | ||
|
|
ade9babb80 | ||
|
|
d4627576c8 | ||
|
|
49d3d5dffe | ||
|
|
9133b80f2b | ||
|
|
97925a6ad9 | ||
|
|
3456b4c58a |
51
README.md
51
README.md
@@ -31,7 +31,7 @@ Getting Started
|
||||
===============
|
||||
|
||||
The easiest way to test Element is to just use the hosted copy at https://app.element.io.
|
||||
The `develop` branch is continuously deployed by Jenkins at https://develop.element.io
|
||||
The `develop` branch is continuously deployed to https://develop.element.io
|
||||
for those who like living dangerously.
|
||||
|
||||
To host your own copy of Element, the quickest bet is to use a pre-built
|
||||
@@ -58,8 +58,11 @@ and thus allowed.
|
||||
To install Element as a desktop application, see [Running as a desktop
|
||||
app](#running-as-a-desktop-app) below.
|
||||
|
||||
Important Security Note
|
||||
=======================
|
||||
Important Security Notes
|
||||
========================
|
||||
|
||||
Separate domains
|
||||
----------------
|
||||
|
||||
We do not recommend running Element from the same domain name as your Matrix
|
||||
homeserver. The reason is the risk of XSS (cross-site-scripting)
|
||||
@@ -71,6 +74,45 @@ We have put some coarse mitigations into place to try to protect against this
|
||||
situation, but it's still not good practice to do it in the first place. See
|
||||
https://github.com/vector-im/element-web/issues/1977 for more details.
|
||||
|
||||
Configuration best practices
|
||||
----------------------------
|
||||
|
||||
Unless you have special requirements, you will want to add the following to
|
||||
your web server configuration when hosting Element Web:
|
||||
|
||||
- The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being
|
||||
framed and protect from [clickjacking][owasp-clickjacking].
|
||||
- The `frame-ancestors 'none'` directive to your `Content-Security-Policy`
|
||||
header, as the modern replacement for `X-Frame-Options` (though both should be
|
||||
included since not all browsers support it yet, see
|
||||
[this][owasp-clickjacking-csp]).
|
||||
- The `X-Content-Type-Options: nosniff` header, to [disable MIME
|
||||
sniffing][mime-sniffing].
|
||||
- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
|
||||
legacy browsers.
|
||||
|
||||
[mime-sniffing]:
|
||||
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing>
|
||||
|
||||
[owasp-clickjacking-csp]:
|
||||
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html#content-security-policy-frame-ancestors-examples>
|
||||
|
||||
[owasp-clickjacking]:
|
||||
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html>
|
||||
|
||||
If you are using nginx, this would look something like the following:
|
||||
|
||||
```
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Content-Security-Policy "frame-ancestors 'none'";
|
||||
```
|
||||
|
||||
Note: In case you are already setting a `Content-Security-Policy` header
|
||||
elsewhere, you should modify it to include the `frame-ancestors` directive
|
||||
instead of adding that last line.
|
||||
|
||||
Building From Source
|
||||
====================
|
||||
|
||||
@@ -99,7 +141,8 @@ guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it alread
|
||||
Note that `yarn dist` is not supported on Windows, so Windows users can run `yarn build`,
|
||||
which will build all the necessary files into the `webapp` directory. The version of Element
|
||||
will not appear in Settings without using the dist script. You can then mount the
|
||||
`webapp` directory on your webserver to actually serve up the app, which is entirely static content.
|
||||
`webapp` directory on your web server to actually serve up the app, which is
|
||||
entirely static content.
|
||||
|
||||
Running as a Desktop app
|
||||
========================
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
"siteId": 1,
|
||||
"policyUrl": "https://element.io/cookie-policy"
|
||||
},
|
||||
"countly": {
|
||||
"url": "https://try.count.ly",
|
||||
"appKey": "8abf1ee15646bc884556b82e5053857904264b66"
|
||||
},
|
||||
"roomDirectory": {
|
||||
"servers": [
|
||||
"matrix.org",
|
||||
|
||||
@@ -58,16 +58,15 @@
|
||||
"highlight.js": "^10.5.0",
|
||||
"jsrsasign": "^10.1.5",
|
||||
"katex": "^0.12.0",
|
||||
"matrix-js-sdk": "9.6.0",
|
||||
"matrix-react-sdk": "3.13.1",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
||||
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
|
||||
"matrix-widget-api": "^0.1.0-beta.13",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"sanitize-html": "github:apostrophecms/sanitize-html#3c7f93f2058f696f5359e3e58d464161647226db",
|
||||
"ua-parser-js": "^0.7.23",
|
||||
"url": "^0.11.0"
|
||||
"ua-parser-js": "^0.7.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
@@ -125,6 +124,7 @@
|
||||
"modernizr": "^3.11.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"postcss-calc": "^7.0.5",
|
||||
"postcss-easings": "^2.0.0",
|
||||
"postcss-extend": "^1.0.5",
|
||||
"postcss-hexrgba": "^2.0.1",
|
||||
|
||||
12
src/@types/global.d.ts
vendored
12
src/@types/global.d.ts
vendored
@@ -39,18 +39,20 @@ declare global {
|
||||
matrixChat: ReturnType<Renderer>;
|
||||
|
||||
// electron-only
|
||||
electron: {
|
||||
on(channel: ElectronChannel, listener: (event: Event, ...args: any[]) => void): void;
|
||||
send(channel: ElectronChannel, ...args: any[]): void;
|
||||
}
|
||||
electron?: Electron;
|
||||
|
||||
// opera-only
|
||||
opera: any;
|
||||
opera?: any;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/InstallTrigger
|
||||
InstallTrigger: any;
|
||||
}
|
||||
|
||||
interface Electron {
|
||||
on(channel: ElectronChannel, listener: (event: Event, ...args: any[]) => void): void;
|
||||
send(channel: ElectronChannel, ...args: any[]): void;
|
||||
}
|
||||
|
||||
interface Navigator {
|
||||
// PWA badging extensions https://w3c.github.io/badging/
|
||||
setAppBadge?(count: number): Promise<void>;
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
"Dismiss": "Omet",
|
||||
"Unknown device": "Dispositiu desconegut",
|
||||
"Welcome to Element": "Benvingut/da a Element",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Necessites utilitzar HTTPS per poder fer una trucada amb pantalla compartida.",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Has d'utilitzar HTTPS per poder fer una trucada amb pantalla compartida.",
|
||||
"powered by Matrix": "amb tecnologia de Matrix",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Xat descentralitzat, encriptat & col·laboratiu amb tecnologia de [matrix]",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Xat descentralitzat, xifrat i col·laboratiu amb tecnologia de [matrix]",
|
||||
"Create Account": "Crea un compte",
|
||||
"Explore rooms": "Explora sales",
|
||||
"Sign In": "Inicia la sessió",
|
||||
"Sign In": "Inicia sessió",
|
||||
"Invalid configuration: no default server specified.": "Configuració invàlida: no s'ha especificat cap servidor predeterminat.",
|
||||
"Invalid JSON": "JSON invàlid",
|
||||
"Go to your browser to complete Sign In": "Ves al teu navegador per completar l'inici de sessió",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuració invàlida: només pots especificar una sol de default_server_config, default_server_name, o default_hs_url.",
|
||||
"Go to your browser to complete Sign In": "Vés al navegador per completar l'inici de sessió",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuració invàlida: només pots especificar una únic default_server_config, default_server_name, o default_hs_url.",
|
||||
"Your Element is misconfigured": "Element està mal configurat",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "La configuració d'Element conté un JSON invàlid. Arregla el problema i actualitza la pàgina.",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "La configuració d'Element conté un JSON invàlid. Soluciona el problema i actualitza la pàgina.",
|
||||
"The message from the parser is: %(message)s": "El missatge de l'analitzador és: %(message)s",
|
||||
"Unable to load config file: please refresh the page to try again.": "No s'ha pogut carregar el fitxer de configuració: actualitza la pàgina per tornar-ho a provar.",
|
||||
"Unexpected error preparing the app. See console for details.": "Error inesperat preparant l'app. Consulta la consola pels a més detalls.",
|
||||
"Download Completed": "Descàrrega completada",
|
||||
"Unexpected error preparing the app. See console for details.": "Error inesperat durant la preparació de l'aplicació. Consulta la consola pels a més detalls.",
|
||||
"Download Completed": "Baixada completada",
|
||||
"Open": "Obre",
|
||||
"Open user settings": "Obre la configuració d'usuari",
|
||||
"Previous/next recently visited room or community": "Anterior/següent sala o comunitat visitada recentment",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Dezentrale, verschlüsselte Chat- & Kollaborationslösung mittels [matrix]",
|
||||
"Sign In": "Anmelden",
|
||||
"Create Account": "Account erstellen",
|
||||
"Explore rooms": "Erkunde Räume",
|
||||
"Explore rooms": "Räume erkunden",
|
||||
"Unexpected error preparing the app. See console for details.": "Unerwarteter Fehler bei der Vorbereitung der App. Siehe Konsole für Details.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Ungültige Konfiguration: Es kann nur eine der Optionen default_server_config, default_server_name oder default_hs_url angegeben werden.",
|
||||
"Invalid configuration: no default server specified.": "Ungültige Konfiguration: Es wurde kein Standardserver angegeben.",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Απαιτείται η χρήση HTTPS για την πραγματοποίηση κλήσης διαμοιρασμού επιφάνειας εργασίας.",
|
||||
"powered by Matrix": "λειτουργεί με το Matrix",
|
||||
"Welcome to Element": "Καλώς ήλθατε στο Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Αποκεντρωμένη, κρυπτογραφημένη συνομιλία και συνεργασία χρησιμοποιώντας το [matrix]",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Αποκεντρωμένη, κρυπτογραφημένη συνεργασία συνομιλίας χρησιμοποιώντας το [matrix]",
|
||||
"Sign In": "Σύνδεση",
|
||||
"Create Account": "Δημιουργία Λογαριασμού",
|
||||
"The message from the parser is: %(message)s": "Το μήνυμα από τον αναλυτή είναι: %(message)s",
|
||||
|
||||
@@ -3,34 +3,34 @@
|
||||
"Dismiss": "Omitir",
|
||||
"powered by Matrix": "con el poder de Matrix",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Debes usar HTTPS para hacer una llamada con pantalla compartida.",
|
||||
"Welcome to Element": "Bienvenido a Element",
|
||||
"Welcome to Element": "Te damos la bienvenida a Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Conversaciones cifradas y descentralizadas & colaboración impulsada por [matrix]",
|
||||
"Sign In": "Iniciar sesión",
|
||||
"Create Account": "Crear cuenta",
|
||||
"Explore rooms": "Explorar salas",
|
||||
"Unexpected error preparing the app. See console for details.": "Error inesperado preparando la aplicación. Vea la consola para más detalles.",
|
||||
"Unexpected error preparing the app. See console for details.": "Error inesperado preparando la aplicación. Ver la consola para más detalles.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuración errónea: sólo puede especificar uno de default_server_config, default_server_name, o default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Configuración errónea: no se ha especificado servidor.",
|
||||
"The message from the parser is: %(message)s": "El mensaje del parser es: %(message)s",
|
||||
"Invalid JSON": "JSON inválido",
|
||||
"Open user settings": "Abrir opciones de usuario",
|
||||
"Go to your browser to complete Sign In": "Abre tu navegador web para completar el registro",
|
||||
"Missing indexeddb worker script!": "Falta el script de trabajo indexeddb!",
|
||||
"Unable to load config file: please refresh the page to try again.": "No se ha podido cargar el archivo de configuración. Recarga la página para intentar nuevamente.",
|
||||
"Missing indexeddb worker script!": "¡Falta el script de trabajo indexeddb!",
|
||||
"Unable to load config file: please refresh the page to try again.": "No se ha podido cargar el archivo de configuración. Recarga la página para intentarlo otra vez.",
|
||||
"Previous/next recently visited room or community": "Anterior/siguiente sala o comunidad visitada recientemente",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Escritorio (%(platformName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s de escritorio (%(platformName)s)",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"Unsupported browser": "Navegador no soportado",
|
||||
"Unsupported browser": "Navegador no compatible",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Por favor, instale <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, o <safariLink>Safari</safariLink> para la mejor experiencia.",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Puedes seguir utilizando tu navegador actual, pero puede que algunas funcionalidades no estén disponibles o que algunas partes de la aplicación se muestren de forma incorrecta.",
|
||||
"I understand the risks and wish to continue": "Entiendo los riesgos y deseo continuar",
|
||||
"Go to element.io": "Ir a element.io",
|
||||
"Failed to start": "Fallo al iniciar",
|
||||
"Your Element is misconfigured": "Tu elemento está mal configurado",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Su configuración de Element contiene JSON inválido. Por favor corríjalo e inténtelo de nuevo.",
|
||||
"Your Element is misconfigured": "Element está mal configurado",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Tu configuración de Element contiene JSON inválido. Por favor corrígelo e inténtelo de nuevo.",
|
||||
"Download Completed": "Descarga completada",
|
||||
"Open": "Abrir",
|
||||
"Your browser can't run %(brand)s": "Su navegador es incompatible con %(brand)s",
|
||||
"Your browser can't run %(brand)s": "Su navegador no es compatible con %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s usa funciones avanzadas que su navegador actual no soporta.",
|
||||
"Powered by Matrix": "Desarrollado por Matrix"
|
||||
"Powered by Matrix": "Funciona con Matrix"
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"Unexpected error preparing the app. See console for details.": "アプリケーションの準備中に予期しないエラーが発生しました。詳細はコンソールを参照してください。",
|
||||
"Invalid configuration: no default server specified.": "不正な設定です:デフォルトのサーバーが設定されていません。",
|
||||
"Sign In": "サインイン",
|
||||
"Create Account": "アカウント作成",
|
||||
"Explore rooms": "部屋を探索する",
|
||||
"Create Account": "アカウントの作成",
|
||||
"Explore rooms": "部屋を探す",
|
||||
"The message from the parser is: %(message)s": "パーザーのメッセージ: %(message)s",
|
||||
"Invalid JSON": "妥当でないJSON",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "無効な設定: default_server_config、default_server_name、または default_hs_urlのいずれか一つのみが指定できます。",
|
||||
@@ -31,5 +31,6 @@
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Elementの設定ファイルに不正なJSONが含まれています。問題を修正してからページを再読込してください。",
|
||||
"Your browser can't run %(brand)s": "このブラウザでは%(brand)sが動きません",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)sはブラウザの高度な機能を使う必要がありますが、このブラウザではその機能がサポートされていないようです。",
|
||||
"Powered by Matrix": "Powered by Matrix"
|
||||
"Powered by Matrix": "Powered by Matrix",
|
||||
"Previous/next recently visited room or community": "最近利用したルームまたはコミュニティ"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"Open user settings": "Atvērt lietotāja iestatījumus",
|
||||
"Go to your browser to complete Sign In": "Pārejiet uz pārlūku, lai pabeigtu pierakstīšanos",
|
||||
"Unsupported browser": "Neatbalstīts pārlūks",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Labākajai izmantošanas pieredzei, lūdzu, instalē <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> vai <safariLink>Safari</safariLink> pārlūku.",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Labākajai izmantošanas pieredzei, lūdzu, instalējiet <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> vai <safariLink>Safari</safariLink> pārlūku.",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Jūs varat turpināt lietot savu pašreizējo pārlūku, bet dažas vai visas funkcijas nestrādās, un lietotnes izskats var būt nepareizs.",
|
||||
"I understand the risks and wish to continue": "Es pieņemu riskus un vēlos turpināt",
|
||||
"Go to element.io": "Ej uz element.io",
|
||||
@@ -30,5 +30,7 @@
|
||||
"Open": "Atvērt",
|
||||
"Download Completed": "Lejupielāde pabeigta",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Jūsu Element konfigurācija satur kļūdainu JSON. Lūdzu, salabojiet problēmu un pārlādējiet lapu.",
|
||||
"Your Element is misconfigured": "Jūsu Element ir nokonfigurēts kļūdaini"
|
||||
"Your Element is misconfigured": "Jūsu Element ir nokonfigurēts kļūdaini",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Gedecentraliseerd en versleuteld chatten & samenwerken dankzij [matrix]",
|
||||
"Sign In": "Aanmelden",
|
||||
"Create Account": "Account aanmaken",
|
||||
"Explore rooms": "Kamers verkennen",
|
||||
"Explore rooms": "Gesprekken ontdekken",
|
||||
"Unexpected error preparing the app. See console for details.": "Er is een onverwachte fout opgetreden bij het voorbereiden van de app. Zie de console voor details.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuratiefout: kan slechts één van default_server_config, default_server_name, of default_hs_url opgeven.",
|
||||
"Invalid configuration: no default server specified.": "Configuratie ongeldig: geen standaardserver opgegeven.",
|
||||
@@ -26,7 +26,7 @@
|
||||
"I understand the risks and wish to continue": "Ik begrijp de risico's en wil verder gaan",
|
||||
"Go to element.io": "Ga naar element.io",
|
||||
"Failed to start": "Opstarten mislukt",
|
||||
"Open": "Open",
|
||||
"Open": "Openen",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Uw Element configuratie bevat ongeldige JSON. Gelieve het probleem te corrigeren daarna de pagina te herladen.",
|
||||
"Download Completed": "Download voltooid",
|
||||
"Your Element is misconfigured": "Uw Element is verkeerd geconfigureerd",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"powered by Matrix": "покреће Матрикс",
|
||||
"Welcome to Element": "Добродошли у Елемент",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Децентрализовано, шифровано ћаскање и сарадња коју покреће [matrix]",
|
||||
"Sign In": "Пријава",
|
||||
"Sign In": "Пријави се",
|
||||
"Create Account": "Направи налог",
|
||||
"Explore rooms": "Истражи собе",
|
||||
"Invalid configuration: no default server specified.": "Погрешно подешавање: подразумевани сервер није наведен.",
|
||||
|
||||
@@ -23,7 +23,6 @@ import React from 'react';
|
||||
// this incidentally means we can forget our React imports in JSX files without penalty.
|
||||
window.React = React;
|
||||
|
||||
import url from 'url';
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import {_td, newTranslatableError} from 'matrix-react-sdk/src/languageHandler';
|
||||
@@ -120,11 +119,12 @@ function onTokenLoginCompleted() {
|
||||
// if we did a token login, we're now left with the token, hs and is
|
||||
// url as query params in the url; a little nasty but let's redirect to
|
||||
// clear them.
|
||||
const parsedUrl = url.parse(window.location.href);
|
||||
parsedUrl.search = "";
|
||||
const formatted = url.format(parsedUrl);
|
||||
console.log(`Redirecting to ${formatted} to drop loginToken from queryparams`);
|
||||
window.history.replaceState(null, "", formatted);
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
url.searchParams.delete("loginToken");
|
||||
|
||||
console.log(`Redirecting to ${url.href} to drop loginToken from queryparams`);
|
||||
window.history.replaceState(null, "", url.href);
|
||||
}
|
||||
|
||||
export async function loadApp(fragParams: {}) {
|
||||
|
||||
@@ -28,16 +28,7 @@ require('katex/dist/katex.css');
|
||||
// These are things that can run before the skin loads - be careful not to reference the react-sdk though.
|
||||
import {parseQsFromFragment} from "./url_utils";
|
||||
import './modernizr';
|
||||
|
||||
async function settled(...promises: Array<Promise<any>>) {
|
||||
for (const prom of promises) {
|
||||
try {
|
||||
await prom;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
import {settled} from "./promise_utils";
|
||||
|
||||
function checkBrowserFeatures() {
|
||||
if (!window.Modernizr) {
|
||||
@@ -45,14 +36,20 @@ function checkBrowserFeatures() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// custom checks atop Modernizr because it doesn't have ES2018/ES2019 checks in it for some features we depend on,
|
||||
// Modernizr requires rules to be lowercase with no punctuation:
|
||||
// ES2018: http://www.ecma-international.org/ecma-262/9.0/#sec-promise.prototype.finally
|
||||
// Custom checks atop Modernizr because it doesn't have ES2018/ES2019 checks
|
||||
// in it for some features we depend on.
|
||||
// Modernizr requires rules to be lowercase with no punctuation.
|
||||
// ES2018: http://262.ecma-international.org/9.0/#sec-promise.prototype.finally
|
||||
window.Modernizr.addTest("promiseprototypefinally", () =>
|
||||
window.Promise && window.Promise.prototype && typeof window.Promise.prototype.finally === "function");
|
||||
// ES2019: http://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries
|
||||
typeof window.Promise?.prototype?.finally === "function");
|
||||
// ES2018: https://262.ecma-international.org/9.0/#sec-get-regexp.prototype.dotAll
|
||||
window.Modernizr.addTest("regexpdotall", () => (
|
||||
window.RegExp?.prototype &&
|
||||
!!Object.getOwnPropertyDescriptor(window.RegExp.prototype, "dotAll")?.get
|
||||
));
|
||||
// ES2019: http://262.ecma-international.org/10.0/#sec-object.fromentries
|
||||
window.Modernizr.addTest("objectfromentries", () =>
|
||||
window.Object && typeof window.Object.fromEntries === "function");
|
||||
typeof window.Object?.fromEntries === "function");
|
||||
|
||||
const featureList = Object.keys(window.Modernizr);
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import {hideToast as hideUpdateToast, showToast as showUpdateToast} from "matrix
|
||||
import {Action} from "matrix-react-sdk/src/dispatcher/actions";
|
||||
import { CheckUpdatesPayload } from 'matrix-react-sdk/src/dispatcher/payloads/CheckUpdatesPayload';
|
||||
|
||||
import url from 'url';
|
||||
import UAParser from 'ua-parser-js';
|
||||
|
||||
const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
|
||||
@@ -184,17 +183,13 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||
|
||||
getDefaultDeviceDisplayName(): string {
|
||||
// strip query-string and fragment from uri
|
||||
const u = url.parse(window.location.href);
|
||||
u.protocol = "";
|
||||
u.search = "";
|
||||
u.hash = "";
|
||||
// Remove trailing slash if present
|
||||
u.pathname = u.pathname.replace(/\/$/, "");
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
let appName = u.format();
|
||||
// Remove leading slashes if present
|
||||
appName = appName.replace(/^\/\//, "");
|
||||
// `appName` is now in the format `develop.element.io`.
|
||||
// `appName` in the format `develop.element.io/abc/xyz`
|
||||
const appName = [
|
||||
url.host,
|
||||
url.pathname.replace(/\/$/, ""), // Remove trailing slash if present
|
||||
].join("");
|
||||
|
||||
const ua = new UAParser();
|
||||
const browserName = ua.getBrowser().name || "unknown browser";
|
||||
|
||||
25
src/vector/promise_utils.ts
Normal file
25
src/vector/promise_utils.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2021 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
export async function settled(...promises: Array<Promise<any>>) {
|
||||
for (const prom of promises) {
|
||||
try {
|
||||
await prom;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/vector/thin_widget/app.tsx
Normal file
45
src/vector/thin_widget/app.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2021 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import AppTile from "matrix-react-sdk/src/components/views/elements/AppTile";
|
||||
import { IWidget } from "matrix-widget-api";
|
||||
import MatrixClientContext from "matrix-react-sdk/src/contexts/MatrixClientContext";
|
||||
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
|
||||
|
||||
// add React and ReactPerf to the global namespace, to make them easier to access via the console
|
||||
// this incidentally means we can forget our React imports in JSX files without penalty.
|
||||
window.React = React;
|
||||
|
||||
export interface IStartOpts {
|
||||
widgetId: string;
|
||||
roomId?: string;
|
||||
}
|
||||
|
||||
export async function loadApp(widget: IWidget) {
|
||||
return (
|
||||
<MatrixClientContext.Provider value={MatrixClientPeg.get()}>
|
||||
<div id="mx_ThinWrapper_container">
|
||||
<AppTile
|
||||
app={widget}
|
||||
fullWidth={true}
|
||||
userId={MatrixClientPeg.get().getUserId()}
|
||||
userWidget={false}
|
||||
/>
|
||||
</div>
|
||||
</MatrixClientContext.Provider>
|
||||
);
|
||||
}
|
||||
12
src/vector/thin_widget/index.html
Normal file
12
src/vector/thin_widget/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Thin Widget</title>
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Sorry, this requires JavaScript to be enabled.</noscript> <!-- TODO: Translate this? -->
|
||||
<section id="matrixchat" style="height: 100%; overflow: auto;" class="notranslate"></section>
|
||||
</body>
|
||||
</html>
|
||||
58
src/vector/thin_widget/index.scss
Normal file
58
src/vector/thin_widget/index.scss
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2021 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO: Match the user's theme: https://github.com/vector-im/element-web/issues/12794
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nunito';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('~matrix-react-sdk/res/fonts/Nunito/Nunito-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
$dark-fg: #edf3ff;
|
||||
$dark-bg: #363c43;
|
||||
$light-fg: #2e2f32;
|
||||
$light-bg: #fff;
|
||||
body {
|
||||
font-family: Nunito, Arial, Helvetica, sans-serif;
|
||||
background-color: $dark-bg;
|
||||
color: $dark-fg;
|
||||
}
|
||||
|
||||
body.theme-light {
|
||||
background-color: $light-bg;
|
||||
color: $light-fg;
|
||||
}
|
||||
|
||||
body, html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mx_ThinWrapper_container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
|
||||
.mx_AppTileFullWidth {
|
||||
width: unset !important;
|
||||
height: calc(100% - 10px); // 5px top + bottom borders on the AppTile
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
105
src/vector/thin_widget/index.ts
Normal file
105
src/vector/thin_widget/index.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright 2021 New Vector Ltd.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// We have to trick webpack into loading our CSS for us.
|
||||
require("./index.scss");
|
||||
import * as qs from 'querystring';
|
||||
import { settled } from "../promise_utils";
|
||||
import ReactDOM from 'react-dom';
|
||||
import { StopGapWidgetDriver, WidgetRenderMode } from "matrix-react-sdk/src/stores/widgets/StopGapWidgetDriver";
|
||||
import WidgetUtils from "matrix-react-sdk/src/utils/WidgetUtils";
|
||||
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
|
||||
|
||||
// The widget's options are encoded into the fragment to avoid leaking info to the server. The widget
|
||||
// spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
|
||||
const widgetQuery = qs.parse(window.location.hash.substring(2));
|
||||
const qsParam = (name: string, optional = false): string => {
|
||||
if (!optional && (!widgetQuery[name] || typeof (widgetQuery[name]) !== 'string')) {
|
||||
throw new Error(`Expected singular ${name} in query string`);
|
||||
}
|
||||
return widgetQuery[name] as string;
|
||||
};
|
||||
|
||||
const accessToken = qsParam("accessToken");
|
||||
const homeserverUrl = qsParam("hsUrl");
|
||||
const roomId = qsParam("roomId", true);
|
||||
const widgetId = qsParam("widgetId"); // state_key or account data key
|
||||
|
||||
// TODO: clear href so people don't accidentally copy/paste it
|
||||
//window.location.hash = '';
|
||||
|
||||
(async function() {
|
||||
const {
|
||||
rageshakePromise,
|
||||
preparePlatform,
|
||||
loadSkin,
|
||||
loadOlm, // to handle timelines
|
||||
loadLanguage,
|
||||
loadTheme,
|
||||
showError,
|
||||
_t,
|
||||
} = await import(
|
||||
/* webpackChunkName: "thin-wrapper-init" */
|
||||
/* webpackPreload: true */
|
||||
"../init");
|
||||
|
||||
try {
|
||||
// give rageshake a chance to load/fail, we don't actually assert rageshake loads, we allow it to fail if no IDB
|
||||
console.log("Waiting for rageshake...");
|
||||
await settled(rageshakePromise);
|
||||
|
||||
console.log("Running startup...");
|
||||
StopGapWidgetDriver.RENDER_MODE = WidgetRenderMode.ThinWrapper;
|
||||
await loadSkin();
|
||||
await loadOlm();
|
||||
preparePlatform();
|
||||
await MatrixClientPeg.shim(homeserverUrl, accessToken);
|
||||
await loadTheme();
|
||||
await loadLanguage();
|
||||
|
||||
console.log("Locating widget...");
|
||||
const stateEvent = await MatrixClientPeg.get()._http.authedRequest(
|
||||
undefined, "GET",
|
||||
`/rooms/${encodeURIComponent(roomId)}/state/im.vector.modular.widgets/${encodeURIComponent(widgetId)}`,
|
||||
undefined, undefined, {},
|
||||
);
|
||||
if (!stateEvent?.url) {
|
||||
throw new Error("Invalid widget");
|
||||
}
|
||||
const app = WidgetUtils.makeAppConfig(
|
||||
widgetId,
|
||||
stateEvent,
|
||||
MatrixClientPeg.get().getUserId(), // assume we are the sender
|
||||
roomId,
|
||||
widgetId);
|
||||
|
||||
// Now we can start our custom code
|
||||
console.log("Loading app...");
|
||||
const module = await import(
|
||||
/* webpackChunkName: "thin-wrapper-app" */
|
||||
/* webpackPreload: true */
|
||||
"./app");
|
||||
window.matrixChat = ReactDOM.render(await module.loadApp(app),
|
||||
document.getElementById('matrixchat'));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
// Like the compatibility page, AWOOOOOGA at the user
|
||||
// This uses the default brand since the app config is unavailable.
|
||||
await showError(_t("Your Element is misconfigured"), [
|
||||
err.translatedMessage || _t("Unexpected error preparing the app. See console for details."),
|
||||
]);
|
||||
}
|
||||
})();
|
||||
@@ -31,6 +31,15 @@ module.exports = (env, argv) => {
|
||||
const reactSdkSrcDir = path.resolve(require.resolve("matrix-react-sdk/package.json"), '..', 'src');
|
||||
const jsSdkSrcDir = path.resolve(require.resolve("matrix-js-sdk/package.json"), '..', 'src');
|
||||
|
||||
const themeBundles = {
|
||||
"theme-legacy": "./node_modules/matrix-react-sdk/res/themes/legacy-light/css/legacy-light.scss",
|
||||
"theme-legacy-dark": "./node_modules/matrix-react-sdk/res/themes/legacy-dark/css/legacy-dark.scss",
|
||||
"theme-light": "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
|
||||
"theme-dark": "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
|
||||
"theme-light-custom": "./node_modules/matrix-react-sdk/res/themes/light-custom/css/light-custom.scss",
|
||||
"theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss",
|
||||
};
|
||||
|
||||
return {
|
||||
...development,
|
||||
|
||||
@@ -40,14 +49,10 @@ module.exports = (env, argv) => {
|
||||
"mobileguide": "./src/vector/mobile_guide/index.js",
|
||||
"jitsi": "./src/vector/jitsi/index.ts",
|
||||
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
|
||||
"thinwidget": "./src/vector/thin_widget/index.ts",
|
||||
|
||||
// CSS themes
|
||||
"theme-legacy": "./node_modules/matrix-react-sdk/res/themes/legacy-light/css/legacy-light.scss",
|
||||
"theme-legacy-dark": "./node_modules/matrix-react-sdk/res/themes/legacy-dark/css/legacy-dark.scss",
|
||||
"theme-light": "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
|
||||
"theme-dark": "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
|
||||
"theme-light-custom": "./node_modules/matrix-react-sdk/res/themes/light-custom/css/light-custom.scss",
|
||||
"theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss",
|
||||
...themeBundles,
|
||||
},
|
||||
|
||||
optimization: {
|
||||
@@ -227,6 +232,7 @@ module.exports = (env, argv) => {
|
||||
require("postcss-easings")(),
|
||||
require("postcss-strip-inline-comments")(),
|
||||
require("postcss-hexrgba")(),
|
||||
require("postcss-calc")({warnWhenCannotResolve: true}),
|
||||
|
||||
// It's important that this plugin is last otherwise we end
|
||||
// up with broken CSS.
|
||||
@@ -312,7 +318,7 @@ module.exports = (env, argv) => {
|
||||
// HtmlWebpackPlugin will screw up our formatting like the names
|
||||
// of the themes and which chunks we actually care about.
|
||||
inject: false,
|
||||
excludeChunks: ['mobileguide', 'usercontent', 'jitsi'],
|
||||
excludeChunks: ['mobileguide', 'usercontent', 'jitsi', 'thinwidget'],
|
||||
minify: argv.mode === 'production',
|
||||
vars: {
|
||||
og_image_url: og_image_url,
|
||||
@@ -327,6 +333,14 @@ module.exports = (env, argv) => {
|
||||
chunks: ['jitsi'],
|
||||
}),
|
||||
|
||||
// This is a small thin wrapper for widgets (popout; isolated stack)
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/thin_widget/index.html',
|
||||
filename: 'thin_widget.html',
|
||||
minify: argv.mode === 'production',
|
||||
chunks: ['thinwidget', ...Object.keys(themeBundles)],
|
||||
}),
|
||||
|
||||
// This is the mobile guide's entry point (separate for faster mobile loading)
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/mobile_guide/index.html',
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -7511,10 +7511,9 @@ mathml-tag-names@^2.1.3:
|
||||
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
|
||||
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
||||
|
||||
matrix-js-sdk@9.6.0:
|
||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-9.6.0.tgz#e3aee2f2a2c395aaa8a90a19023addee7af02099"
|
||||
integrity sha512-zoNqB7z0C0QDncN7yD1K50c4C88VPofWaCQ0gNXqO/Ac1dr/xLF/46iNF9Y+dBwq7siBO9wEh20WFHMaRpeLOg==
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/6ad3fb16b3813c717943f6bc8bca5a55fe325477"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
another-json "^0.2.0"
|
||||
@@ -7534,10 +7533,9 @@ matrix-mock-request@^1.2.3:
|
||||
bluebird "^3.5.0"
|
||||
expect "^1.20.2"
|
||||
|
||||
matrix-react-sdk@3.13.1:
|
||||
"matrix-react-sdk@github:matrix-org/matrix-react-sdk#develop":
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/matrix-react-sdk/-/matrix-react-sdk-3.13.1.tgz#40256dda0d9b0e091ce01d1e48565f6aa93ad35d"
|
||||
integrity sha512-VFcZSAO6P+afjKKJylgsp9PwjBf36xjaWN3l+8WaGqyZDKyJdYOjoU4UZE3O9s/W9YTIcb5UUYyq1y0sunJjog==
|
||||
resolved "https://codeload.github.com/matrix-org/matrix-react-sdk/tar.gz/e9740f5a693861fb993bf9b85560d6c25784bca9"
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
await-lock "^2.1.0"
|
||||
@@ -7565,7 +7563,7 @@ matrix-react-sdk@3.13.1:
|
||||
katex "^0.12.0"
|
||||
linkifyjs "^2.1.9"
|
||||
lodash "^4.17.20"
|
||||
matrix-js-sdk "9.6.0"
|
||||
matrix-js-sdk "github:matrix-org/matrix-js-sdk#develop"
|
||||
matrix-widget-api "^0.1.0-beta.13"
|
||||
minimist "^1.2.5"
|
||||
pako "^2.0.3"
|
||||
@@ -8892,7 +8890,7 @@ postcss-attribute-case-insensitive@^4.0.1:
|
||||
postcss "^7.0.2"
|
||||
postcss-selector-parser "^6.0.2"
|
||||
|
||||
postcss-calc@^7.0.1:
|
||||
postcss-calc@^7.0.1, postcss-calc@^7.0.5:
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e"
|
||||
integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==
|
||||
|
||||
Reference in New Issue
Block a user