diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c13c5f6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b64e0cd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ + +# EditorConfig is awesome: http://EditorConfig.org + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +[*.json] +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49f1d25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.sass-cache +.jekyll-metadata +node_modules +Gemfile.lock +_dist +.awspublish* +yarn.lock +.yarnclean +.bundle +package-lock.json diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..b95eefa --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,3 @@ +{ + "extends": "stylelint-config-bigchaindb" +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d7e2252 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +sudo: required +dist: trusty + +language: ruby +rvm: + - 2.4.0 + +cache: + bundler: true + directories: + - $TRAVIS_BUILD_DIR/node_modules + +before_install: + - nvm install 8 + +before_script: "_ci/setup.sh" +script: "_ci/build.sh" +after_success: "_ci/deploy.sh" + +notifications: + email: false diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..4d9de1f --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +gem 'jekyll' + +group :jekyll_plugins do + gem 'jekyll-sitemap' + gem 'jekyll-redirect-from' +end \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..78eb129 --- /dev/null +++ b/LICENSE @@ -0,0 +1,174 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. diff --git a/README.md b/README.md index ec06fb5..e45764a 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,206 @@ -# README.md +# ![ipdb/site](.png) -## Overview -This repository contains files related to the IPDB website. +> The blockchain database governance site the universe needs +> https://ipdb.io -## Contributors -Three teams are working on this: -- Members of the IPDB team +🐉🐲 **Highly in development right now, nothing in `master` is final. Content & structure development [happening in Google Doc](https://docs.google.com/a/bigchaindb.com/document/d/1bgQozCf47XGOViYT0KOCwRV2UdPlpeDQh1JuAPaHi-A/edit?usp=sharing)** 🐲🐉 + +[![Build Status](https://travis-ci.org/ipdb/site.io.svg?branch=master)](https://travis-ci.org/ipdb/site.io) +[![css bigchaindb](https://img.shields.io/badge/css-bigchaindb-39BA91.svg)](https://github.com/bigchaindb/stylelint-config-bigchaindb) +[![js ascribe](https://img.shields.io/badge/js-ascribe-39BA91.svg)](https://github.com/ascribe/javascript) + +# Contents + +- [Content editing](#content-editing) + - [Pages](#pages) + - [Special pages](#special-pages) + - [Front page](#front-page) +- [Development](#development) + - [Install dependencies](#install-dependencies) + - [Development build](#development-build) +- [Continuous deployment: always be shipping](#continuous-deployment-always-be-shipping) +- [Manual deployment](#manual-deployment) + - [Prerequisite: authentication](#prerequisite-authentication) + - [Staging build & beta deployment](#staging-build--beta-deployment) + - [Production build & live deployment](#production-build--live-deployment) +- [Coding conventions](#coding-conventions) + - [(S)CSS](#scss) + - [js](#js) +- [Authors & Contributors](#authors--contributors) +- [License](#license) + +# Content editing + +![unknown](https://user-images.githubusercontent.com/90316/28792395-c1b74594-762f-11e7-8ff6-b49586f39360.jpeg) + +Most content on the site can be edited on GitHub without messing with HTML markup. + +The site's source and structure is in the [`_src/`](_src) folder. Ignore everything with an underscore in its name. + +When viewing a file on GitHub you will see a small pencil icon in the top right. Click that to edit the file. + +## Pages + +All pages are simple Markdown files. Markdown is a way of telling the site how an element should be marked up, like headings & bold text: + +```markdown +I'm a simple paragraph. No fancy symbols needed. + +# I'm a heading 1 +## I'm a heading 2 + +You can make text **bold like so** +``` + +## Special pages + +Some pages like front page source their content dynamically during site build. This is so we have a single source of truth for content used in multiple places on the site. + +### Front page + +Content for all sections on front page is coming from a data file: +- [`_src/_data/content-front.yml`](_src/_data/content-front.yml) + + +# Development + +![200](https://user-images.githubusercontent.com/90316/28792559-56cbe02c-7630-11e7-851f-40192e0ce50a.gif) + +You need to have the following tools installed on your development machine before moving on: + +- [node.js](http://nodejs.org/) & [npm](https://npmjs.org/) +- (optional) use [Yarn](https://yarnpkg.com) instead of npm for faster dependency installations +- [Ruby](https://www.ruby-lang.org) (for sanity, install with [rvm](https://rvm.io/)) +- [Bundler](http://bundler.io/) + +## Install dependencies + +Run the following command from the repository's root folder to install all dependencies. + +```bash +npm i && bundle install +``` + +or + +```bash +yarn && bundle install +``` + +## Development build + +Spin up local dev server and livereloading watch task, reachable under [https://localhost:1337](https://localhost:1337): + +```bash +gulp +``` + +# Continuous deployment: always be shipping + +![shipping](https://cloud.githubusercontent.com/assets/90316/26559768/e21e9724-44b1-11e7-90cf-6ef6ebb06d09.gif) + +The site gets built & deployed automatically via Travis. This is the preferred way of deployment, it makes sure the site is always deployed with fresh dependencies and only after a successful build. + +Build & deployment happens under the following conditions on Travis: + +- every push builds the site +- **live deployment**: every push to the master branch initiates a live deployment +- **beta deployment**: every new pull request and every subsequent push to it initiates a beta deployment + +# Manual deployment + +For emergency live deployments or beta deployments, the manual method can be used. The site is hosted in an S3 bucket and gets deployed via a gulp task. + +## Prerequisite: authentication + +To deploy the site, you must authenticate yourself against the AWS API with your AWS credentials. Get your AWS access key and secret and add them to `~/.aws/credentials`: + +``` +[default] +aws_access_key_id = +aws_secret_access_key = +``` + +This is all that is needed to authenticate with AWS if you've setup your credentials as the default profile. + +If you've set them up as another profile, say `[ipdb]` you can grab those credentials by using the `AWS_PROFILE` variable like so: + +```bash +AWS_PROFILE=ipdb gulp deploy --live +``` + +In case that you get authentication errors or need an alternative way to authenticate with AWS, check out the [AWS documentation](http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html). + +## Staging build & beta deployment + +The staging build is a full production build but prevents search engine indexing & Google Analytics tracking. + +```bash +# make sure your local npm packages & gems are up to date +npm update && bundle update + +# make staging build in /_dist +# build preventing search engine indexing & Google Analytics tracking +gulp build --staging + +# deploy contents of /_dist to beta +gulp deploy --beta +``` + +## Production build & live deployment + +```bash +# make sure your local npm packages & gems are up to date +npm update && bundle update + +# make production build in /_dist +gulp build --production + +# deploy contents of /_dist to live +gulp deploy --live +``` + +# Coding conventions + +Lint with ESLint & [stylelint](https://stylelint.io) in your editor or run: + +```bash +npm test +``` + +## (S)CSS + +Follows [stylelint-config-bigchaindb](https://github.com/bigchaindb/stylelint-config-bigchaindb) which itself extends [stylelint-config-standard](https://github.com/stylelint/stylelint-config-standard). + +# js + +Follows [ascribe/javascript](https://github.com/ascribe/javascript) which itself extends [airbnb/javascript](https://github.com/airbnb/javascript). + +# Authors & Contributors + +- Greg McMullen ([@gmcmullen](https://github.com/gmcmullen)) - [IPDB Foundation](https://ipdb.foundation) +- Matthias Kretschmann ([@kremalicious](https://github.com/kremalicious)) - [BigchainDB](https://www.bigchaindb.com) +- Members of the IPDB Foundation team - Members of the BigchainDB development team -- Representatives of Caretakers in the IPDB +- Representatives of Caretakers in the IPDB -## Contact -[Greg McMullen](https://github.com/gmcmullen). + +# License + +For all code in this repository the Apache License, Version 2.0 is applied. + +``` +Copyright Interplanetary Database Foundation 2017. All rights reserved. + +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. +``` diff --git a/_ci/build.sh b/_ci/build.sh new file mode 100755 index 0000000..a5f325e --- /dev/null +++ b/_ci/build.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -e; + +echo "$(tput setaf 136)" +echo "=============================================" +echo " Starting tests " +echo "=============================================" +echo "$(tput sgr0)" # reset + +npm test + +echo "$(tput setaf 64)" # green +echo "---------------------------------------------" +echo " ✓ done testing" +echo "---------------------------------------------" +echo "$(tput sgr0)" # reset + + +echo "$(tput setaf 136)" +echo "=============================================" +echo " Starting build " +echo "=============================================" +echo "$(tput sgr0)" # reset + +## +## check for pull request against master +## +if [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then + + gulp build --staging + + +## +## check for master push which is no pull request +## +elif [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + + gulp build --production + +else + + gulp build --production + +fi; + + +echo "$(tput setaf 64)" # green +echo "---------------------------------------------" +echo " ✓ done building" +echo "---------------------------------------------" +echo "$(tput sgr0)" # reset diff --git a/_ci/deploy.sh b/_ci/deploy.sh new file mode 100755 index 0000000..318e978 --- /dev/null +++ b/_ci/deploy.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -e; + +## +## check for pull request against master +## +if [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then + + gulp deploy --beta; + + +## +## check for master push which is no pull request +## +elif [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + + gulp deploy --live; + +else + + echo "$(tput setaf 64)" # green + echo "---------------------------------------------" + echo " ✓ nothing to deploy " + echo "---------------------------------------------" + echo "$(tput sgr0)" # reset + +fi; + +echo "$(tput setaf 64)" # green +echo "---------------------------------------------" +echo " ✓ done deployment " +echo "---------------------------------------------" +echo "$(tput sgr0)" # reset + +exit; diff --git a/_ci/setup.sh b/_ci/setup.sh new file mode 100755 index 0000000..fef53ce --- /dev/null +++ b/_ci/setup.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e; + +echo "$(tput setaf 136)" +echo " Installing dependencies " +echo "=============================================" +echo "$(tput sgr0)" # reset + +npm install gulpjs/gulp.git#4.0 -g +npm install + +# Travis does that automatically after selecting ruby +#bundle install + +echo "$(tput setaf 64)" # green +echo "---------------------------------------------" +echo " ✓ done installing dependencies" +echo "$(tput sgr0)" # reset diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c98d372 --- /dev/null +++ b/_config.yml @@ -0,0 +1,33 @@ +# The Basics +# -------------------- +title: "IPDB" +description: "The Interplanetary database." +url: "https://ipdb.io" +email: "contact@ipdb.io" + +github: + org: "ipdb" + repo: "site" + +analyticsID: "" + + +# Urls +# -------------------- +permalink: /:title/ + + +# Generator +# -------------------- +source: ./_src +destination: ./_dist + + +# Plugins +# -------------------- +plugins: + - jekyll-sitemap + - jekyll-redirect-from + +exclude: + - "*README.md" diff --git a/SERVICEPRIVACY.md b/_src/SERVICEPRIVACY.md similarity index 100% rename from SERVICEPRIVACY.md rename to _src/SERVICEPRIVACY.md diff --git a/SERVICETERMS.md b/_src/SERVICETERMS.md similarity index 100% rename from SERVICETERMS.md rename to _src/SERVICETERMS.md diff --git a/SITEPRIVACY.md b/_src/SITEPRIVACY.md similarity index 100% rename from SITEPRIVACY.md rename to _src/SITEPRIVACY.md diff --git a/SITETERMS.md b/_src/SITETERMS.md similarity index 100% rename from SITETERMS.md rename to _src/SITETERMS.md diff --git a/_src/_assets/js/_dnt.js b/_src/_assets/js/_dnt.js new file mode 100644 index 0000000..abf646b --- /dev/null +++ b/_src/_assets/js/_dnt.js @@ -0,0 +1,46 @@ +/** + * Returns true or false based on whether doNotTack is enabled. It also takes into account the + * anomalies, such as !bugzilla 887703, which effect versions of Fx 31 and lower. It also handles + * IE versions on Windows 7, 8 and 8.1, where the DNT implementation does not honor the spec. + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1217896 for more details + * @params {string} [dnt] - An optional mock doNotTrack string to ease unit testing. + * @params {string} [userAgent] - An optional mock userAgent string to ease unit testing. + * @returns {boolean} true if enabled else false + */ +function _dntEnabled(dnt, userAgent) { + + 'use strict'; + + // for old version of IE we need to use the msDoNotTrack property of navigator + // on newer versions, and newer platforms, this is doNotTrack but, on the window object + // Safari also exposes the property on the window object. + var dntStatus = dnt || navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack; + var ua = userAgent || navigator.userAgent; + + // List of Windows versions known to not implement DNT according to the standard. + var anomalousWinVersions = ['Windows NT 6.1', 'Windows NT 6.2', 'Windows NT 6.3']; + + var fxMatch = ua.match(/Firefox\/(\d+)/); + var ieRegEx = /MSIE|Trident/i; + var isIE = ieRegEx.test(ua); + // Matches from Windows up to the first occurance of ; un-greedily + // http://www.regexr.com/3c2el + var platform = ua.match(/Windows.+?(?=;)/g); + + // With old versions of IE, DNT did not exist so we simply return false; + if (isIE && typeof Array.prototype.indexOf !== 'function') { + return false; + } else if (fxMatch && parseInt(fxMatch[1], 10) < 32) { + // Can't say for sure if it is 1 or 0, due to Fx bug 887703 + dntStatus = 'Unspecified'; + } else if (isIE && platform && anomalousWinVersions.indexOf(platform.toString()) !== -1) { + // default is on, which does not honor the specification + dntStatus = 'Unspecified'; + } else { + // sets dntStatus to Disabled or Enabled based on the value returned by the browser. + // If dntStatus is undefined, it will be set to Unspecified + dntStatus = { '0': 'Disabled', '1': 'Enabled' }[dntStatus] || 'Unspecified'; + } + + return dntStatus === 'Enabled' ? true : false; +} diff --git a/_src/_assets/js/ipdb.js b/_src/_assets/js/ipdb.js new file mode 100644 index 0000000..3ba89f1 --- /dev/null +++ b/_src/_assets/js/ipdb.js @@ -0,0 +1 @@ +//=include _dnt.js diff --git a/_src/_assets/scss/_typography.scss b/_src/_assets/scss/_typography.scss new file mode 100644 index 0000000..dc0307f --- /dev/null +++ b/_src/_assets/scss/_typography.scss @@ -0,0 +1,65 @@ +@import 'variables'; + +html { + font-size: $font-size-root; + -webkit-tap-highlight-color: transparent; + + @media ($screen-lg) { + font-size: $font-size-root-lg; + } +} + +body { + font-family: $font-family-base; + font-size: $font-size-base; + line-height: $line-height; + color: $text-color; + background: $brand-04; + margin: 0; + + // Controversial! But prevents text flickering in + // Safari/Firefox when animations are running + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +h1, h2, h3, h4, h5 { // stylelint-disable-line selector-list-comma-newline-after + color: $brand-03; + font-family: $font-family-silkscreen; + margin-top: $spacer; + margin-bottom: $spacer; + + &:first-child { + margin-top: 0; + } +} + +p, +ul, +ol { + margin: 0 0 $spacer; +} + + +// +// Lists +// +ul, +ol { + margin-left: 0; + padding-left: $spacer; +} + +a { + color: $brand-03; + + &:hover, + &:focus { + color: darken($brand-03, 20%); + } +} + +.lead { + color: $brand-03; + font-size: $font-size-large; +} diff --git a/_src/_assets/scss/_variables.scss b/_src/_assets/scss/_variables.scss new file mode 100644 index 0000000..f05d452 --- /dev/null +++ b/_src/_assets/scss/_variables.scss @@ -0,0 +1,40 @@ +// +// Colors +// +$brand-01: # !default; +$brand-02: # !default; +$brand-03: # !default; +$brand-04: # !default; +$brand-05: # !default; +$brand-06: # !default; + +// +// Typography +// +$font-family-base: !default; +$font-family-silkscreen: !default; +$font-size-root: 16px !default; +$font-size-root-lg: 18px !default; +$line-height: 1.4 !default; +$spacer: 1.5rem !default; + +$font-size-base: 1rem !default; +$font-size-large: 1.3rem !default; +$font-size-small: .8rem !default; +$font-size-mini: .7rem !default; + +$font-weight-normal: 400 !default; +$font-weight-bold: 700 !default; + +$text-color: $brand-05 !default; + +// +// Responsive breakpoints +// +$screen-sm-min: 40em !default; +$screen-md-min: 58em !default; +$screen-lg-min: 85em !default; + +$screen-sm: 'min-width: #{$screen-sm-min}'; +$screen-md: 'min-width: #{$screen-md-min}'; +$screen-lg: 'min-width: #{$screen-lg-min}'; diff --git a/_src/_assets/scss/ipdb.scss b/_src/_assets/scss/ipdb.scss new file mode 100644 index 0000000..e69de29 diff --git a/_src/_caretakers/coala.md b/_src/_caretakers/coala.md new file mode 100644 index 0000000..e69de29 diff --git a/FAQ.md b/_src/_docs/faq.md similarity index 100% rename from FAQ.md rename to _src/_docs/faq.md diff --git a/_src/_includes/head.html b/_src/_includes/head.html new file mode 100644 index 0000000..0ebaf67 --- /dev/null +++ b/_src/_includes/head.html @@ -0,0 +1,62 @@ + + + + + + {% if page.title %} + {{ page.title }} {{ site.title }} + {% else %} + {{ site.title }} {{ site.description }} + {% endif %} + + + + {% if page.description %} + + {% elsif page.front_page %} + + {% else %} + + {% endif %} + + + + + + + + + + + + {% if page.css %} + + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + {% if jekyll.environment != 'production' or page.sitemap == false %} + + {% endif %} + + + diff --git a/_src/_includes/scripts.html b/_src/_includes/scripts.html new file mode 100644 index 0000000..e2d562e --- /dev/null +++ b/_src/_includes/scripts.html @@ -0,0 +1,66 @@ + + + + +{% if page.js %} + +{% elsif layout.js %} + +{% endif %} + + + + + +{% if jekyll.environment == "production" %} + +{% else %} + +{% endif%} diff --git a/_src/_layouts/base.html b/_src/_layouts/base.html new file mode 100644 index 0000000..42496dc --- /dev/null +++ b/_src/_layouts/base.html @@ -0,0 +1,22 @@ + + + + {% include head.html %} + + {% capture id %}{% if page.front_page %}front{% else %}{{ page.url | replace:'/','-' | replace_first:'-','' | replace:'.html','' | replace:'-index','' }}{% endif %}{% endcapture %} + + + + + + {{ content }} + + {% include scripts.html %} + + + + diff --git a/gulpfile.babel.js b/gulpfile.babel.js new file mode 100644 index 0000000..9a995cc --- /dev/null +++ b/gulpfile.babel.js @@ -0,0 +1,446 @@ +// load plugins +const $ = require('gulp-load-plugins')() + +// manually import modules that won't get picked up by gulp-load-plugins +import { src, dest, watch, parallel, series } from 'gulp' +import del from 'del' +import parallelize from 'concurrent-transform' +import browser from 'browser-sync' +import critical from 'critical' +import fs from 'fs' +import yaml from 'js-yaml' +import request from 'request' + +// required to get our mix of old and ES6+ js to work with ugify-js 3 +import uglifyjs from 'uglify-es' +import composer from 'gulp-uglify/composer' +const minify = composer(uglifyjs, console) + +// get all the configs: `pkg` and `site` +import pkg from './package.json' +const site = yaml.safeLoad(fs.readFileSync('./_config.yml')) + +// handle errors +const onError = (error) => { + console.log($.util.colors.red('\nYou fucked up:', error.message, 'on line' , error.lineNumber, '\n')) + this.emit('end') +} + +// 'development' is just default, production overrides are triggered +// by adding the production flag to the gulp command e.g. `gulp build --production` +const isProduction = ($.util.env.production === true ? true : false), + isStaging = ($.util.env.staging === true ? true : false) + + +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// Config +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +// Port to use for the development server +const PORT = 1337 + +// paths +const SRC = site.source + '/', + DIST = site.destination + '/' + +// deployment +const S3BUCKET = 'beta.ipdb.io', + S3REGION = 'eu-central-1', + S3BUCKET_BETA = 'beta.ipdb.io', + S3REGION_BETA = 'eu-central-1' + +// SVG sprite +const SPRITECONFIG = { + dest: DIST + 'assets/img/', + mode: { + symbol: { + dest: './', + sprite: 'sprite.svg' + } + } +} + +// code banner +const BANNER = [ + '/**', + ' ** <%= pkg.name %>', + ' ** <%= pkg.description %>', + ' ** <%= pkg.homepage %>', + ' **', + ' ** <%= pkg.author.name %> <<%= pkg.author.email %>>', + ' **/', + '' +].join('\n') + + +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// Tasks +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +// +// Delete build artifacts +// +export const clean = () => + del([ + DIST + '**/*', + DIST + '.*' // delete all hidden files + ]) + + +// +// Jekyll +// +export const jekyll = (done) => { + + browser.notify('Compiling Jekyll') + + if (isProduction) { + process.env.JEKYLL_ENV = 'production' + var jekyll_options = 'jekyll build' + } else if (isStaging) { + process.env.JEKYLL_ENV = 'staging' + var jekyll_options = 'jekyll build' + } else { + process.env.JEKYLL_ENV = 'development' + var jekyll_options = 'jekyll build --incremental --drafts --future' + } + + let spawn = require('child_process').spawn, + jekyll = spawn('bundle', ['exec', jekyll_options], { stdio: 'inherit' }) + + jekyll.on('error', (error) => onError() ).on('close', done) +} + + +// +// HTML +// +export const html = () => src(DIST + '**/*.html') + .pipe($.if(isProduction || isStaging, $.htmlmin({ + collapseWhitespace: true, + conservativeCollapse: true, + removeComments: true, + useShortDoctype: true, + collapseBooleanAttributes: true, + removeRedundantAttributes: true, + removeEmptyAttributes: true, + minifyJS: true, + minifyCSS: true + }))) + .pipe(dest(DIST)) + + +// +// Styles +// +export const css = () => src([ + SRC + '_assets/styles/ipdb.scss', + SRC + '_assets/styles/page-*.scss' + ]) + .pipe($.if(!(isProduction || isStaging), $.sourcemaps.init())) + .pipe($.sass({ + includePaths: ['node_modules'] + }).on('error', $.sass.logError)) + .pipe($.autoprefixer()) + .pipe($.if(isProduction || isStaging, $.cleanCss())) + .pipe($.if(!(isProduction || isStaging), $.sourcemaps.write())) + .pipe($.if(isProduction || isStaging, $.header(BANNER, { pkg: pkg }))) + .pipe($.rename({ suffix: '.min' })) + .pipe(dest(DIST + 'assets/css/')) + .pipe(browser.stream()) + +// inline critical-path CSS +export const criticalCss = (done) => { + if (isProduction || isStaging) { + critical.generate({ + base: DIST, + src: 'index.html', + dest: 'index.html', + inline: true, + minify: true, + dimensions: [{ + height: 320, + width: 640 + }, { + height: 600, + width: 800 + }, { + height: 900, + width: 1360 + }] + }) + } + done() +} + + +// +// JavaScript +// +export const js = () => + src([ + SRC + '_assets/scripts/ipdb.js', + SRC + '_assets/scripts/page-*.js' + ]) + .pipe($.if(!(isProduction || isStaging), $.sourcemaps.init())) + .pipe($.include({ + includePaths: ['node_modules', SRC + '_assets/scripts'] + })).on('error', onError) + .pipe($.if(isProduction || isStaging, minify())).on('error', onError) + .pipe($.if(!(isProduction || isStaging), $.sourcemaps.write())) + .pipe($.if(isProduction || isStaging, $.header(BANNER, { pkg: pkg }))) + .pipe($.rename({suffix: '.min'})) + .pipe(dest(DIST + 'assets/js/')) + + +// +// SVG sprite +// +export const svg = () => src(SRC + '_assets/img/*.svg') + .pipe($.if(isProduction || isStaging, $.imagemin({ + svgoPlugins: [{ removeRasterImages: true }] + }))) + .pipe($.svgSprite(SPRITECONFIG)) + .pipe(dest(DIST + 'assets/img/')) + + +// +// Copy Images +// +export const images = () => src(SRC + '_assets/img/**/*') + .pipe($.if(isProduction || isStaging, $.imagemin([ + $.imagemin.gifsicle({ interlaced: true }), + $.imagemin.jpegtran({ progressive: true }), + $.imagemin.optipng({ optimizationLevel: 5 }), + $.imagemin.svgo({plugins: [{ removeViewBox: true }]}) + ]))) + .pipe(dest(DIST + 'assets/img/')) + + +// +// Revision static assets +// +export const rev = (done) => { + // globbing is slow so do everything conditionally for faster dev build + if (isProduction || isStaging) { + return src(DIST + 'assets/**/*.{css,js,png,jpg,jpeg,svg,eot,ttf,woff,woff2}') + .pipe($.rev()) + .pipe(dest(DIST + 'assets/')) + // output rev manifest for next replace task + .pipe($.rev.manifest()) + .pipe(dest(DIST + 'assets/')) + } + done() +} + + +// +// Replace all links to assets in files +// from a manifest file +// +export const revReplace = (done) => { + // globbing is slow so do everything conditionally for faster dev build + if (isProduction || isStaging) { + let manifest = src(DIST + 'assets/rev-manifest.json') + + return src(DIST + '**/*.{html,css,js}') + .pipe($.revReplace({ manifest: manifest })) + .pipe(dest(DIST)) + } + done() +} + + +// +// Dev Server +// +export const server = (done) => { + browser.init({ + server: DIST, + port: PORT, + reloadDebounce: 2000 + }) + done() +} + + +// +// Watch for file changes +// +export const watchSrc = () => { + watch(SRC + '_assets/styles/**/*.scss').on('all', series(css)) + watch(SRC + '_assets/scripts/**/*.js').on('all', series(js, browser.reload)) + watch(SRC + '_assets/images/**/*.{png,jpg,jpeg,gif,webp}').on('all', series(images, browser.reload)) + watch(SRC + '_assets/images/**/*.{svg}').on('all', series(svg, browser.reload)) + watch([SRC + '**/*.{html,xml,json,txt,md,yml}', './*.yml', SRC + '_includes/svg/*']).on('all', series('build', browser.reload)) +} + + +// +// Build banner +// +const buildBanner = (done) => { + console.log($.util.colors.gray(" ------------------------------------------")) + console.log($.util.colors.green(' Building ' + ($.util.env.production ? 'production' : $.util.env.staging ? 'staging' : 'dev') + ' version...')) + console.log($.util.colors.gray(" ------------------------------------------")) + + done() +} + + +// +// Deploy banner +// +const deployBanner = (done) => { + if (($.util.env.live || $.util.env.beta || $.util.env.gamma) === true ) { + console.log($.util.colors.gray(" ------------------------------------------")) + console.log($.util.colors.green(' Deploying to ' + ($.util.env.live ? 'Live' : $.util.env.beta ? 'Beta' : 'Gamma') + '... ')) + console.log($.util.colors.gray(" ------------------------------------------")) + } else { + console.log($.util.colors.red('\nHold your horses! You need to specify a deployment target like so: gulp deploy --beta. Possible targets are: --live, --beta, --gamma\n')) + } + done() +} + + +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// Collection tasks +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +// +// Full build +// +// `gulp build` is the development build +// `gulp build --production` is the production build +// +export const build = series(buildBanner, clean, jekyll, parallel(html, css, js, images, svg), rev, revReplace, criticalCss) + +// +// Build site, run server, and watch for file changes +// +// `gulp dev` +// +export const dev = series(build, server, watchSrc) + +// Set `gulp dev` as default: `gulp` +export default dev + + +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// Deployment +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +// +// gulp deploy --live +// gulp deploy --beta +// gulp deploy --gamma +// +export const s3 = () => { + + // create publisher, define config + if ($.util.env.live === true) { + var publisher = $.awspublish.create({ + params: { 'Bucket': S3BUCKET }, + 'accessKeyId': process.env.AWS_ACCESS_KEY, + 'secretAccessKey': process.env.AWS_SECRET_KEY, + 'region': S3REGION + }) + } else if ($.util.env.beta === true) { + var publisher = $.awspublish.create({ + params: { 'Bucket': S3BUCKET_BETA }, + 'accessKeyId': process.env.AWS_BETA_ACCESS_KEY, + 'secretAccessKey': process.env.AWS_BETA_SECRET_KEY, + 'region': S3REGION_BETA + }) + } else { + return + } + + return src(DIST + '**/*') + .pipe($.awspublishRouter({ + cache: { + // cache for 5 minutes by default + cacheTime: 300 + }, + routes: { + // all static assets, cached & gzipped + '^assets/(?:.+)\\.(?:js|css|png|jpg|jpeg|gif|ico|svg|ttf|eot|woff|woff2)$': { + cacheTime: 2592000, // cache for 1 month + gzip: true + }, + + // every other asset, cached + '^assets/.+$': { + cacheTime: 2592000 // cache for 1 month + }, + + // all html files, not cached & gzipped + '^.+\\.html': { + cacheTime: 0, + gzip: true + }, + + // all pdf files, not cached + '^.+\\.pdf': { + cacheTime: 0 + }, + + // font mime types + '\.ttf$': { + key: '$&', + headers: { 'Content-Type': 'application/x-font-ttf' } + }, + '\.woff$': { + key: '$&', + headers: { 'Content-Type': 'application/x-font-woff' } + }, + '\.woff2$': { + key: '$&', + headers: { 'Content-Type': 'application/x-font-woff2' } + }, + + // pass-through for anything that wasn't matched by routes above, to be uploaded with default options + "^.+$": "$&" + } + })) + .pipe(parallelize(publisher.publish(), 100)).on('error', onError) + .pipe(publisher.sync()) // delete files in bucket that are not in local folder + .pipe($.awspublish.reporter({ + states: ['create', 'update', 'delete'] + })) +} + + +// +// Ping search engines on live deployment +// +export const seo = (done) => { + + const googleUrl = 'http://www.google.com/webmasters/tools/ping?sitemap=', + bingUrl = 'http://www.bing.com/webmaster/ping.aspx?siteMap=' + + const response = (error, response) => { + if (error) { + $.util.log($.util.colors.red(error)) + } else { + $.util.log($.util.colors.gray('Status:', response && response.statusCode)) + + if (response.statusCode === 200) { + $.util.log($.util.colors.green('Successfully notified')) + } + } + } + + // if ($.util.env.live === true) { + // request(googleUrl + site.url + '/sitemap.xml', response) + // request(bingUrl + site.url + '/sitemap.xml', response) + // } + + done() +} + + +// +// `gulp deploy` +// +export const deploy = series(deployBanner, s3, seo) diff --git a/package.json b/package.json new file mode 100644 index 0000000..b792c4b --- /dev/null +++ b/package.json @@ -0,0 +1,76 @@ +{ + "name": "ipdb-site", + "version": "1.0.0", + "author": { + "name": "Matthias Kretschmann", + "email": "matthias@bigchaindb.com" + }, + "description": "The blockchain database governance the universe needs", + "homepage": "https://ipdb.io", + "license": "(c) 2017 IPDB Foundation - All Rights Reserved", + "main": "gulpfile.babel.js", + "scripts": { + "start": "gulp", + "build": "gulp build --production", + "test": "eslint _src/_assets/js/* && stylelint _src/_assets/styles/**/*.scss" + }, + "browserslist": [ + "last 2 versions", + "Chrome >= 30", + "Safari >= 6.1", + "Firefox >= 35", + "Opera >= 32", + "iOS >= 8", + "Android >= 4", + "ie >= 10" + ], + "dependencies": {}, + "devDependencies": { + "babel-core": "^6.25.0", + "babel-eslint": "^7.2.3", + "babel-preset-es2015": "^6.24.1", + "browser-sync": ">=2.10.0", + "concurrent-transform": "^1.0.0", + "critical": "^0.9.0", + "cross-spawn": "^5.1.0", + "del": "^3.0.0", + "eslint": "^4.4.1", + "eslint-config-ascribe": "^3.0.4", + "eslint-plugin-import": "^2.7.0", + "gulp": "github:gulpjs/gulp#4.0", + "gulp-autoprefixer": "^4.0.0", + "gulp-awspublish": "^3.0.0", + "gulp-awspublish-router": "^0.1.1", + "gulp-clean-css": "^3.7.0", + "gulp-cli": "^1.2.2", + "gulp-concat": "^2.6.0", + "gulp-header": "^1.8.9", + "gulp-htmlmin": "^3.0.0", + "gulp-if": "^2.0.2", + "gulp-imagemin": "^3.3.0", + "gulp-include": "^2.0.2", + "gulp-load-plugins": "^1.5.0", + "gulp-rename": "^1.2.2", + "gulp-replace": "^0.6.1", + "gulp-rev": "^8.0.0", + "gulp-rev-replace": "^0.4.2", + "gulp-sass": "^3.1.0", + "gulp-sourcemaps": "^2.4.1", + "gulp-svg-sprite": "^1.3.7", + "gulp-uglify": "^3.0.0", + "gulp-util": "^3.0.6", + "js-yaml": "^3.9.0", + "request": "^2.81.0", + "stylelint": "^8.0.0", + "stylelint-config-bigchaindb": "^1.0.0", + "stylelint-config-standard": "^17.0.0", + "uglify-es": "^3.0.25" + }, + "engines": { + "node": ">=7.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/ipdb/site" + } +}