diff --git a/script/tailwind.config.js b/script/tailwind.config.js index fc8127ef6e6aa812006f05502a60a633b444c65a..1208df7327ec70326e9dc62278eec50c427b75cd 100644 --- a/script/tailwind.config.js +++ b/script/tailwind.config.js @@ -1,44 +1,46 @@ +const colors = require('tailwindcss/colors') + module.exports = { + corePlugins: { + float: false, + tableLayout: false, + sepia: false, + saturate: false, + }, + theme: { fontFamily: { display: [ - "Visby CF", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", - "Helvetica Neue", "Arial", "Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Spectral", "Constantia", "Lucida Bright", "Lucidabright", "Lucida Serif", "Lucida", "DejaVu Serif", "Bitstream Vera Serif", + "Liberation Serif", "Georgia", "serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" ], body: [ - "Open Sans", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", - "Helvetica Neue", "Arial", "Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", - "Noto Color Emoji" + "JetBrains Mono", "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", + "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji" + ], + mono: [ + "JetBrains Mono", "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", + "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji" ], }, - extend: { - typography: (theme) => ({ - DEFAULT: { - css: { - h1: { - fontFamily: theme("fontFamily.display").join(", ") - }, - h2: { - fontFamily: theme("fontFamily.display").join(", ") - }, - h3: { - fontFamily: theme("fontFamily.display").join(", ") - }, - h4: { - fontFamily: theme("fontFamily.display").join(", ") - } - } - } - }) - } + colors: { + transparent: 'transparent', + current: 'currentColor', + black: colors.black, + white: colors.white, + gray: colors.trueGray, + }, + extend: {}, }, + variants: { }, - plugins: [ - require('@tailwindcss/typography'), - ], + darkMode: false, purge: [ - "../server/templates/**/*.hbs" + "../server/templates/**/*.hbs", + "../server/templates/*.hbs" ] } \ No newline at end of file diff --git a/server/favicon.ico b/server/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..93bce503927b4aa4c3206261759da0b1dbb8f15f Binary files /dev/null and b/server/favicon.ico differ diff --git a/server/migrations/20210920192001_add_interests_to_signups.sql b/server/migrations/20210920192001_add_interests_to_signups.sql new file mode 100644 index 0000000000000000000000000000000000000000..2457abfc757a3d3c6171d9639e2c280981689ead --- /dev/null +++ b/server/migrations/20210920192001_add_interests_to_signups.sql @@ -0,0 +1,4 @@ +ALTER TABLE "signups" + ADD "wants_releases" BOOLEAN, + ADD "wants_updates" BOOLEAN, + ADD "wants_community" BOOLEAN; \ No newline at end of file diff --git a/server/src/community.rs b/server/src/community.rs new file mode 100644 index 0000000000000000000000000000000000000000..306cd30de53bc2803fdc7fc63ac3494a8d972de3 --- /dev/null +++ b/server/src/community.rs @@ -0,0 +1,15 @@ +use crate::{AppState, Request, RequestExt}; +use std::sync::Arc; +use tide::http::mime; + +pub fn add_routes(community: &mut tide::Server>) { + community.at("/community").get(get_community); +} + +async fn get_community(mut request: Request) -> tide::Result { + let data = request.layout_data().await?; + Ok(tide::Response::builder(200) + .body(request.state().render_template("community.hbs", &data)?) + .content_type(mime::HTML) + .build()) +} diff --git a/server/src/db.rs b/server/src/db.rs index bd9fca85e744503ba66fc79ff8c3a350323b0e61..ebc861be03d5ddaaa6a85165812a60a9f4494ac5 100644 --- a/server/src/db.rs +++ b/server/src/db.rs @@ -47,17 +47,30 @@ impl Db { github_login: &str, email_address: &str, about: &str, + wants_releases: bool, + wants_updates: bool, + wants_community: bool, ) -> Result { test_support!(self, { let query = " - INSERT INTO signups (github_login, email_address, about) - VALUES ($1, $2, $3) + INSERT INTO signups ( + github_login, + email_address, + about, + wants_releases, + wants_updates, + wants_community + ) + VALUES ($1, $2, $3, $4, $5, $6) RETURNING id "; sqlx::query_scalar(query) .bind(github_login) .bind(email_address) .bind(about) + .bind(wants_releases) + .bind(wants_updates) + .bind(wants_community) .fetch_one(&self.pool) .await .map(SignupId) @@ -475,6 +488,9 @@ pub struct Signup { pub github_login: String, pub email_address: String, pub about: String, + pub wants_releases: Option, + pub wants_updates: Option, + pub wants_community: Option, } id_type!(ChannelId); diff --git a/server/src/home.rs b/server/src/home.rs index 25adde3a0f2fed3d7b11c107e23dcbfdf1d67bac..10336f2fb77613b6ee9b1ef4b8a73c582daa84c5 100644 --- a/server/src/home.rs +++ b/server/src/home.rs @@ -61,6 +61,12 @@ async fn post_signup(mut request: Request) -> tide::Result { github_login: String, email_address: String, about: String, + #[serde(default)] + wants_releases: bool, + #[serde(default)] + wants_updates: bool, + #[serde(default)] + wants_community: bool, } let mut form: Form = request.body_form().await?; @@ -75,7 +81,14 @@ async fn post_signup(mut request: Request) -> tide::Result { // Save signup in the database request .db() - .create_signup(&form.github_login, &form.email_address, &form.about) + .create_signup( + &form.github_login, + &form.email_address, + &form.about, + form.wants_releases, + form.wants_updates, + form.wants_community, + ) .await?; let layout_data = request.layout_data().await?; @@ -101,4 +114,4 @@ async fn get_release_asset(request: Request) -> tide::Result { .content_type(mime::BYTE_STREAM) .body(body) .build()) -} +} \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index ba54f05f1c4d33fe5947f30f4257d962b3348ba8..ac01561f2fb9c39adad84c89bc070bf0e00485a3 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -9,6 +9,8 @@ mod github; mod home; mod rpc; mod team; +mod releases; +mod community; use self::errors::TideResultExt as _; use anyhow::Result; @@ -173,6 +175,8 @@ pub async fn run_server( web.with(errors::Middleware); home::add_routes(&mut web); team::add_routes(&mut web); + releases::add_routes(&mut web); + community::add_routes(&mut web); admin::add_routes(&mut web); auth::add_routes(&mut web); assets::add_routes(&mut web); diff --git a/server/src/releases.rs b/server/src/releases.rs new file mode 100644 index 0000000000000000000000000000000000000000..f1f341057780c4e8f58e0072296323d77a9dd65d --- /dev/null +++ b/server/src/releases.rs @@ -0,0 +1,55 @@ +use crate::{ + auth::RequestExt as _, github::Release, AppState, LayoutData, Request, RequestExt as _, +}; +use comrak::ComrakOptions; +use serde::{Serialize}; +use std::sync::Arc; +use tide::{http::mime}; + +pub fn add_routes(releases: &mut tide::Server>) { + releases.at("/releases").get(get_releases); +} + +async fn get_releases(mut request: Request) -> tide::Result { + + #[derive(Serialize)] + struct ReleasesData { + #[serde(flatten)] + layout: Arc, + releases: Option>, + } + + let mut data = ReleasesData { + layout: request.layout_data().await?, + releases: None, + }; + + if let Some(user) = request.current_user().await? { + if user.is_insider { + data.releases = Some( + request + .state() + .repo_client + .releases() + .await? + .into_iter() + .filter_map(|mut release| { + if release.draft { + None + } else { + let mut options = ComrakOptions::default(); + options.render.unsafe_ = true; // Allow raw HTML in the markup. We control these release notes anyway. + release.body = comrak::markdown_to_html(&release.body, &options); + Some(release) + } + }) + .collect(), + ); + } + } + + Ok(tide::Response::builder(200) + .body(request.state().render_template("releases.hbs", &data)?) + .content_type(mime::HTML) + .build()) +} \ No newline at end of file diff --git a/server/static/browserconfig.xml b/server/static/browserconfig.xml new file mode 100644 index 0000000000000000000000000000000000000000..15a8331058027d2be873412a680d5047094a5546 --- /dev/null +++ b/server/static/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #000000 + + + diff --git a/server/static/images/android-chrome-192x192.png b/server/static/images/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..2342d82c0b663bf671cf1426c6b57e4f826542a9 Binary files /dev/null and b/server/static/images/android-chrome-192x192.png differ diff --git a/server/static/images/android-chrome-512x512.png b/server/static/images/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..d25b64f77a0701dd1316ec7f26b807c7d6e1893c Binary files /dev/null and b/server/static/images/android-chrome-512x512.png differ diff --git a/server/static/images/apple-touch-icon.png b/server/static/images/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ba99f40f188d557e37ca9cbfbc8f0af1d18d91 Binary files /dev/null and b/server/static/images/apple-touch-icon.png differ diff --git a/server/static/images/favicon-16x16.png b/server/static/images/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..486c293a8248f03d74d09da2613bf90faba287bd Binary files /dev/null and b/server/static/images/favicon-16x16.png differ diff --git a/server/static/images/favicon-32x32.png b/server/static/images/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..a34711800bd9138a465b76ebb91ad379baacac8e Binary files /dev/null and b/server/static/images/favicon-32x32.png differ diff --git a/server/static/images/favicon.png b/server/static/images/favicon.png index 074140e0627270a23e1b8574d9ab8f178f759ab6..821698c28fe0047d22f09b94e1634ef00819d71f 100644 Binary files a/server/static/images/favicon.png and b/server/static/images/favicon.png differ diff --git a/server/static/images/favicon.svg b/server/static/images/favicon.svg new file mode 100644 index 0000000000000000000000000000000000000000..fdd3fe4610b187a2eab5a433cb64596027793e5d --- /dev/null +++ b/server/static/images/favicon.svg @@ -0,0 +1,14 @@ + + + + + diff --git a/server/static/images/mstile-144x144.png b/server/static/images/mstile-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..e70abaf8d20288ed4ea4966c7f19334657eae981 Binary files /dev/null and b/server/static/images/mstile-144x144.png differ diff --git a/server/static/images/mstile-150x150.png b/server/static/images/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..545758300a14795d8875a43c907d2a994f3aaf4c Binary files /dev/null and b/server/static/images/mstile-150x150.png differ diff --git a/server/static/images/mstile-310x150.png b/server/static/images/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..73072f380d4b1c67bd55de6075dbfaa7ceb2ebf7 Binary files /dev/null and b/server/static/images/mstile-310x150.png differ diff --git a/server/static/images/mstile-310x310.png b/server/static/images/mstile-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..2f8fc1c3a178d84a5b51c2871952a113db6f409b Binary files /dev/null and b/server/static/images/mstile-310x310.png differ diff --git a/server/static/images/mstile-70x70.png b/server/static/images/mstile-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..c28ce9405c389400128457723df93f892e3ab821 Binary files /dev/null and b/server/static/images/mstile-70x70.png differ diff --git a/server/static/images/safari-pinned-tab.svg b/server/static/images/safari-pinned-tab.svg new file mode 100644 index 0000000000000000000000000000000000000000..981cf3f1cb55f01d41197ae4743b3e4b9ac4ad03 --- /dev/null +++ b/server/static/images/safari-pinned-tab.svg @@ -0,0 +1,19 @@ + + + + + + + diff --git a/server/static/images/zed-og-image.png b/server/static/images/zed-og-image.png new file mode 100644 index 0000000000000000000000000000000000000000..9410e705d8b9a2070f07e7dacc6898f3b5c26ce7 Binary files /dev/null and b/server/static/images/zed-og-image.png differ diff --git a/server/static/images/zed-twitter-image.png b/server/static/images/zed-twitter-image.png new file mode 100644 index 0000000000000000000000000000000000000000..607d9bf9c6e9e6c9a8e81596c6e92a7e76a04ac0 Binary files /dev/null and b/server/static/images/zed-twitter-image.png differ diff --git a/server/static/prism.js b/server/static/prism.js new file mode 100644 index 0000000000000000000000000000000000000000..b08aaf6c6a83165b7aef089d353a7a1c4ce68cbc --- /dev/null +++ b/server/static/prism.js @@ -0,0 +1,12 @@ +/* PrismJS 1.25.0 +https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+bash+c+cpp+rust+scss */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,e={},M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);y+=m.value.length,m=m.next){var b=m.value;if(t.length>n.length)return;if(!(b instanceof W)){var k,x=1;if(h){if(!(k=z(v,y,n,f)))break;var w=k.index,A=k.index+k[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var E=m;E!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=I(t,j,O),y+=O.length),q(t,j,x);var C=new W(o,g?M.tokenize(S,g):S,d,S);if(m=I(t,j,C),L&&I(t,m,L),1l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function z(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){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 I(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 q(e,n,t){for(var r=n.next,a=0;a"+a.content+""},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var t=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(t&&(M.filename=t.src,t.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var a=document.readyState;"loading"===a||"interactive"===a&&t&&t.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_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"},/"|'/]}},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:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\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|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\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])*(?=\.(?:prototype|constructor))/,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:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[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]+/}}}),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",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,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}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};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+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|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|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|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|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|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|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|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;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\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}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],i=a.variable[1].inside,o=0;o>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),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],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}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_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|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(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\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){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,function(){return a});a=a.replace(//g,function(){return"[^\\s\\S]"}),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0,alias:"string"},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|Self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:[ui](?:8|16|32|64|128|size)|f(?:32|64)|bool|char|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64|size)?|f32|f64))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|forward|for|each|while|import|use|extend|debug|warn|mixin|include|function|return|content)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),Prism.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|with|show|hide)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss; diff --git a/server/static/prose.css b/server/static/prose.css new file mode 100644 index 0000000000000000000000000000000000000000..03bffb119684ed68b2f3c91f47b8cc5d2a84172f --- /dev/null +++ b/server/static/prose.css @@ -0,0 +1,253 @@ +article.prose { + margin-bottom: 2.5rem; +} + +article.prose, +.type-prose { + font-family: "Spectral", "Constantia", "Lucida Bright", "Lucidabright", "Lucida Serif", "Lucida", "DejaVu Serif", "Bitstream Vera Serif", "Liberation Serif", "Georgia", "serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", serif; + letter-spacing: -0.05rem; +} + +article.prose h1, +article.prose h2, +article.prose h3, +article.prose h4, +.type-prose h1, +.type-prose h2, +.type-prose h3, +.type-prose h4 { + margin: 3rem 0 1rem 0; +} + +article.prose h1, +.type-prose h1 { + font-size: 2.25rem; + line-height: 2.5rem; +} + +article.prose h2, +.type-prose h2 { + font-size: 1.875rem; + line-height: 2.25rem; +} + +article.prose h3, +.type-prose h3 { + font-size: 1.6rem; + line-height: 2rem; +} + +article.prose h4, +.type-prose h4 { + font-size: 1.4rem; + line-height: 1.75rem; +} + +article.prose p, +article.prose li, +article.prose a, +.type-prose p, +.type-prose li, +.type-prose a { + color: #eee; + font-size: 1.3rem; + line-height: 2.1rem; +} + +article.prose a:not(img), +.type-prose a:not(img) { + text-decoration: underline; + text-underline-offset: 4px; +} + +article.prose strong, +.type-prose strong { + font-weight: 600; +} + +article.prose i, +.type-prose i { + font-style: italic; +} + +article.prose p:not(:last-of-type), +.type-prose p:not(:last-of-type) { + margin-bottom: 1.5rem; +} + +article.prose img, +article.prose pre, +.type-prose img, +.type-prose pre { + margin: 1.5rem 0; +} + +article.prose ul, +.type-prose ul { + margin-left: 1.5rem; +} + +article.prose ul li, +.type-prose ul li { + list-style-type: disc; + list-style-position: outside; +} + +article.prose ul li:not(:last-of-type), +.type-prose ul li:not(:last-of-type) { + margin-bottom: 0.2rem; +} + +article.prose code, +.type-prose code { + font-family: "JetBrains Mono", "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", monospace; + font-size: 0.96rem; + letter-spacing: 0rem; +} + +article.prose :not(pre) > code, +.type-prose :not(pre) > code { + padding: 0.2rem 0.4rem; +} + +article.prose pre, +.type-prose pre { + padding: 0.8rem; +} + +article.prose pre, +article.prose :not(pre) > code, +.type-prose pre, +.type-prose :not(pre) > code { + border-radius: 4px; + background-color: rgba(255, 255, 255, 0.1); +} + +/* Code Highlighting Styles +/* Based on PrismJS 1.25.0 +https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+bash+c+cpp+rust+scss */ +code[class*="language-"], +pre[class*="language-"] { + color: #ddd; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Code blocks */ +pre[class*="language-"]::-moz-selection { + /* Firefox */ + background: #3b57bc33; +} + +pre[class*="language-"]::selection { + /* Safari */ + background: #3b57bc33; +} + +/* Text Selection colour */ +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #3b57bc33; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #3b57bc33; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #9cdcfe; +} + +.token.punctuation { + opacity: 0.7; +} + +.token.namespace { + opacity: 0.7; +} + +.token.tag, +.token.boolean, +.token.number, +.token.deleted { + color: #b5cea8; +} + +.token.keyword, +.token.property, +.token.selector, +.token.constant, +.token.symbol, +.token.builtin { + color: #0086c0; + /* #F9EE98 */ +} + +.token.attr-name, +.token.attr-value, +.token.string, +.token.char, +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string, +.token.variable, +.token.inserted { + color: #4e94ce; +} + +.token.atrule { + color: #4ec9b0; +} + +.token.regex, +.token.important { + color: #dcdcaa; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +/* Markup */ +.language-markup .token.tag, +.language-markup .token.attr-name, +.language-markup .token.punctuation { + color: #4e94ce; +} + +/* Make the tokens sit above the line highlight so the colours don't look faded. */ +.token { + position: relative; + z-index: 1; +} +/*# sourceMappingURL=prose.css.map */ \ No newline at end of file diff --git a/server/static/prose.css.map b/server/static/prose.css.map new file mode 100644 index 0000000000000000000000000000000000000000..0125373da822a173ec933781ade6d6a3a9d00876 --- /dev/null +++ b/server/static/prose.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "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", + "sources": [ + "prose.scss" + ], + "names": [], + "file": "prose.css" +} \ No newline at end of file diff --git a/server/static/prose.scss b/server/static/prose.scss new file mode 100644 index 0000000000000000000000000000000000000000..e034fdd7a2218154472832248346aca7cca7a865 --- /dev/null +++ b/server/static/prose.scss @@ -0,0 +1,260 @@ +// Style prose by hand +// add .prose to any
to activate prose styles +// or .type-prose to any element + +article.prose { + margin-bottom: 2.5rem; +} + +article.prose, +.type-prose { + font-family: "Spectral", "Constantia", "Lucida Bright", "Lucidabright", + "Lucida Serif", "Lucida", "DejaVu Serif", "Bitstream Vera Serif", + "Liberation Serif", "Georgia", "serif", "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", serif; + letter-spacing: -0.05rem; + + h1, + h2, + h3, + h4 { + margin: 3rem 0 1rem 0; + } + + h1 { + font-size: 2.25rem; + line-height: 2.5rem; + } + + h2 { + font-size: 1.875rem; + line-height: 2.25rem; + } + + h3 { + font-size: 1.6rem; + line-height: 2rem; + } + + h4 { + font-size: 1.4rem; + line-height: 1.75rem; + } + + p, + li, + a { + color: #eee; + font-size: 1.3rem; + line-height: 2.1rem; + } + + a:not(img) { + text-decoration: underline; + text-underline-offset: 4px; + } + + strong { + font-weight: 600; + } + + i { + font-style: italic; + } + + p:not(:last-of-type) { + margin-bottom: 1.5rem; + } + + img, + pre { + margin: 1.5rem 0; + } + + ul { + margin-left: 1.5rem; + } + + ul li { + list-style-type: disc; + list-style-position: outside; + &:not(:last-of-type) { + margin-bottom: 0.2rem; + } + } + + code { + font-family: "JetBrains Mono", "Andale Mono WT", "Andale Mono", + "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", + "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", + "Courier New", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Noto Color Emoji", monospace; + font-size: 0.96rem; + letter-spacing: 0rem; + } + + :not(pre) > code { + padding: 0.2rem 0.4rem; + } + + pre { + padding: 0.8rem; + } + + pre, + :not(pre) > code { + border-radius: 4px; + background-color: rgba(255, 255, 255, 0.1); + } +} + +/* Code Highlighting Styles +/* Based on PrismJS 1.25.0 +https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+bash+c+cpp+rust+scss */ + +code[class*="language-"], +pre[class*="language-"] { + color: #ddd; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Code blocks */ +pre[class*="language-"] { + // Language specific code block styles +} + +pre[class*="language-"]::-moz-selection { + /* Firefox */ + background: #3b57bc33; +} + +pre[class*="language-"]::selection { + /* Safari */ + background: #3b57bc33; +} + +/* Text Selection colour */ +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #3b57bc33; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #3b57bc33; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #9cdcfe; +} + +.token.punctuation { + opacity: 0.7; +} + +.token.namespace { + opacity: 0.7; +} + +.token.tag, +.token.boolean, +.token.number, +.token.deleted { + color: #b5cea8; +} + +.token.keyword, +.token.property, +.token.selector, +.token.constant, +.token.symbol, +.token.builtin { + color: #0086c0; /* #F9EE98 */ +} + +.token.attr-name, +.token.attr-value, +.token.string, +.token.char, +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string, +.token.variable, +.token.inserted { + color: #4e94ce; +} + +.token.atrule { + color: #4ec9b0; +} + +.token.regex, +.token.important { + color: #dcdcaa; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +/* Markup */ +.language-markup .token.tag, +.language-markup .token.attr-name, +.language-markup .token.punctuation { + color: #4e94ce; +} + +/* Make the tokens sit above the line highlight so the colours don't look faded. */ +.token { + position: relative; + z-index: 1; +} + +// TODO: Style line highlights + +// .line-highlight.line-highlight { +// background: hsla(0, 0%, 33%, 0.25); /* #545454 */ +// background: linear-gradient(to right, hsla(0, 0%, 33%, .1) 70%, hsla(0, 0%, 33%, 0)); /* #545454 */ +// border-bottom: 1px dashed hsl(0, 0%, 33%); /* #545454 */ +// border-top: 1px dashed hsl(0, 0%, 33%); /* #545454 */ +// margin-top: 0.75em; /* Same as .prism’s padding-top */ +// z-index: 0; +// } + +// .line-highlight.line-highlight:before, +// .line-highlight.line-highlight[data-end]:after { +// background-color: hsl(215, 15%, 59%); /* #8794A6 */ +// color: hsl(24, 20%, 95%); /* #F5F2F0 */ +// } diff --git a/server/static/site.webmanifest b/server/static/site.webmanifest new file mode 100644 index 0000000000000000000000000000000000000000..f69ceec6eb1e85d5d9916fbae8c37544636c09e2 --- /dev/null +++ b/server/static/site.webmanifest @@ -0,0 +1,18 @@ +{ + "name": "Zed – a lightning fast, collaborative code editor written natively in Rust", + "short_name": "Zed", + "icons": [ + { + "src": "/static/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/static/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#000", + "background_color": "#000" +} diff --git a/server/styles.css b/server/styles.css index ab10493e32ab146ccec53f5a29c179785288c32a..33af3f1033a21ad7732fe6eda08b4c7fa8a764b8 100644 --- a/server/styles.css +++ b/server/styles.css @@ -1,108 +1,136 @@ /* This file is compiled to /assets/styles/tailwind.css via script/tailwind */ -@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap'); - -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Thin.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Thin.woff') format('woff'); - font-weight: 100; - font-style: normal; -} +@import url("https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,200;0,300;1,200;1,300&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100;0,300;0,600;1,100;1,300;1,600&display=swap"); +@tailwind base; +@tailwind components; +@tailwind utilities; -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Light.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Light.woff') format('woff'); - font-weight: 300; - font-style: normal; -} - -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Regular.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Regular.woff') format('woff'); - font-weight: 400; - font-style: normal; -} +@layer base { + html { + font-size: 110%; + text-rendering: geometricPrecision; + } -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Medium.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Medium.woff') format('woff'); - font-weight: 500; - font-style: normal; -} + @media screen and (min-width: 1024px) { + html { + font-size: 125%; + } + } -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-DemiBold.woff2') format('woff2'), - url('/static/fonts/VisbyCF-DemiBold.woff') format('woff'); - font-weight: 600; - font-style: normal; -} + h1 { + @apply text-4xl; + @apply tracking-tighter; + } + h2 { + @apply text-3xl; + @apply tracking-tighter; + } + h3 { + @apply text-2xl; + @apply tracking-tighter; + } + h4 { + @apply text-xl; + } -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Bold.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Bold.woff') format('woff'); - font-weight: 700; - font-style: normal; -} + .underline, + .hover\:underline:hover { + text-underline-offset: 6px; + } -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-ExtraBold.woff2') format('woff2'), - url('/static/fonts/VisbyCF-ExtraBold.woff') format('woff'); - font-weight: 800; - font-style: normal; + @media screen and (min-width: 1024px) { + .text-columns-2 { + column-count: 2; + column-gap: 3rem; + } + } + .site-nav a:not(.active) .nav-active-arrow { + display: none; + } -@font-face { - font-family: 'Visby CF'; - src: - url('/static/fonts/VisbyCF-Heavy.woff2') format('woff2'), - url('/static/fonts/VisbyCF-Heavy.woff') format('woff'); - font-weight: 900; - font-style: normal; -} + .site-nav a.active .nav-active-arrow { + display: flex; + } -@tailwind base; -@tailwind components; -@tailwind utilities; + .site-mobile-nav a.active { + font-weight: bold; + } + + .text-columns-2 { + -webkit-column-break-inside: avoid; + page-break-inside: avoid; + break-inside: avoid; + } -@layer utilities { - @responsive { - .bg-dotgrid-sm { - background: - linear-gradient(90deg, theme('colors.gray.50') 38px, transparent 1%) center, - linear-gradient(theme('colors.gray.50') 38px, transparent 1%) center, - theme('colors.gray.600'); - background-size: 40px 40px; - } - - .bg-dotgrid-md { - background: - linear-gradient(90deg, theme('colors.gray.50') 58px, transparent 1%) center, - linear-gradient(theme('colors.gray.50') 58px, transparent 1%) center, - theme('colors.gray.600'); - background-size: 60px 60px; - } - - .bg-dotgrid-lg { - background: - linear-gradient(90deg, theme('colors.gray.50') 88px, transparent 1%) center, - linear-gradient(theme('colors.gray.50') 88px, transparent 1%) center, - theme('colors.gray.600'); - background-size: 90px 90px; - } + .text-columns-2 p { + break-inside: avoid; + } + + .alternate-bg:nth-of-type(even) { + background-color: rgba(255,255,255,0.06); + } + + /* div:not(.type-prose) code { + background-color: rgba(255,255,255,0.15); + padding: 0px 4px; + border-radius: 2px; + color: #eee; + } */ + + /* This fixes scrollbar jump */ + @media screen and (min-width: 960px) { + html { + margin-left: calc(100vw - 100%); + margin-right: 0; } -} \ No newline at end of file + } + + :root { + --color: white; + --disabled: #959495; + } + + .checkbox { + color: var(--color); + } + + .checkbox--disabled { + color: var(--disabled); + } + + .checkbox__control { + width: 30px; + height: 30px; + } + + .checkbox__control svg { + transform: scale(0); + transform-origin: center center; + } + + .checkbox__brackets { + left: -1px; + top: -1px; + } + + .checkbox__input input { + opacity: 0; + width: 30px; + height: 30px; + } + + .checkbox__input input:focus + .checkbox__control { + box-shadow: 0 0 0 2px #000, 0 0 0 4px #3b57bc99 + } + + .checkbox__input input:checked + .checkbox__control svg { + transform: scale(1); + } + + .checkbox__input input:disabled + .checkbox__control { + color: var(--disabled); + } +} diff --git a/server/templates/admin.hbs b/server/templates/admin.hbs index 4dbce023bb8096de291b3e4477aaf41a15f74a89..d992e92c7b566a6b19aa1d152cea25af3945ee2d 100644 --- a/server/templates/admin.hbs +++ b/server/templates/admin.hbs @@ -20,62 +20,80 @@ }); -
-
-

Users

- - - - - - - - - - - - +
+
+

Admin

+ +
+ +

Users

+ +
+
+

Github Username

+

Admin

+

+
+
+ +
+

+

+

+
+ +
+
+ +
+
+

Github Username

+

Admin

+

+
+ {{#each users}} +
+
+
+

{{github_login}}

+

+

+
+
+ {{/each}} +
- {{#each users}} -
- - - - - - - {{/each}} -
GitHub LoginAdmin
- - - - - -
- {{github_login}} - - - - -
+

Signups

-

Signups

- - {{#each signups}} - - - - - - - - - {{/each}} -
{{github_login}}{{email_address}}{{about}} - -
+
+ +
+

Email

+

Github

+

Releases

+

Updates

+

Community

+

Remove

+
+ {{#each signups}} +
+
+
+

{{email_address}}

+

{{github_login}}

+

{{#if wants_releases}}[✓]{{else}}[ ]{{/if}}

+

{{#if wants_updates}}[✓]{{else}}[ ]{{/if}}

+

{{#if wants_community}}[✓]{{else}}[ ]{{/if}}

+

+
+
+

{{about}}

+
+ {{/each}}
{{/layout}} \ No newline at end of file diff --git a/server/templates/community.hbs b/server/templates/community.hbs new file mode 100644 index 0000000000000000000000000000000000000000..dfae551cdba8ccb49d39d5cfa4ac2099e7d67c23 --- /dev/null +++ b/server/templates/community.hbs @@ -0,0 +1,107 @@ +{{#> layout }} + +
+

We’re building a community of passionate developers & advocates.

+ +

If you would like to get involved early, sign up below and we will let you know when our developer community opens!

+ +
+
    +
  • + + + + + + + + + + + + + +
    + +

    + We'll put you on the list to play with an early beta and let you know when Zed launches. +

    +
    +
  • +
  • + + + + + + + + + + + + + + +
    + +

    + We'll send you occasional updates about our progress and share what we're learning along the way. +

    +
    +
  • +
  • + + + + + + + + + + + + + + + +
    + +

    + We'll add you to the waitlist to receive early builds and ask you to help us by testing them out. +

    +
    +
  • +
+
+ + + +
+ + + + + +

+ We're not gonna spam you—You can expect an email every 1 to 3 months from us if you sign up for updates, and occasional emails about beta releases. +

+
+
+ +{{/layout}} diff --git a/server/templates/error.hbs b/server/templates/error.hbs index 6013b2de80eb80ffd9e28be522beda5a522b88bc..4d0a99d27b5dbd638f16bb9a6b9dd665ddea59af 100644 --- a/server/templates/error.hbs +++ b/server/templates/error.hbs @@ -1,7 +1,15 @@ {{#> layout }} -
-
- Sorry, we encountered a {{status}} error: {{reason}}. -
+ +
+
+

Sorry!

+

+ Looks like we encountered a {{status}} error: {{reason}} +

+

+ Try refreshing or going home. +

+
+ {{/layout}} \ No newline at end of file diff --git a/server/templates/home.hbs b/server/templates/home.hbs index 83dc7112094d03ff72a62ac287c4bbcef2bf8d51..da2fe8f97693dffa5f65e5cf24dceded12536efc 100644 --- a/server/templates/home.hbs +++ b/server/templates/home.hbs @@ -1,69 +1,104 @@ {{#> layout }} -{{#if releases}} - -
-
- {{#each releases}} -
-
-
- VERSION {{name}} -
- - DOWNLOAD - -
-
- {{{body}}} -
-
- {{/each}} -
-
-{{else}} +
+
+

Introducing Zed—A lightning-fast, collaborative code editor written in Rust.

+

+ We think there’s a better way to write code, and it starts with the following assumptions: +

-
- -
+

Mission-critical tools should be hyper-responsive.

+ +

+ When you move the cursor or type a character, you should see pixels on the next refresh of your display—every time. Even sub-perceptual pauses add up over the course of a day to create unnecessary stress. +

-
-
-

- We’re the team behind GitHub’s Atom text editor, and we’re building something new: +

+ Joyful coding starts with an editor that stays out of your way.

+ +

Real-time collaboration produces better software.

-

- Zed is a fully-native desktop code editor focused on high performance, - clean design, and seamless collaboration. +

+ Pull requests have their place, but sometimes you just want to code together. It’s more fun than code review, builds trust between colleagues, and it’s one of the best ways to distribute knowledge through a team. But it has to be easy.

+ +

+ If you want someone’s perspective on a piece of code, it should be as easy as sending a message to pull them into your working copy and start coding. +

+ +

Conversations about software should happen close to the code.

-

- We’re in early development, but we’d like to build a small community of developers who care deeply about - their tools and are willing to give us feedback. We'll be sharing alpha builds with community members and - telling our story along the way. +

+ If you want to talk about code on GitHub you have to commit and push it first, and pasting code into a chat application sucks.

-

- If you’re interested in joining us, please let us know. +

+ By treating keystrokes as the fundamental unit of change and integrating chat into the editor, we can make it easy to have a conversation about any line of code in any working copy–whether it was committed last year or just typed ten seconds ago. +

+ +

Our goal is to make you as efficient as possible.

+ +

+ If you’re living in a tool for hours every day, you want it to disappear. Every pixel must carry its weight, and the software you’re creating should always be the focus. So we constantly ask ourselves how we can maximize signal and minimize noise.

-
- -
- - - - -
+ +

+ Do we need an icon? Do we need a gradient? We all want to achieve mastery. Our goal is to find the most efficient way to accomplish each coding task and make it accessible. We will never dumb things down. +

+ +

———

+ +

Under the hood

+ +
+

Building in Rust

+

Rust offers expressivity and developer productivity rivaling languages that depend on a VM, while simultaneously offering the control required to fully utilize the underlying hardware.

+ +

Rust’s unique ownership model is a challenge at the beginning, but once you internalize it, you can write extremely efficient multi-core code without fear of invoking undefined behavior.

+ +

It also makes it straightforward to call directly into the C-based APIs of the operating system. Rust makes it possible for a small team to build a complex product quickly, and Zed wouldn’t have been possible without it.

+ +

In the past, to write software with this performant you would need to use C++. Rust, for the first time, enables us to write software at that level as a very small team.

+
+ +
+

A new GPU-powered UI framework

+

We originally planned to use Electron as a convenient means of delivering a cross-platform GUI for Zed, while building the core of the application in Rust. But at every turn, we found that web technology was the bottleneck in achieving amazing performance. Finally, we decided to take full control and simply build a GPU-powered UI framework that met our needs.

+ +

We call it GPUI.

+ +

We took a lot of inspiration from Mozilla’s Webrender project. The key insight was that modern graphics hardware can render complex 3D graphics at high frame rates, so why not use it to render relatively simple 2D user interfaces with an immediate mode architecture?

+ +

Rust’s ownership model required us to rethink much of what we learned in other UI programming paradigms, but the result is a framework that’s productive to use and remarkably easy to reason about.

+ +

It’s liberating to control every pixel, and it’s a rush to push those pixels at lightning speed.

+
+ +
+

Conflict-free replicated data types

+ +

Real-time collaborative editing presents the illusion that multiple people are editing the same buffer. In reality, each collaborator maintains their own personal replica of the buffer to which they can apply local edits immediately without network latency.

+ +

After being applied locally, edits are transmitted to collaborators over the network, whose copies may have also changed in the meantime. This means that as participants edit together, their replicas continuously diverge and reconverge. Turns out this is a tricky problem.

+ +

To solve it, we’re using conflict-free replicated data types, which have emerged in the last decade as a general framework for achieving eventual consistency in a variety of circumstances.

+ +

Making Zed’s buffers CRDTs allows for collaborative editing, but it also helps us reason about concurrent change so that we can push work into background threads and keep the UI thread responsive.

+
+ +
+

Tree-sitter

+ +

We plan to integrate with the Language Server Protocol to support advanced IDE features, but we also think it’s important for a code editor to have a rich, native understanding of syntax.

+ +

That’s why we built Tree-sitter, a fast, general, incremental parsing library that can provide Zed with syntax trees for over 50 languages. Tree-sitter already powers production functionality on GitHub, and we’ll use it to deliver syntactically-precise syntax highlighting, tree-based selection and cursor navigation, robust auto-indent support, symbolic navigation, and more.

+
+ +

———

+ +

Excited about what we are building? Sign up for updates to follow along in our development process.

+
-{{/if}} {{/layout}} \ No newline at end of file diff --git a/server/templates/partials/layout.hbs b/server/templates/partials/layout.hbs index 1e4a3561bda5f10287617c1f2a5e4c2a39c13628..3a39eeda3c3174371e9114c37e9931264157d617 100644 --- a/server/templates/partials/layout.hbs +++ b/server/templates/partials/layout.hbs @@ -1,62 +1,193 @@ - + + + + + + + + + - Zed Industries - - - + + + + + + + + + + + + + + + + + + Zed + - -
-
- - ZEDINDUSTRIES - -
- - Team + +
+ + +
+ - {{> @partial-block}} +
+ {{> @partial-block}} +
+ + + + \ No newline at end of file diff --git a/server/templates/releases.hbs b/server/templates/releases.hbs new file mode 100644 index 0000000000000000000000000000000000000000..ab02c16822805c6d314768956bbc149a2a67f8f7 --- /dev/null +++ b/server/templates/releases.hbs @@ -0,0 +1,35 @@ +{{#> layout }} + +
+ {{#if current_user}} +

Releases

+

Zed is currently only available on macOS.

+

We are frequently shipping new versions, check back regularly to get the most recent version.

+ + {{#if releases}} + + {{#each releases}} + + {{/each}} + {{/if}} + + {{else}} + +

Hold it!

+

You can't access this without logging in.

+

Try joining our community to get access to updates & releases.

+ {{/if}} +
+ +{{/layout}} diff --git a/server/templates/signup.hbs b/server/templates/signup.hbs index 738cf2e6e6b485f9194b87ca34af17fbdd453424..5a032f457b2519cf0f85faa1cf76b39fd7fdbc74 100644 --- a/server/templates/signup.hbs +++ b/server/templates/signup.hbs @@ -1,19 +1,18 @@ {{#> layout }} -
-
-
- THANKS -
-
-

- Thanks a ton for your interest! We'll add you to our list and let you know when we have something ready - for you to try out. -

-

- Back to / -

-
-
+
+

Thanks for signing up!

+

+ We'll add you to our list and let you know when we have something ready for you to try out. +

+ +

+ Thanks for your interest! +

+ + + Back to Home +
-{{/layout}} \ No newline at end of file + +{{/layout}} diff --git a/server/templates/team.hbs b/server/templates/team.hbs index e02f284c0c3980e9bf9be79c1f5214019831857c..82ac66ade3fb98d8db2d6cc991f41b28fb6825e7 100644 --- a/server/templates/team.hbs +++ b/server/templates/team.hbs @@ -1,62 +1,160 @@ {{#> layout }} -
-
-
- -
- - NATHAN SOBO - -
- Nathan joined GitHub in late 2011 to build the Atom text editor, and - he led the Atom team until 2018. He also co-led development of Teletype for Atom, pioneering one of the first production - uses of conflict-free replicated data types for collaborative text editing. He's been dreaming about - building the world’s best text editor since he graduated from college, and is excited to finally - have - the knowledge, tools, and resources to achieve this vision. +
+

+ We think there’s a better way to write code—and we've been working for more than a decade to bring it into existence. +

+

+ Our first attempt was Atom, which we loved like a child but which ultimately fell short of our original vision. When we created Electron in 2012 to serve as Atom's runtime, there weren't a lot of great options for building cross-platform desktop apps. +

+

+ Had we tried to write Atom in C or C++, it never would have shipped, and we loved the idea of developers extending their editor with the familiar tools of JavaScript, HTML, and CSS. +

+

+ In the end, however, we reached the conclusion that the editor we wanted to use couldn't be built in a single-threaded scripting language. It was time to start over. Now we're back from the wilderness, this time with the knowledge and tools we need to execute without compromise. +

+

+ We're leveraging Rust, conflict-free replicated data types, and every core of your CPU and GPU to deliver an editor that will make coding more productive, fun, and collaborative. We look forward to sharing our best with you! +

+ +

The Team

+
+
+
+

Nathan Sobo

+
+

Nathan joined GitHub in late 2011 to build the Atom text editor, and he led the Atom team until 2018.

+ +

He also co-led development of Teletype for Atom, pioneering one of the first production uses of conflict-free replicated data types for collaborative text editing.

+ +

He's been dreaming about building the world’s best text editor since he graduated from college, and is excited to finally have the knowledge, tools, and resources to achieve this vision.

+ + +
+

———

+
+
+ +
+
+

Antonio Scandurra

+
+

Antonio joined the Atom team in 2014 while still in university after his outstanding open source contributions caught the attention of the team.

+ +

He later joined Nathan in architecting Teletype for Atom and researching the foundations of what has turned into Zed.

+ +

For the last two years, he’s become an expert in distributed systems and conflict-free replicated data types through the development of a real-time, distributed, conflict-free database implemented in Rust for Ditto.

+ + +
+
+

———

+
+ +
+
+

Max Brunsfeld

+
+

Max joined the Atom team in 2013 after working at Pivotal Labs.

+ +

While driving Atom towards its 1.0 launch during the day, Max spent nights and weekends building Tree-sitter, a blazing-fast and expressive incremental parsing framework that currently powers all code analysis at GitHub.

+ +

Before leaving to start Zed, Max helped GitHub's semantic analysis team integrate Tree-sitter to support syntax highlighting and code navigation on github.com.

+ +
-
-
- -
- - ANTONIO SCANDURRA - -
- Antonio joined the Atom team in 2014 while still in university after his outstanding open source - contributions caught the attention of the team. He later joined Nathan in architecting Teletype for - Atom and researching the foundations of what has turned into Zed. For the last two years, - he’s - become an expert in distributed systems and conflict-free replicated data types through the - development of a real-time, distributed, conflict-free database implemented in Rust for Ditto. +

———

+
+ +
+
+

Nate Butler

+
+

Nate joined the Facebook team in 2015 as a product designer on News Feed, after spending the previous few years working on sites like Format.com and Lookbook.com.

+ +

He spent three years shipping creative tools and projects like Facebook Avatars. He later moved on to working on dev tools and design systems, focused on developer efficiency.

+ +

Before leaving to join Zed, Nate spent his last year at Facebook developing a future vision for Stories.

+ +
- -
- -
- - MAX BRUNSFELD - -
- Max joined the Atom team in 2013 after working at Pivotal Labs. While driving Atom towards its 1.0 - launch during the day, Max spent nights and weekends building Tree-sitter, a blazing-fast and - expressive incremental parsing framework that currently powers all code analysis at GitHub. Before - leaving to start Zed, Max helped GitHub's semantic analysis team integrate Tree-sitter to support - syntax highlighting and code navigation on github.com. +

———

+
+ +
+
+

Want to join us?

+
+

We hope to bring a few more staff-level engineers in the near future. Come join us in building the next generation of software.

+ +

Drop us a line.

- +
- + + {{/layout}}