diff --git a/README.md b/README.md index d2756911..effeb3b2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ +
+ + Grain + +
+ # Grain Website -Documentation for the Grain programming language. +Documentation for the Grain programming language at [grain-lang.org](https://grain-lang.org/). [![Netlify Status](https://api.netlify.com/api/v1/badges/62e3f960-de88-4a28-a8f8-b8dddca145cb/deploy-status)](https://app.netlify.com/sites/grain-lang/deploys) @@ -10,52 +16,29 @@ This documentation site is a [Hexo](https://hexo.io/) site. All of the docs are ## Contributing -### Documentation Site - -The documentation site is everything served from `/docs/` and `/guide/` on the [main Grain website](https://grain-lang.org/). - -To get the docs up and running locally, just run - -```sh -npm install -npm start -``` - -You can run `npm run start:guide` if you want to see changes to the guide. +### Editing a Document -This will install all necessary dependencies and serve the website on port 4000. +To make a change to a document, edit the corresponding Markdown file in [src](src). The file path matches the URL path after `/docs`, but if you have trouble finding the page you're looking for, you can click the "Edit on GitHub" button at the top of page on the website. -For simple edits to the existing Markdown files, just edit them as you would any normal Markdown. +### Adding a New Document -To add a new page, add a new Markdown file in the relevant location and update `_config.yml` to include it. It's the same as normal Markdown, but you must include a set of front matter, i.e. a set of key value pairs that begin the file and surrounded by dashes, like so: +Create your new Markdown file in `src`. You'll also need to update [docs_config.yml](docs_config.yml) to include your new page in the sidebar. Each document starts with some front-matter, which is a bit of yml/json that is given to the renderer. For now, this only includes the title of the page. Since the title of the page is an `h1`, headers in your document should begin at level 2: -``` +```markdown --- title: Some Title of Some Topic --- -## Content begins here +## Content Begins Here ``` -The title is inserted at the beginning of the page, and is used in the sidebar. Thus, all headings in the Markdown files should start at heading level 2. +### Previewing the Site -### Home Page - -The home page is just static HTML/CSS. To get it running, start a web server in your local directory. For example: +Once a PR is created, Netlify will create a preview site and comment on the PR with a link. If you'd like to view your changes locally, run ```sh -python -m SimpleHTTPServer 4040 -# This starts a server on port 4040 -``` - -### Putting It All Together - -If for some reason you wish to view the entire site running together, you can run - -```sh -npm run build +npm install +npm start ``` -and then follow the steps outlined in the Home Page section. - -Don't commit the `/docs/` directory, as we wish to keep this repo clean (it's not in the `.gitignore` because those files need to be checked into source control for GitHub pages to work properly, and that's done automatically on the `master` branch). +This will install all build dependencies and serve the website on port 3000. diff --git a/index.html b/index.html index 7312fb9e..2bc872d0 100644 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ gtag('config', 'UA-123482724-1'); Grain: A strongly-typed functional programming language for the modern web. - + diff --git a/javascripts/prism.css b/javascripts/prism.css deleted file mode 100644 index 97f30cfc..00000000 --- a/javascripts/prism.css +++ /dev/null @@ -1,241 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&plugins=toolbar+show-language */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - background: none; - text-shadow: none; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em 1.5em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: white; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; - white-space: normal; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; - font-style: italic; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol, -.token.deleted { - color: #cc9900; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin, -.token.inserted { - color: #388E3C; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #a67f59; - background: hsla(0, 0%, 100%, .5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #3F51B5; -} - -.token.function { - color: #448AFF; -} - -.token.regex, -.token.important, -.token.variable { - color: #448AFF; -} - -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} - -.token.entity { - cursor: help; -} - -pre.code-toolbar { - position: relative; -} - -pre.code-toolbar > .toolbar { - position: absolute; - top: .3em; - right: .2em; - transition: opacity 0.3s ease-in-out; - opacity: 0; -} - -pre.code-toolbar:hover > .toolbar { - opacity: 1; -} - -pre.code-toolbar > .toolbar .toolbar-item { - display: inline-block; -} - -pre.code-toolbar > .toolbar a { - cursor: pointer; -} - -pre.code-toolbar > .toolbar button { - background: none; - border: 0; - color: inherit; - font: inherit; - line-height: normal; - overflow: visible; - padding: 0; - -webkit-user-select: none; /* for button */ - -moz-user-select: none; - -ms-user-select: none; -} - -pre.code-toolbar > .toolbar a, -pre.code-toolbar > .toolbar button, -pre.code-toolbar > .toolbar span { - color: #bbb; - font-size: .8em; - padding: 0 .5em; - background: #f5f2f0; - background: rgba(224, 224, 224, 0.2); - box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); - border-radius: .5em; -} - -pre.code-toolbar > .toolbar a:hover, -pre.code-toolbar > .toolbar a:focus, -pre.code-toolbar > .toolbar button:hover, -pre.code-toolbar > .toolbar button:focus, -pre.code-toolbar > .toolbar span:hover, -pre.code-toolbar > .toolbar span:focus { - color: inherit; - text-decoration: none; -} - -pre.line-numbers { - position: relative; - padding-left: 3.8em; - counter-reset: linenumber; -} - -pre.line-numbers > code { - position: relative; - white-space: inherit; -} - -.line-numbers .line-numbers-rows { - position: absolute; - pointer-events: none; - top: 0; - font-size: 100%; - left: -3.8em; - width: 3em; /* works for line-numbers below 1000 lines */ - letter-spacing: -1px; - /* border-right: 1px solid #999; */ - - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -} - -.line-numbers-rows > span { - pointer-events: none; - display: block; - counter-increment: linenumber; -} - -.line-numbers-rows > span:before { - content: counter(linenumber); - color: #BDBDBD; - display: block; - padding-right: 0.8em; - text-align: right; - top: -1px; -} \ No newline at end of file diff --git a/javascripts/prism.js b/javascripts/prism.js deleted file mode 100644 index ccefc681..00000000 --- a/javascripts/prism.js +++ /dev/null @@ -1,17 +0,0 @@ -/* PrismJS 1.11.0 -http://prismjs.com/download.html?themes=prism&plugins=line-numbers+remove-initial-line-feed */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,N=t.length;N>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,S=w.slice(0,A),C=w.slice(j),M=[b,P];S&&(++b,k+=S.length,M.push(S));var E=new s(g,f?n.tokenize(_,f):_,y,_,m);if(M.push(E),C&&M.push(C),Array.prototype.splice.apply(t,M),1!=P&&n.matchGrammar(e,t,r,b,k,!0,g),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=/\n(?!$)/g,n=function(e){var n=r(e),s=n["white-space"];if("pre-wrap"===s||"pre-line"===s){var l=e.querySelector("code"),i=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),o=l.textContent.split(t);a||(a=document.createElement("span"),a.className="line-numbers-sizer",l.appendChild(a)),a.style.display="block",o.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;i.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},r=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),n)}),Prism.hooks.add("complete",function(e){if(e.code){var r=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(r&&/pre/i.test(r.nodeName)&&(s.test(r.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s," ")),s.test(r.className)||(r.className+=" line-numbers");var l,i=e.code.match(t),a=i?i.length+1:1,o=new Array(a+1);o=o.join(""),l=document.createElement("span"),l.setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=o,r.hasAttribute("data-start")&&(r.style.counterReset="linenumber "+(parseInt(r.getAttribute("data-start"),10)-1)),e.element.appendChild(l),n(r),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(t,n){if("PRE"===t.tagName&&t.classList.contains(e)){var r=t.querySelector(".line-numbers-rows"),s=parseInt(t.getAttribute("data-start"),10)||1,l=s+(r.children.length-1);s>n&&(n=s),n>l&&(n=l);var i=n-s;return r.children[i]}}}}}(); -!function(){"undefined"!=typeof self&&self.Prism&&self.document&&Prism.hooks.add("before-sanity-check",function(e){if(e.code){var s=e.element.parentNode,n=/\s*\bkeep-initial-line-feed\b\s*/;!s||"pre"!==s.nodeName.toLowerCase()||n.test(s.className)||n.test(e.element.className)||(e.code=e.code.replace(/^(?:\r?\n|\r)/,""))}})}(); -Prism.languages.grain = { - 'string': { - pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/, - greedy: true - }, - 'comment': /#.*/i, - 'function': /(\w+(?=\s*=.*=>)|\w+(?=\())/i, - 'keyword': /(\b(let|rec|and|box|unbox|ref|begin|end|if|else)\b|=>|=|<=|>=|:=)/i, - 'builtin': /(equal|strcat|strlen|strslice|toString|setText|dangerouslySetInnerHTML|query)/i, - 'regex': /DOM/i, - 'constant': /\b(\d+|true|false)\b/i, -} \ No newline at end of file diff --git a/scripts/syntaxHighlight.js b/scripts/syntaxHighlight.js index aa5a3595..298e9a6e 100644 --- a/scripts/syntaxHighlight.js +++ b/scripts/syntaxHighlight.js @@ -43,7 +43,7 @@ registry.loadGrammar('source.grain').then(grammar => { ruleStack = lineTokens.ruleStack; } - return `
${makeGutter(text.length)}
${result.join('')}
`; + return `
${makeGutter(text.length)}
${result.join('')}
`; } }) }) diff --git a/stylesheets/style.css b/stylesheets/style.css index 09a00ad8..c770aef7 100644 --- a/stylesheets/style.css +++ b/stylesheets/style.css @@ -6,7 +6,7 @@ html { --orange: rgb(255, 133, 14); --white: white; --gray2: #9B9B9B; - --blue: #414770; + --blue: #202C59; --black: #33333A; --font-heading: "Source Sans Pro", sans-serif; diff --git a/themes/grain/layout/layout.ejs b/themes/grain/layout/layout.ejs index b3734f90..7b50e00f 100644 --- a/themes/grain/layout/layout.ejs +++ b/themes/grain/layout/layout.ejs @@ -10,7 +10,7 @@ gtag('config', 'UA-123482724-1'); Grain Docs - <%- page.title %> - + @@ -37,11 +37,10 @@ - <%- body %> - +
This is a notification!
\ No newline at end of file diff --git a/themes/grain/source/css/source.grain.css b/themes/grain/source/css/source.grain.css index 4c2898b9..4f9d1917 100644 --- a/themes/grain/source/css/source.grain.css +++ b/themes/grain/source/css/source.grain.css @@ -1,13 +1,14 @@ .tm-highlight { - --code-purple: #083D77; - --code-light-purple: #7D83FF; - --code-green: #0B6E4F; - --code-orange: #DD4B1A; - --code-blue: #00798C; - --code-red: #6A0136; - --code-gray: #808080; + --code-purple: #9fa0ff; + --code-light-purple: #6699cc; + --code-green: #75dddd; + --code-orange: var(--orange); + --code-blue: #d6edff; + --code-light-blue: #05b2dc; + --code-red: #ed254e; + --code-gray: #637081; - --code-extra: #19535F; + --code-extra: #d6edff; --code-pink: #9E0031; --code-brown: #600047; } @@ -21,7 +22,7 @@ } .constant.language.grain, .constant.numeric.grain { - color: var(--code-red); + color: var(--code-orange); } .entity.name.function.grain { color: var(--code-blue); @@ -36,7 +37,7 @@ .keyword.grain, .keyword.operator.accessor.grain, .keyword.operator.grain { - color: var(--code-purple); + color: var(--code-light-purple); } .meta.separator.grain { color: var(--code-gray); @@ -57,7 +58,7 @@ color: var(--code-green); } .support.constant.grain { - color: var(--code-red); + color: var(--code-orange); } .punctuation.support.grain, .support.type.grain { diff --git a/themes/grain/source/css/style.css b/themes/grain/source/css/style.css index 751a25ce..d5dad18b 100644 --- a/themes/grain/source/css/style.css +++ b/themes/grain/source/css/style.css @@ -4,10 +4,12 @@ html { --orange-medium: rgba(255, 133, 14, .15); --blue-light: rgba(65, 71, 112, .05); --white: white; + --gray: #EFEFEF; --gray2: #9B9B9B; - --blue: #414770; + --blue: #4B557A; --cyan: #00A6A6; --black: #33333A; + --oxford: #202C59; --font-heading: "Source Sans Pro", sans-serif; } @@ -80,6 +82,8 @@ h1 { } h2 { font-size: 2rem; + border-top: 2px solid var(--gray); + padding-top: 1.5rem; } h3 { font-size: 1.5rem; @@ -444,20 +448,67 @@ th { padding: 0; } .gutter { - width: 40px; + width: 1rem; } .gutter pre { - background-color: #f9f9f9; - color: #aaa; + background-color: var(--oxford); + color: var(--blue); text-align: right; - padding: 1.5em 12px; + padding: 1.25rem 0 1.25rem 1.25rem; margin: 0; } .code pre { - background-color: #f9f9f9; + background-color: var(--oxford); white-space: pre; - padding: 1.5em 12px; + padding: 1.25rem; margin: 0; + color: var(--white); +} +.code-tools { + width: 1rem; + background-color: var(--oxford); + vertical-align: top; + padding: 1.25rem 1.25rem 1.25rem 0; +} +.code-copy { + color: var(--blue); + display: flex; + cursor: pointer; + transition: color 0.075s; +} +.code-copy:focus, .code-copy:hover { + color: var(--white); +} +.tm-highlight table { + border-spacing: 0; +} +.gutter pre { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.code-tools { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.grain-snackbar { + position: fixed; + background-color: var(--oxford); + color: var(--white); + padding: 1rem; + border-radius: 4px; + right: 1.5rem; + bottom: 1.5rem; + width: 20rem; + transform: translateY(5rem); + transition: transform 0.4s ease; + -webkit-box-shadow: 2px 2px 4px 0px rgba(155,155,155,1); + -moz-box-shadow: 2px 2px 4px 0px rgba(155,155,155,1); + box-shadow: 2px 2px 4px 0px rgba(155,155,155,1); +} + +.grain-snackbar.open { + transform: translateY(0); } /* hack for hash links to work properly */ diff --git a/themes/grain/source/js/main.js b/themes/grain/source/js/main.js index 8a0150c6..fec603fe 100644 --- a/themes/grain/source/js/main.js +++ b/themes/grain/source/js/main.js @@ -11,4 +11,25 @@ if (sidebarToggle) sidebarToggle.addEventListener('click', () => { } }); -new ActiveMenuLink.default('.sidebar.toc', { activeClass: 'current', headerHeight: 0 }); \ No newline at end of file +new ActiveMenuLink.default('.sidebar.toc', { activeClass: 'current', headerHeight: 0 }); + +const snackbar = document.querySelector('.grain-snackbar'); +const closeSnackbar = () => { + snackbar.classList.remove('open'); +}; +const grainNotify = (content, duration) => { + snackbar.textContent = content + snackbar.classList.add('open') + setTimeout(closeSnackbar, duration) +}; + +const codeCopied = () => grainNotify('Code copied to clipboard!', 3000); + +document.querySelectorAll('.tm-highlight').forEach((code) => { + const copy = code.querySelector('.code-copy'); + const text = code.querySelector('.code'); + copy.addEventListener('click', () => { + navigator.clipboard.writeText(text.innerText); + grainNotify('Code copied to clipboard!', 3000); + }); +});