mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-20 07:09:46 -05:00
Began converting docs to hexo
This commit is contained in:
+109
@@ -0,0 +1,109 @@
|
||||
# Hexo Configuration
|
||||
## Docs: https://hexo.io/docs/configuration.html
|
||||
## Source: https://github.com/hexojs/hexo/
|
||||
|
||||
# Site
|
||||
title: Cypress.io
|
||||
subtitle:
|
||||
description:
|
||||
author: Cypress.io
|
||||
language: en
|
||||
timezone: UTC
|
||||
|
||||
# URL
|
||||
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
|
||||
url: http://yoursite.com
|
||||
root: /
|
||||
permalink: :year/:month/:day/:title/
|
||||
permalink_defaults:
|
||||
|
||||
# Directory
|
||||
source_dir: source
|
||||
public_dir: public
|
||||
tag_dir: tags
|
||||
category_dir: categories
|
||||
code_dir: downloads/code
|
||||
i18n_dir: :lang
|
||||
skip_render:
|
||||
|
||||
# Writing
|
||||
new_post_name: :title.md # File name of new posts
|
||||
default_layout: post
|
||||
titlecase: false # Transform title into titlecase
|
||||
external_link: true # Open external links in new tab
|
||||
filename_case: 0
|
||||
render_drafts: false
|
||||
post_asset_folder: false
|
||||
relative_link: false
|
||||
future: true
|
||||
highlight:
|
||||
enable: true
|
||||
line_number: true
|
||||
auto_detect: false
|
||||
tab_replace:
|
||||
|
||||
# Category & Tag
|
||||
default_category: uncategorized
|
||||
category_map:
|
||||
tag_map:
|
||||
|
||||
# Date / Time format
|
||||
## Hexo uses Moment.js to parse and display date
|
||||
## You can customize the date format as defined in
|
||||
## http://momentjs.com/docs/#/displaying/format/
|
||||
date_format: YYYY-MM-DD
|
||||
time_format: HH:mm:ss
|
||||
|
||||
# Pagination
|
||||
## Set per_page to 0 to disable pagination
|
||||
per_page: 10
|
||||
pagination_dir: page
|
||||
|
||||
|
||||
twitter_username: Cypress_io
|
||||
facebook_username: cypressio
|
||||
github_username: cypress-io
|
||||
|
||||
# Disqus settings
|
||||
# _your_disqus_short_name_
|
||||
disqus_username: cypress-io
|
||||
fb_admins: 909781955804405
|
||||
|
||||
## Algolia Search
|
||||
## https://github.com/LouisBarranqueiro/hexo-algoliasearch
|
||||
algolia:
|
||||
appId: "R9KDA5FMJB"
|
||||
apiKey: "2d1dd6823e46b492c7f0fcfad049ef1e"
|
||||
adminApiKey: "86cb5b345150edcc6750db26fba8bf94"
|
||||
chunkSize: 5000
|
||||
indexName: "cypress"
|
||||
fields:
|
||||
- title
|
||||
- tags
|
||||
- slug
|
||||
- excerpt
|
||||
- excerpt:strip
|
||||
- photos
|
||||
- gallery
|
||||
|
||||
# Extensions
|
||||
## Plugins: https://hexo.io/plugins/
|
||||
## Themes: https://hexo.io/themes/
|
||||
theme: cypress
|
||||
|
||||
node_sass:
|
||||
outputStyle: nested
|
||||
precision: 5
|
||||
sourceComments: false
|
||||
|
||||
## https://github.com/hexojs/hexo-generator-sitemap
|
||||
sitemap:
|
||||
path: sitemap.xml
|
||||
template: ./sitemap_template.xml
|
||||
|
||||
# Deployment
|
||||
## Docs: https://hexo.io/docs/deployment.html
|
||||
deploy:
|
||||
type: git
|
||||
repo: https://github.com/cypress-io/cypress-documentation
|
||||
branch: gh-pages
|
||||
@@ -1,4 +0,0 @@
|
||||
slug: features
|
||||
excerpt: features
|
||||
|
||||
these are features
|
||||
@@ -1,30 +0,0 @@
|
||||
slug: why-test
|
||||
excerpt: Why you should test your code.
|
||||
|
||||
Since you've landed here, hopefully you’re open to the idea that testing code has some benefits. But, maybe you're still weighing the benefits or maybe you just need some fuel to convince your team that testing is worth looking into. Let's go over just a few reasons why you should be testing your code.
|
||||
|
||||
# Invest in testing to:
|
||||
|
||||
:fa-code: **Increase code quality**
|
||||
Writing tests challenges you think more clearly about edge cases and code for them.
|
||||
|
||||
:fa-clock-o: **Save time**
|
||||
Less time is spent finding and tracking down bugs when there are tests that fail automatically when bugs are introduced.
|
||||
|
||||
:fa-sitemap: **Decrease code complexity**
|
||||
Complex code requires being broken into smaller pieces when testing. It also helps you think through how dependencies and input/output is handled.
|
||||
|
||||
:fa-wrench: **Encourage refactoring**
|
||||
Knowing there are tests surrounding the functionality of your code means you can feel more comfortable playing around and refactoring that code.
|
||||
|
||||
:fa-hourglass-start: **Develop faster**
|
||||
There is time up front that goes into planning a test strategy, but over time, velocity will increase.
|
||||
|
||||
:fa-bug: **Reduce regression**
|
||||
Having tests cover your code means that when you add new features, you can see if any existing features behavior changed.
|
||||
|
||||
:fa-smile-o: **Increase confidence**
|
||||
The risk of breaking code increases as your applications complexity grows. Being able to catch regressions makes it more likely that your changes will not inadvertently break things that used to work.
|
||||
|
||||
:fa-file-code-o: **Self-document**
|
||||
Test suites cover the expected behavior of your code and are a great documentation reference.
|
||||
@@ -1,283 +0,0 @@
|
||||
slug: server
|
||||
excerpt: Control the behavior of network requests and responses
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "[Read about Network Requests first.](https://on.cypress.io/guides/network-requests-xhr)",
|
||||
"title": "New to Cypress?"
|
||||
}
|
||||
[/block]
|
||||
|
||||
Use `cy.server` to control the behavior of requests and responses.
|
||||
|
||||
***
|
||||
|
||||
# [cy.server()](#section-default-usage)
|
||||
|
||||
Start a server to begin routing responses to your requests.
|
||||
|
||||
***
|
||||
|
||||
# Options
|
||||
|
||||
Pass in an options object to change the default behavior of `cy.server`.
|
||||
|
||||
**[cy.server(*options* )](#options-usage)**
|
||||
|
||||
`cy.server` takes options that are used for 2 different purposes:
|
||||
|
||||
1. As defaults which are merged into [`cy.route`](https://on.cypress.io/api/route).
|
||||
2. As configuration behavior for *all* requests.
|
||||
|
||||
The following options will be merged in as defaults to [`cy.route`](https://on.cypress.io/api/route)
|
||||
|
||||
Option | Default | Notes
|
||||
--- | --- | ---
|
||||
`delay` | `0` | Default delay for responses
|
||||
`method` | `"GET"` | Default method to match against requests
|
||||
`status` | `200` | Default response Status code
|
||||
`headers` | `null` | Default response Headers
|
||||
`response` | `null` | Default response Body
|
||||
`onRequest` | `undefined` | Default callback function when a request is sent
|
||||
`onResponse` | `undefined` | Default callback function when a response is returned
|
||||
`onAbort` | `undefined` | Default callback function which fires anytime an XHR is aborted
|
||||
|
||||
|
||||
The following options control the behavior of the server affecting all requests:
|
||||
|
||||
Option | Default | Notes
|
||||
--- | --- | ---
|
||||
`enable` | `true` | Pass `false` to disable existing route stubs
|
||||
`force404` | `false` | Forces requests that don't match your routes to be sent back `404`.
|
||||
`urlMatchingOptions` | `{ matchBase: true }` | The default options passed to `minimatch` when using glob strings to match URLs
|
||||
`whitelist` | function | Callback function that whitelists requests from ever being logged or stubbed. By default this matches against asset-like requests such as `.js`, `.jsx`, `.html`, and `.css`
|
||||
|
||||
***
|
||||
|
||||
# Default Usage
|
||||
|
||||
## Start a server
|
||||
|
||||
```javascript
|
||||
cy.server()
|
||||
```
|
||||
|
||||
**After starting a server:**
|
||||
|
||||
- Any request that does not match a `cy.route` will be sent a `404` status code.
|
||||
- Any request that matches the `options.whitelist` function will **NOT** be logged or stubbed. In other words it is "whitelisted" and ignored.
|
||||
- You will see requests named as `(XHR Stub)` or `(XHR)` in the Command Log.
|
||||
|
||||
***
|
||||
|
||||
# Options Usage
|
||||
|
||||
## Change the defaults for upcoming `cy.route` commands
|
||||
|
||||
By default [`cy.route`](https://on.cypress.io/api/route) inherits its options from `cy.server`. Passing any of the following options to server will be inherited:
|
||||
|
||||
- delay
|
||||
- method
|
||||
- status
|
||||
- headers
|
||||
- response
|
||||
- onRequest
|
||||
- onResponse
|
||||
|
||||
```javascript
|
||||
cy
|
||||
.server({
|
||||
method: "POST",
|
||||
delay: 1000,
|
||||
status: 422,
|
||||
response: {}
|
||||
})
|
||||
|
||||
// our route command will now inherit its options
|
||||
// from the server. anything we pass specifically
|
||||
// to route will override the defaults.
|
||||
//
|
||||
// in this example our matching requests will
|
||||
// be delayed 1000ms and have a status of 422
|
||||
// but its response will be what we set in route
|
||||
.route(/users/, {errors: "Name cannot be blank"})
|
||||
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Change the default delay for all routes
|
||||
|
||||
Adding delay can help simulate real world network latency. Normally stubbed responses return in under 20ms. Adding a delay can help you visualize how your application's state reacts to requests that are in flight.
|
||||
|
||||
```javascript
|
||||
// delay each response 1500ms
|
||||
cy.server({delay: 1500})
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Prevent sending 404's to unmatched requests
|
||||
|
||||
If you'd like Cypress to automatically send requests that do *NOT* match routes the following:
|
||||
|
||||
Status | Body | Headers
|
||||
--- | --- | ---
|
||||
`404` | "" | `null`
|
||||
|
||||
Simply set `{force404: true}`
|
||||
|
||||
```javascript
|
||||
cy
|
||||
.server({force404: true})
|
||||
.route(/activities/, "fixture:activities.json")
|
||||
```
|
||||
|
||||
```javascript
|
||||
|
||||
// Application Code
|
||||
|
||||
$(function(){
|
||||
$.get("/activities")
|
||||
|
||||
// this will be sent back 404 since it
|
||||
// does not match any of the cy.routes
|
||||
$.getJSON("/users.json")
|
||||
})
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Change the default response headers for all routes
|
||||
|
||||
When you stub requests, you can automatically control their response headers.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "Cypress automatically sets `Content-Length` and `Content-Type` based on the response body you've stubbed"
|
||||
}
|
||||
[/block]
|
||||
|
||||
This is useful when you want to send back meta data in the headers, such as **pagination** or **token** information.
|
||||
|
||||
```javascript
|
||||
cy
|
||||
.server({
|
||||
headers: {
|
||||
"x-token": "abc-123-foo-bar"
|
||||
}
|
||||
})
|
||||
.route("GET", "/users/1", {id: 1, name: "Amanda"}).as("getUser")
|
||||
.visit("/users/1/profile")
|
||||
.wait("@getUser")
|
||||
.its("responseHeaders")
|
||||
.should("have.property", "x-token", "abc-123-foo-bar") // true
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Application Code
|
||||
|
||||
// lets use the native XHR object
|
||||
var xhr = new XMLHttpRequest
|
||||
|
||||
xhr.open("GET", "/users/1")
|
||||
|
||||
xhr.onload = function(){
|
||||
var token = this.getResponseHeader("x-token")
|
||||
console.log(token) // => abc-123-foo-bar
|
||||
}
|
||||
|
||||
xhr.send()
|
||||
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Change the default whitelisting
|
||||
|
||||
Cypress comes with a `whitelist` function that will filter out any requests that are for static assets like `.html`, `.js`, `.jsx`, `.css`.
|
||||
|
||||
Any request that passes the `whitelist` will be ignored - it will not be logged nor will it be stubbed in any way (even if it matches a specific `cy.route`).
|
||||
|
||||
The idea is that we never went to interfere with static assets that are fetched via AJAX.
|
||||
|
||||
The default whitelist function is:
|
||||
|
||||
```javascript
|
||||
var whitelist = function(xhr){
|
||||
// this function receives the xhr object in question and
|
||||
// will whitelist if its a GET that appears to be a static resource
|
||||
xhr.method === "GET" && /\.(jsx?|html|css)(\?.*)?$/.test(xhr.url)
|
||||
}
|
||||
```
|
||||
|
||||
You can override this function with your own specific logic.
|
||||
|
||||
```javascript
|
||||
cy.server({
|
||||
whitelist: function(xhr){
|
||||
// specify your own function that should return
|
||||
// truthy if you want this xhr to be ignored,
|
||||
// not logged, and not stubbed.
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If you would like to change the default option for **ALL** `cy.server` you [can change this option permanently](#permanently-override-default-server-options).
|
||||
|
||||
***
|
||||
|
||||
## Turn off the server after you've started it
|
||||
|
||||
You can disable all stubbing and its effects and restore to the default behavior as a test is running.
|
||||
|
||||
```javascript
|
||||
cy
|
||||
.server()
|
||||
.route("POST", /users/, {}).as("createUser")
|
||||
|
||||
...
|
||||
|
||||
// this now disables stubbing routes and XHR's
|
||||
// will no longer show up as (XHR Stub) in the
|
||||
// Command Log. However routing aliases can
|
||||
// continue to be used and will continue to
|
||||
// match requests, but will not affect responses
|
||||
.server({enable: false})
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
# Notes
|
||||
|
||||
## Server persists until the next test runs
|
||||
|
||||
Cypress automatically continues to persist the server and routing configuration even after a test ends. This means you can continue to use your application and still benefit from stubbing or other server configuration.
|
||||
|
||||
However between tests, when a new test runs, the previous configuration is restored to a clean state. No configuration will leak between tests.
|
||||
|
||||
***
|
||||
|
||||
## Outstanding requests are automatically aborted between tests
|
||||
|
||||
When a new test runs, any oustanding requests still in flight are automatically aborted. In fact this happens by default whether or not you've even started a `cy.server`.
|
||||
|
||||
***
|
||||
|
||||
## Server can be started before you `cy.visit`
|
||||
|
||||
Oftentimes your application may make initial requests immediately when it loads (such as authenticating a user). Cypress makes it possible to start your server and define routes before a [`cy.visit`](https://on.cypress.io/api/visit). Upon the next visit, the server + routes will be instantly applied before your application loads.
|
||||
|
||||
You can [read more about XHR strategy here](https://on.cypress.io/guides/network-requests-xhr).
|
||||
|
||||
***
|
||||
|
||||
# Related
|
||||
|
||||
- [route](https://on.cypress.io/api/route)
|
||||
- [wait](https://on.cypress.io/api/wait)
|
||||
- [request](https://on.cypress.io/api/request)
|
||||
- [visit](https://on.cypress.io/api/visit)
|
||||
- [Network Requests](https://on.cypress.io/guides/network-requests-xhr)
|
||||
|
||||
+19
-7
@@ -3,18 +3,30 @@
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"hexo": {
|
||||
"version": "3.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 0",
|
||||
"upload": "readmeio-sync upload",
|
||||
"clean": "readmeio-sync clean-remote",
|
||||
"add-command": "node ./scripts/add-command.js",
|
||||
"remove-command": "node ./scripts/remove-command.js"
|
||||
"start": "hexo server"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"colors": "^1.1.2",
|
||||
"glob": "^7.0.3",
|
||||
"readmeio-sync": "cypress-io/readmeio-sync#fbd703d57d872093ea7cbf7d0c5b9dd1483860a1"
|
||||
"glob": "^7.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"hexo": "^3.2.0",
|
||||
"hexo-algoliasearch": "^0.2.1",
|
||||
"hexo-deployer-git": "^0.2.0",
|
||||
"hexo-generator-archive": "^0.1.4",
|
||||
"hexo-generator-category": "^0.1.3",
|
||||
"hexo-generator-index": "^0.2.0",
|
||||
"hexo-generator-sitemap": "^1.1.2",
|
||||
"hexo-generator-tag": "^0.2.0",
|
||||
"hexo-renderer-marked": "^0.2.10",
|
||||
"hexo-renderer-scss": "^1.0.2",
|
||||
"hexo-server": "^0.2.0",
|
||||
"lunr": "^2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head prefix="og: http://ogp.me/ns#">
|
||||
<meta charset="utf-8">
|
||||
<title>Documentation | Cypress.io</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- Canonical links -->
|
||||
<link rel="canonical" href="http://yoursite.com/docs/index.html">
|
||||
<!-- Alternative links -->
|
||||
|
||||
|
||||
<link rel="alternative" hreflang="en" href="http://yoursite.com/docs/index.html">
|
||||
|
||||
|
||||
<!-- Icon -->
|
||||
<link rel="icon" type="image/x-icon" href="/icon/favicon.ico" sizes="16x16" />
|
||||
|
||||
<!-- CSS -->
|
||||
<!-- build:css build/css/cypress.css -->
|
||||
<link rel="stylesheet" href="/css/cypress.css">
|
||||
<!-- endbuild -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:300,300i,400,400i,500,500i,600,600i" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css">
|
||||
<!-- RSS -->
|
||||
<link rel="alternate" href="/atom.xml" title="Cypress.io">
|
||||
<!-- Open Graph -->
|
||||
<meta name="description" content="Welcome to the Hexo documentation. If you encounter any problems when using Hexo, have a look at the troubleshooting guide, raise an issue on GitHub or start a topic on the Google Group. What is Hexo">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Documentation">
|
||||
<meta property="og:url" content="http://yoursite.com/docs/index.html">
|
||||
<meta property="og:site_name" content="Cypress.io">
|
||||
<meta property="og:description" content="Welcome to the Hexo documentation. If you encounter any problems when using Hexo, have a look at the troubleshooting guide, raise an issue on GitHub or start a topic on the Google Group. What is Hexo">
|
||||
<meta property="og:updated_time" content="2017-04-17T16:57:24.000Z">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:title" content="Documentation">
|
||||
<meta name="twitter:description" content="Welcome to the Hexo documentation. If you encounter any problems when using Hexo, have a look at the troubleshooting guide, raise an issue on GitHub or start a topic on the Google Group. What is Hexo">
|
||||
<meta property="fb:admins" content="909781955804405">
|
||||
<!-- Google Analytics -->
|
||||
|
||||
<!-- Github Button -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<header id="header" class="wrapper">
|
||||
<div id="header-inner" class="inner">
|
||||
<h1 id="logo-wrap">
|
||||
<a href="/" id="logo">Cypress</a>
|
||||
</h1>
|
||||
<nav id="main-nav">
|
||||
<a href="/docs/" class="main-nav-link">Docs</a>
|
||||
<a href="https://github.com/" class="main-nav-link"><i class="fa fa-github-alt"></i></a>
|
||||
<div id="search-input-wrap">
|
||||
<div id="search-input-icon">
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
<input type="search" id="search-input" placeholder="Search...">
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<a id="mobile-nav-toggle">
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="content-wrap">
|
||||
<div id="content" class="wrapper">
|
||||
<div id="content-inner">
|
||||
<article class="article-container" itemscope itemtype="http://schema.org/Article">
|
||||
<div class="article-inner">
|
||||
<div class="article">
|
||||
<div class="inner">
|
||||
<header class="article-header">
|
||||
<h1 class="article-title" itemprop="name">Documentation</h1>
|
||||
<a href="https://github.com/cypress-io/cypress-documentation/edit/master/source/docs/index.md" class="article-edit-link" title="Improve this doc"><i class="fa fa-pencil"></i></a>
|
||||
</header>
|
||||
<div class="article-content" itemprop="articleBody">
|
||||
<p>Welcome to the Hexo documentation. If you encounter any problems when using Hexo, have a look at the <a href="troubleshooting.html">troubleshooting guide</a>, raise an issue on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="external">GitHub</a> or start a topic on the <a href="https://groups.google.com/group/hexo" target="_blank" rel="external">Google Group</a>.</p>
|
||||
<h2 id="What-is-Hexo" class="article-heading"><a href="#What-is-Hexo" class="headerlink" title="What is Hexo?"></a>What is Hexo?<a class="article-anchor" href="#What-is-Hexo" aria-hidden="true"></a></h2><p>Hexo is a fast, simple and powerful blog framework. You write posts in <a href="http://daringfireball.net/projects/markdown/" target="_blank" rel="external">Markdown</a> (or other languages) and Hexo generates static files with a beautiful theme in seconds.</p>
|
||||
<h2 id="Installation" class="article-heading"><a href="#Installation" class="headerlink" title="Installation"></a>Installation<a class="article-anchor" href="#Installation" aria-hidden="true"></a></h2><p>It only takes a few minutes to set up Hexo. If you encounter a problem and can’t find the solution here, please <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="external">submit a GitHub issue</a> and I’ll try to solve it.</p>
|
||||
<h3 id="Requirements" class="article-heading"><a href="#Requirements" class="headerlink" title="Requirements"></a>Requirements<a class="article-anchor" href="#Requirements" aria-hidden="true"></a></h3><p>Installing Hexo is quite easy. However, you do need to have a couple of other things installed first:</p>
|
||||
<ul>
|
||||
<li><a href="http://nodejs.org/" target="_blank" rel="external">Node.js</a></li>
|
||||
<li><a href="http://git-scm.com/" target="_blank" rel="external">Git</a></li>
|
||||
</ul>
|
||||
<p>If your computer already has these, congratulations! Just install Hexo with npm:</p>
|
||||
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g hexo-cli</div></pre></td></tr></table></figure>
|
||||
<p>If not, please follow the following instructions to install all the requirements.</p>
|
||||
<h3 id="Install-Git" class="article-heading"><a href="#Install-Git" class="headerlink" title="Install Git"></a>Install Git<a class="article-anchor" href="#Install-Git" aria-hidden="true"></a></h3><ul>
|
||||
<li>Windows: Download & install <a href="https://git-scm.com/download/win" target="_blank" rel="external">git</a>.</li>
|
||||
<li>Mac: Install it with <a href="http://mxcl.github.com/homebrew/" target="_blank" rel="external">Homebrew</a>, <a href="http://www.macports.org/" target="_blank" rel="external">MacPorts</a> or <a href="http://sourceforge.net/projects/git-osx-installer/" target="_blank" rel="external">installer</a>.</li>
|
||||
<li>Linux (Ubuntu, Debian): <code>sudo apt-get install git-core</code></li>
|
||||
<li>Linux (Fedora, Red Hat, CentOS): <code>sudo yum install git-core</code></li>
|
||||
</ul>
|
||||
<h3 id="Install-Node-js" class="article-heading"><a href="#Install-Node-js" class="headerlink" title="Install Node.js"></a>Install Node.js<a class="article-anchor" href="#Install-Node-js" aria-hidden="true"></a></h3><p>The best way to install Node.js is with <a href="https://github.com/creationix/nvm" target="_blank" rel="external">nvm</a>.</p>
|
||||
<p>cURL:</p>
|
||||
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | sh</div></pre></td></tr></table></figure>
|
||||
<p>Wget:</p>
|
||||
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | sh</div></pre></td></tr></table></figure>
|
||||
<p>Once nvm is installed, restart the terminal and run the following command to install Node.js.</p>
|
||||
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ nvm install stable</div></pre></td></tr></table></figure>
|
||||
<p>Alternatively, download and run <a href="http://nodejs.org/" target="_blank" rel="external">the installer</a>.</p>
|
||||
<h3 id="Install-Hexo" class="article-heading"><a href="#Install-Hexo" class="headerlink" title="Install Hexo"></a>Install Hexo<a class="article-anchor" href="#Install-Hexo" aria-hidden="true"></a></h3><p>Once all the requirements are installed, you can install Hexo with npm.</p>
|
||||
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g hexo-cli</div></pre></td></tr></table></figure>
|
||||
|
||||
</div>
|
||||
<footer class="article-footer">
|
||||
<time class="article-footer-updated" datetime="2017-04-17T16:57:24.000Z" itemprop="dateModified">Last updated: 2017-04-17</time>
|
||||
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<aside id="article-toc" role="navigation">
|
||||
<div id="article-toc-inner">
|
||||
<strong class="sidebar-title">Contents</strong>
|
||||
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#What-is-Hexo"><span class="toc-text">What is Hexo?</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Installation"><span class="toc-text">Installation</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Requirements"><span class="toc-text">Requirements</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Install-Git"><span class="toc-text">Install Git</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Install-Node-js"><span class="toc-text">Install Node.js</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Install-Hexo"><span class="toc-text">Install Hexo</span></a></li></ol></li></ol>
|
||||
<a href="#" id="article-toc-top">Back to Top</a>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</article>
|
||||
<aside id="sidebar" role="navigation">
|
||||
<div class="inner"><strong class="sidebar-title">Getting Started</strong><a href="index.html" class="sidebar-link current">Overview</a></div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer id="footer" class="wrapper">
|
||||
<div class="inner">
|
||||
<div id="footer-copyright">
|
||||
© 2017 <a href="https://cypress.io" target="_blank">Cypress.io</a>
|
||||
</div>
|
||||
<div id="footer-links">
|
||||
<a href="https://twitter.com/" class="footer-link" target="_blank"><i class="fa fa-twitter"></i></a>
|
||||
<a href="https://github.com/" class="footer-link" target="_blank"><i class="fa fa-github-alt"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div id="mobile-nav-dimmer"></div>
|
||||
<nav id="mobile-nav">
|
||||
<div id="mobile-nav-inner">
|
||||
<ul id="mobile-nav-list">
|
||||
<a href="/docs/" class="mobile-nav-link">Docs</a>
|
||||
<li class="mobile-nav-item">
|
||||
<a href="https://github.com/" class="mobile-nav-link" rel="external" target="_blank">GitHub</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<strong class="mobile-nav-title">Getting Started</strong><a href="index.html" class="mobile-nav-link current">Overview</a>
|
||||
|
||||
</div>
|
||||
<div id="mobile-lang-select-wrap">
|
||||
<span id="mobile-lang-select-label"><i class="fa fa-globe"></i><span>English</span></span>
|
||||
<select id="mobile-lang-select" data-canonical="docs/index.html">
|
||||
|
||||
<option value="en" selected>English</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Scripts -->
|
||||
<!-- build:js build/js/main.js -->
|
||||
|
||||
<script src="/js/scrollingelement.js"></script>
|
||||
<script src="/js/toc.js"></script>
|
||||
<script src="/js/mobile_nav.js"></script>
|
||||
<!-- endbuild -->
|
||||
<script src="https://cdn.jsdelivr.net/retinajs/1.3.0/retina.min.js" async></script>
|
||||
|
||||
<!-- Algolia -->
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1,15 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
function changeLang(){
|
||||
var lang = this.value;
|
||||
var canonical = this.dataset.canonical;
|
||||
if (lang === 'en') lang = '';
|
||||
if (lang) lang += '/';
|
||||
|
||||
location.href = '/' + lang + canonical;
|
||||
}
|
||||
|
||||
document.getElementById('lang-select').addEventListener('change', changeLang);
|
||||
document.getElementById('mobile-lang-select').addEventListener('change', changeLang);
|
||||
})();
|
||||
@@ -0,0 +1,23 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
var navToggle = document.getElementById('mobile-nav-toggle');
|
||||
var container = document.getElementById('container');
|
||||
var dimmer = document.getElementById('mobile-nav-dimmer');
|
||||
var CLASS_NAME = 'mobile-nav-on';
|
||||
if (!navToggle) return;
|
||||
|
||||
navToggle.addEventListener('click', function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
body.classList.toggle(CLASS_NAME);
|
||||
});
|
||||
|
||||
dimmer.addEventListener('click', function(e){
|
||||
if (!body.classList.contains(CLASS_NAME)) return;
|
||||
|
||||
e.preventDefault();
|
||||
body.classList.remove(CLASS_NAME);
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,112 @@
|
||||
/*! https://mths.be/scrollingelement v1.5.2 by @diegoperini & @mathias | MIT license */
|
||||
if (!('scrollingElement' in document)) (function() {
|
||||
|
||||
function computeStyle(element) {
|
||||
if (window.getComputedStyle) {
|
||||
// Support Firefox < 4 which throws on a single parameter.
|
||||
return getComputedStyle(element, null);
|
||||
}
|
||||
// Support Internet Explorer < 9.
|
||||
return element.currentStyle;
|
||||
}
|
||||
|
||||
function isBodyElement(element) {
|
||||
// The `instanceof` check gives the correct result for e.g. `body` in a
|
||||
// non-HTML namespace.
|
||||
if (window.HTMLBodyElement) {
|
||||
return element instanceof HTMLBodyElement;
|
||||
}
|
||||
// Fall back to a `tagName` check for old browsers.
|
||||
return /body/i.test(element.tagName);
|
||||
}
|
||||
|
||||
function getNextBodyElement(frameset) {
|
||||
// We use this function to be correct per spec in case `document.body` is
|
||||
// a `frameset` but there exists a later `body`. Since `document.body` is
|
||||
// a `frameset`, we know the root is an `html`, and there was no `body`
|
||||
// before the `frameset`, so we just need to look at siblings after the
|
||||
// `frameset`.
|
||||
var current = frameset;
|
||||
while (current = current.nextSibling) {
|
||||
if (current.nodeType == 1 && isBodyElement(current)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
// No `body` found.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Note: standards mode / quirks mode can be toggled at runtime via
|
||||
// `document.write`.
|
||||
var isCompliantCached;
|
||||
var isCompliant = function() {
|
||||
var isStandardsMode = /^CSS1/.test(document.compatMode);
|
||||
if (!isStandardsMode) {
|
||||
// In quirks mode, the result is equivalent to the non-compliant
|
||||
// standards mode behavior.
|
||||
return false;
|
||||
}
|
||||
if (isCompliantCached === void 0) {
|
||||
// When called for the first time, check whether the browser is
|
||||
// standard-compliant, and cache the result.
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.height = '1px';
|
||||
(document.body || document.documentElement || document).appendChild(iframe);
|
||||
var doc = iframe.contentWindow.document;
|
||||
doc.write('<!DOCTYPE html><div style="height:9999em">x</div>');
|
||||
doc.close();
|
||||
isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight;
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
}
|
||||
return isCompliantCached;
|
||||
};
|
||||
|
||||
function isRendered(style) {
|
||||
return style.display != 'none' && !(style.visibility == 'collapse' &&
|
||||
/^table-(.+-group|row|column)$/.test(style.display));
|
||||
}
|
||||
|
||||
function isScrollable(body) {
|
||||
// A `body` element is scrollable if `body` and `html` both have
|
||||
// non-`visible` overflow and are both being rendered.
|
||||
var bodyStyle = computeStyle(body);
|
||||
var htmlStyle = computeStyle(document.documentElement);
|
||||
return bodyStyle.overflow != 'visible' && htmlStyle.overflow != 'visible' &&
|
||||
isRendered(bodyStyle) && isRendered(htmlStyle);
|
||||
}
|
||||
|
||||
var scrollingElement = function() {
|
||||
if (isCompliant()) {
|
||||
return document.documentElement;
|
||||
}
|
||||
var body = document.body;
|
||||
// Note: `document.body` could be a `frameset` element, or `null`.
|
||||
// `tagName` is uppercase in HTML, but lowercase in XML.
|
||||
var isFrameset = body && !/body/i.test(body.tagName);
|
||||
body = isFrameset ? getNextBodyElement(body) : body;
|
||||
// If `body` is itself scrollable, it is not the `scrollingElement`.
|
||||
return body && isScrollable(body) ? null : body;
|
||||
};
|
||||
|
||||
if (Object.defineProperty) {
|
||||
// Support modern browsers that lack a native implementation.
|
||||
Object.defineProperty(document, 'scrollingElement', {
|
||||
'get': scrollingElement
|
||||
});
|
||||
} else if (document.__defineGetter__) {
|
||||
// Support Firefox ≤ 3.6.9, Safari ≤ 4.1.3.
|
||||
document.__defineGetter__('scrollingElement', scrollingElement);
|
||||
} else {
|
||||
// IE ≤ 4 lacks `attachEvent`, so it only gets this one assignment. IE ≤ 7
|
||||
// gets it too, but the value is updated later (see `propertychange`).
|
||||
document.scrollingElement = scrollingElement();
|
||||
document.attachEvent && document.attachEvent('onpropertychange', function() {
|
||||
// This is for IE ≤ 7 only.
|
||||
// A `propertychange` event fires when `<body>` is parsed because
|
||||
// `document.activeElement` then changes.
|
||||
if (window.event.propertyName == 'activeElement') {
|
||||
document.scrollingElement = scrollingElement();
|
||||
}
|
||||
});
|
||||
}
|
||||
}());
|
||||
@@ -0,0 +1,31 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var header = document.getElementById('header');
|
||||
var toc = document.getElementById('article-toc');
|
||||
var tocTop = document.getElementById('article-toc-top');
|
||||
var headerHeight = header.clientHeight;
|
||||
|
||||
if (!toc) return;
|
||||
|
||||
function updateSidebarPosition(){
|
||||
var scrollTop = document.scrollingElement.scrollTop;
|
||||
|
||||
if (scrollTop > headerHeight){
|
||||
toc.classList.add('fixed');
|
||||
} else {
|
||||
toc.classList.remove('fixed');
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function(){
|
||||
window.requestAnimationFrame(updateSidebarPosition);
|
||||
});
|
||||
|
||||
updateSidebarPosition();
|
||||
|
||||
tocTop.addEventListener('click', function(e){
|
||||
e.preventDefault();
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
|
||||
<url>
|
||||
<loc>http://yoursite.com/docs/index.html</loc>
|
||||
|
||||
<lastmod>2017-04-17T16:57:24.000Z</lastmod>
|
||||
|
||||
</url>
|
||||
|
||||
</urlset>
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: {{ title }}
|
||||
tags:
|
||||
---
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: {{ title }}
|
||||
date: {{ date }}
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: {{ title }}
|
||||
date: {{ date }}
|
||||
tags:
|
||||
---
|
||||
@@ -1,25 +0,0 @@
|
||||
var colors = require('colors/safe');
|
||||
var util = require('./lib/util');
|
||||
|
||||
var newCommandName = util.getCommandNameFromArgs();
|
||||
|
||||
util.getCommands(function (commands) {
|
||||
var commandNames = commands.map(function (command) { return command.name; }).join();
|
||||
if (commandNames.indexOf(newCommandName) > -1) {
|
||||
console.log(colors.red.bold('Command "' + newCommandName + '" already exists'));
|
||||
return;
|
||||
}
|
||||
|
||||
var updatedCommands = commands.concat([{ name: newCommandName }]).sort(util.sortCommands);
|
||||
updatedCommands.forEach(function (command, index) {
|
||||
if (command.path) {
|
||||
util.updateCommand(command, index);
|
||||
} else {
|
||||
util.addCommand(command, index, commands);
|
||||
}
|
||||
});
|
||||
|
||||
if (!util.isDryRun()) {
|
||||
console.log(colors.green('\nAdded file for command "' + newCommandName + '" and renamed files accordingly\n'));
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
'use strict';
|
||||
|
||||
var pathFn = require('path');
|
||||
var _ = require('lodash');
|
||||
var url = require('url');
|
||||
var cheerio = require('cheerio');
|
||||
var lunr = require('lunr');
|
||||
|
||||
var localizedPath = ['docs', 'api'];
|
||||
|
||||
function startsWith(str, start){
|
||||
return str.substring(0, start.length) === start;
|
||||
}
|
||||
|
||||
hexo.extend.helper.register('page_nav', function(){
|
||||
var type = this.page.canonical_path.split('/')[0];
|
||||
var sidebar = this.site.data.sidebar[type];
|
||||
var path = pathFn.basename(this.path);
|
||||
var list = {};
|
||||
var prefix = 'sidebar.' + type + '.';
|
||||
|
||||
for (var i in sidebar){
|
||||
for (var j in sidebar[i]){
|
||||
list[sidebar[i][j]] = j;
|
||||
}
|
||||
}
|
||||
|
||||
var keys = Object.keys(list);
|
||||
var index = keys.indexOf(path);
|
||||
var result = '';
|
||||
|
||||
if (index > 0){
|
||||
result += '<a href="' + keys[index - 1] + '" class="article-footer-prev" title="' + this.__(prefix + list[keys[index - 1]]) + '">' +
|
||||
'<i class="fa fa-chevron-left"></i><span>' + this.__('page.prev') + '</span></a>';
|
||||
}
|
||||
|
||||
if (index < keys.length - 1){
|
||||
result += '<a href="' + keys[index + 1] + '" class="article-footer-next" title="' + this.__(prefix + list[keys[index + 1]]) + '">' +
|
||||
'<span>' + this.__('page.next') + '</span><i class="fa fa-chevron-right"></i></a>';
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('doc_sidebar', function(className){
|
||||
var type = this.page.canonical_path.split('/')[0];
|
||||
var sidebar = this.site.data.sidebar[type];
|
||||
var path = pathFn.basename(this.path);
|
||||
var result = '';
|
||||
var self = this;
|
||||
var prefix = 'sidebar.' + type + '.';
|
||||
|
||||
_.each(sidebar, function(menu, title){
|
||||
result += '<strong class="' + className + '-title">' + self.__(prefix + title) + '</strong>';
|
||||
|
||||
_.each(menu, function(link, text){
|
||||
var itemClass = className + '-link';
|
||||
if (link === path) itemClass += ' current';
|
||||
|
||||
result += '<a href="' + link + '" class="' + itemClass + '">' + self.__(prefix + text) + '</a>';
|
||||
})
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('header_menu', function(className){
|
||||
var menu = this.site.data.menu;
|
||||
var result = '';
|
||||
var self = this;
|
||||
var lang = this.page.lang;
|
||||
var isEnglish = lang === 'en';
|
||||
|
||||
_.each(menu, function(path, title){
|
||||
if (!isEnglish && ~localizedPath.indexOf(title)) path = lang + path;
|
||||
|
||||
result += '<a href="' + self.url_for(path) + '" class="' + className + '-link">' + self.__('menu.' + title) + '</a>';
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('canonical_url', function(lang){
|
||||
var path = this.page.canonical_path;
|
||||
if (lang && lang !== 'en') path = lang + '/' + path;
|
||||
|
||||
return this.config.url + '/' + path;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('url_for_lang', function(path){
|
||||
var lang = this.page.lang;
|
||||
var url = this.url_for(path);
|
||||
|
||||
if (lang !== 'en' && url[0] === '/') url = '/' + lang + url;
|
||||
|
||||
return url;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('raw_link', function(path){
|
||||
return 'https://github.com/cypress-io/cypress-documentation/edit/master/source/' + path;
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('page_anchor', function(str){
|
||||
var $ = cheerio.load(str, {decodeEntities: false});
|
||||
var headings = $('h1, h2, h3, h4, h5, h6');
|
||||
|
||||
if (!headings.length) return str;
|
||||
|
||||
headings.each(function(){
|
||||
var id = $(this).attr('id');
|
||||
|
||||
$(this)
|
||||
.addClass('article-heading')
|
||||
.append('<a class="article-anchor" href="#' + id + '" aria-hidden="true"></a>');
|
||||
});
|
||||
|
||||
return $.html();
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('lunr_index', function(data){
|
||||
var index = lunr(function(){
|
||||
this.field('name', {boost: 10});
|
||||
this.field('tags', {boost: 50});
|
||||
this.field('description');
|
||||
this.ref('id');
|
||||
});
|
||||
|
||||
_.sortBy(data, 'name').forEach(function(item, i){
|
||||
index.add(_.assign({id: i}, item));
|
||||
});
|
||||
|
||||
return JSON.stringify(index.toJSON());
|
||||
});
|
||||
|
||||
hexo.extend.helper.register('canonical_path_for_nav', function(){
|
||||
var path = this.page.canonical_path;
|
||||
|
||||
if (startsWith(path, 'docs/') || startsWith(path, 'api/')){
|
||||
return path;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
// hexo.extend.helper.register('lang_name', function(lang){
|
||||
// var data = this.site.data.languages[lang];
|
||||
// return data.name || data;
|
||||
// });
|
||||
|
||||
hexo.extend.helper.register('disqus_lang', function(){
|
||||
var lang = this.page.lang;
|
||||
var data = this.site.data.languages[lang];
|
||||
|
||||
return data.disqus_lang || lang;
|
||||
});
|
||||
@@ -1,101 +0,0 @@
|
||||
var colors = require('colors');
|
||||
var glob = require('glob');
|
||||
var fs = require('fs');
|
||||
|
||||
var commandNameRe = /\d{1,2}-(\w+)\.md$/;
|
||||
var indexRe = /(\d{1,2})(-\w+\.md)$/;
|
||||
|
||||
var dryRun = isDryRun();
|
||||
|
||||
if (dryRun) {
|
||||
console.log(colors.cyan('Dry Run\n'));
|
||||
}
|
||||
|
||||
function getCommandNameFromArgs () {
|
||||
return process.argv[2];
|
||||
}
|
||||
|
||||
function isDryRun () {
|
||||
return process.argv[3] === '--dry-run';
|
||||
}
|
||||
|
||||
function getCommands (callback) {
|
||||
glob('cypress/v1.0/documentation/*Commands/*.md', {}, function (err, filePaths) {
|
||||
if (err) throw err;
|
||||
|
||||
var commands = filePaths.map(function (filePath) {
|
||||
return {
|
||||
path: filePath,
|
||||
name: getCommandNameFromPath(filePath),
|
||||
};
|
||||
});
|
||||
callback(commands);
|
||||
});
|
||||
}
|
||||
|
||||
function getCommandNameFromPath (filePath) {
|
||||
var match = filePath.match(commandNameRe);
|
||||
return match[1];
|
||||
}
|
||||
|
||||
function replaceCommandIndex (filePath, index) {
|
||||
return filePath.replace(indexRe, index + '$2');
|
||||
}
|
||||
|
||||
function sortCommands (a, b) {
|
||||
if(a.name < b.name) return -1;
|
||||
if(a.name > b.name) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function commandsBasePath (commands) {
|
||||
var exampleCommandPath = commands[0].path;
|
||||
return exampleCommandPath.replace(/\d{1,2}(-\w+\.md)$/, '');
|
||||
}
|
||||
|
||||
function updateCommand (command, index) {
|
||||
var newPath = replaceCommandIndex(command.path, index);
|
||||
if (command.path === newPath) return;
|
||||
if (dryRun) {
|
||||
console.log(command.path + ' -> ' + newPath);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.rename(command.path, newPath, function (err) {
|
||||
if (err) console.log(colors.red.bold('Error occurred while renaming file: ' + err));
|
||||
});
|
||||
}
|
||||
|
||||
function addCommand (command, index, commands) {
|
||||
var newPath = commandsBasePath(commands) + index + '-' + command.name + '.md';
|
||||
if (dryRun) {
|
||||
console.log(colors.green('Add file: ', newPath));
|
||||
return;
|
||||
}
|
||||
|
||||
fs.writeFile(newPath, '', function (err) {
|
||||
if (err) console.log(colors.red.bold('Error occurred while creating file: ' + err));
|
||||
});
|
||||
}
|
||||
|
||||
function removeCommand (commandName, commands) {
|
||||
var command = commands.filter(function (command) { return command.name === commandName; })[0];
|
||||
if (dryRun) {
|
||||
console.log(colors.red('Remove file: ', command.path));
|
||||
return;
|
||||
}
|
||||
|
||||
fs.unlink(command.path, function (err) {
|
||||
if (err) console.log(colors.red.bold('Error occurred while removing file: ' + err));
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addCommand: addCommand,
|
||||
getCommandNameFromArgs: getCommandNameFromArgs,
|
||||
getCommands: getCommands,
|
||||
isDryRun: isDryRun,
|
||||
removeCommand: removeCommand,
|
||||
sortCommands: sortCommands,
|
||||
updateCommand: updateCommand,
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
var colors = require('colors/safe');
|
||||
var util = require('./lib/util');
|
||||
|
||||
var commandToRemove = util.getCommandNameFromArgs();
|
||||
|
||||
util.getCommands(function (commands) {
|
||||
var commandNames = commands.map(function (command) { return command.name; }).join();
|
||||
if (commandNames.indexOf(commandToRemove) === -1) {
|
||||
console.log(colors.red.bold('Command "' + commandToRemove + '" does not exist'));
|
||||
return;
|
||||
}
|
||||
|
||||
var updatedCommands = commands.filter(function (command) {
|
||||
return command.name !== commandToRemove;
|
||||
}).sort(util.sortCommands);
|
||||
|
||||
util.removeCommand(commandToRemove, commands);
|
||||
updatedCommands.forEach(util.updateCommand);
|
||||
|
||||
if (!util.isDryRun()) {
|
||||
console.log(colors.green('\nRemoved file for command "' + commandToRemove + '" and renamed files accordingly\n'));
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
en: English
|
||||
@@ -0,0 +1,2 @@
|
||||
docs: /docs/
|
||||
api: /api/
|
||||
@@ -0,0 +1,129 @@
|
||||
docs:
|
||||
welcome:
|
||||
intro: index.html
|
||||
our_goals: our_goals.html
|
||||
getting_started:
|
||||
installing_and_running: installing_and_running.html
|
||||
writing_your_first_test: writing_your_first_test.html
|
||||
using_the_cypress_runner: using_the_cypress_runner.html
|
||||
examples:
|
||||
list_of_example_apps: list_of_example_apps.html
|
||||
list_of_example_recipes: list_of_example_recipes.html
|
||||
dashboard:
|
||||
features: dashboard-features.html
|
||||
projects: dashboard-projects.html
|
||||
runs: dashboard-runs.html
|
||||
organizations: dashboard-organizations.html
|
||||
guides:
|
||||
configuration: configuration.html
|
||||
issuing_commands: issuing_commands.html
|
||||
finding_elements: finding_elements.html
|
||||
making_assertions: making_assertions.html
|
||||
network_requests: network_requests.html
|
||||
continuous_integration: continuous_integration.html
|
||||
environment_variables: environment_variables.html
|
||||
stubs_spies_and_clocks: stubs_spies_and_clocks.html
|
||||
using_aliases: using_aliases.html
|
||||
creating_fixtures: creating_fixtures.html
|
||||
screenshots_and_videos: screenshots_and_videos.html
|
||||
bundled_tools: bundled_tools.html
|
||||
reporters: reporters.html
|
||||
references:
|
||||
cli_tool: cli_tool.html
|
||||
error_messages: error_messages.html
|
||||
anti-patterns: anti-patterns.html
|
||||
known_issues: known_issues.html
|
||||
web_security: web_security.html
|
||||
browser_management: browser_management.html
|
||||
userland_extensions: userland_extensions.html
|
||||
|
||||
api:
|
||||
welcome:
|
||||
api: index.html
|
||||
commands:
|
||||
and: and.html
|
||||
as: as.html
|
||||
blur: blur.html
|
||||
check: check.html
|
||||
children: children.html
|
||||
clear: clear.html
|
||||
clear_cookie: clear_cookie.html
|
||||
clear_cookies: clear_cookies.html
|
||||
clear_local_storage: clear_local_storage.html
|
||||
click: click.html
|
||||
clock: clock.html
|
||||
closest: closest.html
|
||||
contains: contains.html
|
||||
dblclick: dblclick.html
|
||||
debug: debug.html
|
||||
document: document.html
|
||||
each: each.html
|
||||
end: end.html
|
||||
eq: eq.html
|
||||
exec: exec.html
|
||||
filter: filter.html
|
||||
find: find.html
|
||||
first: first.html
|
||||
fixture: fixture.html
|
||||
focus: focus.html
|
||||
focused: focused.html
|
||||
get: get.html
|
||||
get_cookie: get_cookie.html
|
||||
get_cookies: get_cookies.html
|
||||
go: go.html
|
||||
hash: hash.html
|
||||
hover: hover.html
|
||||
invoke: invoke.html
|
||||
its: its.html
|
||||
last: last.html
|
||||
location: location.html
|
||||
log: log.html
|
||||
next: next.html
|
||||
next_all: next_all.html
|
||||
next_until: next_until.html
|
||||
not: not.html
|
||||
parent: parent.html
|
||||
parents: parents.html
|
||||
parents_until: parents_until.html
|
||||
read_file: read_file.html
|
||||
reload: reload.html
|
||||
request: request.html
|
||||
root: root.html
|
||||
route: route.html
|
||||
screenshot: screenshot.html
|
||||
select: select.html
|
||||
server: server.html
|
||||
set_cookie: set_cookie.html
|
||||
should: should.html
|
||||
siblings: siblings.html
|
||||
spread: spread.html
|
||||
spy: spy.html
|
||||
stub: stub.html
|
||||
submit: submit.html
|
||||
then: then.html
|
||||
tick: tick.html
|
||||
title: title.html
|
||||
type: type.html
|
||||
uncheck: uncheck.html
|
||||
url: url.html
|
||||
viewport: viewport.html
|
||||
visit: visit.html
|
||||
wait: wait.html
|
||||
window: window.html
|
||||
within: within.html
|
||||
wrap: wrap.html
|
||||
write_file: write_file.html
|
||||
utilities:
|
||||
_: _.html
|
||||
$: $.html
|
||||
minimatch: minimatch.html
|
||||
blob: blob.html
|
||||
promise: promise.html
|
||||
cypress_api:
|
||||
config: config.html
|
||||
env: env.html
|
||||
cypress_commands: commands.html
|
||||
cookies: cookies.html
|
||||
dom: dom.html
|
||||
cypress_server: server.html
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
title: API
|
||||
---
|
||||
@@ -0,0 +1,86 @@
|
||||
title: Using the Cypress Runner
|
||||
---
|
||||
|
||||
# What is the Dashboard?
|
||||
|
||||

|
||||
|
||||
[The Dashboard](https://on.cypress.io/dashboard) is a Cypress service that gives you access to tests you've recorded - typically when running Cypress tests from your CI provider. The Dashboard provides you insight into what happened during your run.
|
||||
|
||||
**The Dashboard allows you to:**
|
||||
|
||||
- See the number of failed, pending and passing tests
|
||||
- Get the entire stack trace of failed tests
|
||||
- View screenshots taken when tests fail and when using [`cy.screenshot`](https://on.cypress.io/api/screenshot)
|
||||
- Watch a video of your entire test run or a clip at the point of test failure.
|
||||
- Manage who has access to your run data
|
||||
|
||||
Additionally we've integrated the dashboard into the Cypress [Desktop Application](https://on.cypress.io/guides/installing-and-running). This means you'll see the test runs in the Tunes tab from within every project.
|
||||
|
||||

|
||||
|
||||
***
|
||||
|
||||
## Example Projects
|
||||
|
||||
Once you're logged into the [Dashboard](https://on.cypress.io/dashboard) you can view any [public project](https://on.cypress.io/what-is-project-access).
|
||||
|
||||
Here are some of our own public projects you can look at:
|
||||
|
||||
- [cypress-core-desktop-gui](https://dashboard.cypress.io/#/projects/fas5qd)
|
||||
- [cypress-example-recipes](https://dashboard.cypress.io/#/projects/6p53jw)
|
||||
- [cypress-example-kitchensink](https://dashboard.cypress.io/#/projects/4b7344)
|
||||
- [cypress-example-todomvc](https://dashboard.cypress.io/#/projects/245obj)
|
||||
- [cypress-example-piechopper](https://dashboard.cypress.io/#/projects/fuduzp)
|
||||
|
||||
***
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
## How do I record my tests?
|
||||
|
||||
1. First [setup your project to record](https://on.cypress.io/recording-project-runs).
|
||||
2. Then [record your runs](https://on.cypress.io/how-do-i-record-runs).
|
||||
|
||||
After recording your tests, you will see them in the Dashboard and in the Desktop Application.
|
||||
|
||||
***
|
||||
|
||||
## How is this different than CI?
|
||||
|
||||
Cypress is **complimentary** to your CI provider, and plays a completely different role.
|
||||
|
||||
It doesn't replace nor change anything related to CI. You will simply run Cypress tests in your CI provider.
|
||||
|
||||
The difference is that your CI provider has no idea what is going on inside of the Cypress process. It's simply programmed to know whether or not a process failed - based on whether it had an exit code greater than `0`.
|
||||
|
||||
Our dashboard provides you with the low level details of *what* happened during your run. Using both your CI provider + Cypress together gives the insight required to debug your test runs.
|
||||
|
||||
When a run happens and a test fails - instead of going and inspecting your CI provider's `stdout` output, you can log into the [Dashboard](https://on.cypress.io/dashboard) and see all of the test run results. It should be instantly clear what the problem was.
|
||||
|
||||
***
|
||||
|
||||
## How much does this cost?
|
||||
|
||||
Everything is free while we are in Beta.
|
||||
|
||||
In the future, we will charge per month for private projects.
|
||||
|
||||
Public projects will be free but will likely have a monthly usage cap on them.
|
||||
|
||||
We will offer similar pricing models of other Developer Tools you are familiar with using.
|
||||
|
||||
Plans will likely start around the $99/month level.
|
||||
***
|
||||
|
||||
## Can I host this myself?
|
||||
|
||||
No, although we are looking to build an on-premise version of the Dashboard for use in private clouds. If you're interested in our on-premise version, [let us know](mailto:hello@cypress.io)!
|
||||
|
||||
***
|
||||
|
||||
## Can I choose not to use it?
|
||||
|
||||
Of course. The dashboard is a separate service from the Desktop Application and will always remain optional. We hope you'll find a tremendous amount of value out of it, but it is not coupled to being able to run your tests.
|
||||
|
||||
You can simply always run your tests in CI using `cypress run` without the `--record` flag which does not communicate with our external servers and will not record any test results.
|
||||
@@ -0,0 +1,193 @@
|
||||
title: Projects
|
||||
---
|
||||
|
||||
# What are Projects?
|
||||
|
||||
A Cypress project represents the directory of files and folders that make up your tests.
|
||||
|
||||
This is often the same repository as your code, but can also be a subfolder or a separate repository altogether.
|
||||
|
||||
***
|
||||
|
||||
# Adding a new Project
|
||||
|
||||
Projects can **only** be added to Cypress through our [Desktop Application](https://on.cypress.io/guides/installing-and-running).
|
||||
|
||||
1. Click :fa-plus: Add Project.
|
||||
|
||||

|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "Projects added in our Desktop Application are strictly local to your computer. They are not tracked in any way by Cypress servers and do not communicate with us until they are [setup to be recorded](#section-recording-runs)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
***
|
||||
|
||||
# Setting up a Project to Record
|
||||
|
||||
You can also setup your project to have its test runs recorded and displayed in both the Desktop Application and the Dashboard.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "Not sure what the Dashboard is? [Its our service which displays all of your recorded runs](https://on.cypress.io/guides/dashboard-features)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
During a run we record all failing tests, logs, screenshots, and videos.
|
||||
|
||||
**To setup a project:**
|
||||
|
||||
1. Click on the "Runs" tab of your project, then click "Setup Project to Record".
|
||||
|
||||

|
||||
|
||||
2. Fill in the name of your project (this is only for display purposes and can be changed later).
|
||||
|
||||

|
||||
|
||||
3. Choose who owns the project. You can personally own it or select an organization you've created. Organizations work just like they do in Github. They enable you to seperate your personal and work projects. [Read more about Organizations.](https://on.cypress.io/guides/organizations)
|
||||
|
||||

|
||||
|
||||
4. Choose whether this project is Public or Private.
|
||||
|
||||
**A public project** can have its recordings and runs seen by *anyone*. Typically these are open source projects.
|
||||
|
||||
**A private project** restricts its access to *only users you invite* to see your Organization or your own projects.
|
||||
|
||||

|
||||
|
||||
5. Click "Setup Project".
|
||||
|
||||

|
||||
|
||||
You are now ready to record your runs. Typically you would record your runs when running in [Continuous Integration](https://on.cypress.io/guides/continuous-integration) but you can also record your runs from your local computer.
|
||||
|
||||
***
|
||||
|
||||
## How do I record runs?
|
||||
|
||||
Now that your project is setup, Cypress has inserted your unique [projectId](#section-what-is-a-projectid-) into `cypress.json`.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "Be sure to check your `cypress.json` into source control."
|
||||
}
|
||||
[/block]
|
||||
|
||||
In order to record we also require you provide us your [Record Key](#section-what-is-a-record-key-). The record key along with your projectId uniquely identifies your project.
|
||||
|
||||
You can provide the Record Key when running this command:
|
||||
|
||||
```shell
|
||||
cypress run --record --key <record_key>
|
||||
```
|
||||
|
||||
Or you can also set an environment variable and we will automatically look for that.
|
||||
|
||||
```shell
|
||||
## you'd typically set this in your CI provider
|
||||
export CYPRESS_RECORD_KEY=abc-key-123
|
||||
|
||||
## we will automatically search and apply the key
|
||||
cypress run --record
|
||||
```
|
||||
|
||||
Once tests run, you will see them show up in the [Dashboard](https://on.cypress.io/dashboard) and in the Desktop Application.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
***
|
||||
|
||||
## What is a projectId?
|
||||
|
||||
Once you setup your project to record, we generate a unique `projectId` for your project, and automatically insert it into your `cypress.json` file.
|
||||
|
||||
**The `projectId` is a 6 character string in your cypress.json:**
|
||||
|
||||
```javascript
|
||||
// cypress.json
|
||||
{
|
||||
"projectId": "a7bq2k"
|
||||
}
|
||||
```
|
||||
|
||||
This is how we uniquely identify your project. If you manually alter this, **Cypress will no longer be able to identify your project or find the recorded builds for it**. We recommend that you check your `cypress.json` including the `projectId` into source control.
|
||||
|
||||
***
|
||||
|
||||
## What is a Record Key?
|
||||
|
||||
Once you're setup to record test runs, we automatically generate a **Record Key** for the project.
|
||||
|
||||
**A record key is a GUID that looks like this:**
|
||||
|
||||
```shell
|
||||
f4466038-70c2-4688-9ed9-106bf013cd73
|
||||
```
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "You can create multiple Record Keys for a project, or delete existing ones from our [Dashboard](https://on.cypress.io/dashboard)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
You can also find your Record Key inside of the **Settings** tab.
|
||||
|
||||
|
||||

|
||||
|
||||
***
|
||||
|
||||
## How do a projectId and Record Key work together?
|
||||
|
||||
Cypress uses your `projectId` and **Record Key** together to uniquely identify projects.
|
||||
|
||||

|
||||
|
||||
The record key is used to authenticate that your project is *allowed* to record. As long as your record key stays *private*, nobody will be able to record test runs for your project - even if they have your `projectId`.
|
||||
|
||||
If you have a public project you should *still* keep your record key secret. If someone knows both your record key and your `projectId`, they could record test runs for your project - which would mix up all of your results!
|
||||
|
||||
Think of your record key as the key that enables you to **write and create** builds. However, it has nothing to do with being able to **read or see** builds once they are created.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "warning",
|
||||
"body": "If your Record Key is accidentally exposed, you simply need to remove it and generate a new one from our [Dashboard](https://on.cypress.io/dashboard)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
***
|
||||
|
||||
## What is the difference between public and private projects?
|
||||
|
||||
**A public project** means that anyone can see the recorded runs for it. It's similar to how public projects on Github, Travis, or Circle are handled. Anyone who knows your `projectId` will be able to see the recorded runs for public projects.
|
||||
|
||||
**A private project** means that only [users](https://on.cypress.io/guides/organizations#section-inviting-users) you explicitly invite to your [organization](https://on.cypress.io/guides/organizations) can see its recorded runs. Even if someone knows your `projectId`, they will not have access to your runs unless you have invited them.
|
||||
|
||||
A Record Key has nothing to do with **viewing** build data - it's a "write only" key. Even if it is accidentally leaked, it will not affect who can "see" your builds.
|
||||
|
||||
***
|
||||
|
||||
# Transferring Ownership of a Project
|
||||
|
||||
You can transfer projects that you own to another organization you are a part of or to another user in the organization. This functionality only exists in our [Dashboard](https://on.cypress.io/dashboard).
|
||||
|
||||

|
||||
|
||||
***
|
||||
|
||||
# Deleting a Project
|
||||
|
||||
You can delete projects you own. This will also delete all of their recorded runs. This functionality only exists in our [Dashboard](https://on.cypress.io/dashboard).
|
||||
|
||||

|
||||
@@ -0,0 +1,56 @@
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "[Explore talks, blogs, and podcasts about testing in Cypress.](https://www.cypress.io/explore)",
|
||||
"title": "Want to see Cypress in action?"
|
||||
}
|
||||
[/block]
|
||||
|
||||
---
|
||||
|
||||
| Getting Started | |
|
||||
| -------------------- | -- |
|
||||
| [Installing & Running](https://on.cypress.io/guides/installing-and-running) | Get Cypress downloaded and in your project |
|
||||
| [Writing your First Test](https://on.cypress.io/guides/writing-your-first-test) | Write a test in Cypress |
|
||||
| [Using the Cypress Running](https://on.cypress.io/guides/using-the-cypress-runner) | Review test commands, instrumentation and your application under test. |
|
||||
|
||||
| Examples | |
|
||||
| -------------------- | -- |
|
||||
| [List of Example Apps](https://on.cypress.io/guides/all-example-apps) | See Cypress being used in existing projects. |
|
||||
| [List of Example Recipes](https://github.com/cypress-io/cypress-example-recipes) | Recipes for testing common scenarios in Cypress. |
|
||||
|
||||
| Dashboard | |
|
||||
| -------------------- | -- |
|
||||
| [Features](https://on.cypress.io/guides/dashboard-features) | An overview of our Dashboard. |
|
||||
| [Projects](https://on.cypress.io/guides/projects) | Manage your Projects and configure them to record runs. |
|
||||
| [Runs](https://on.cypress.io/guides/runs) | View your Recorded Runs. |
|
||||
| [Organizations](https://on.cypress.io/guides/organizations) | Manage your Organizations. |
|
||||
|
||||
| Guides | |
|
||||
| -------------------- | -- |
|
||||
| [Configuration](https://on.cypress.io/guides/configuration) | Configure global, network, directory, viewport and animation options |
|
||||
| [Issuing Commands](https://on.cypress.io/guides/issuing-commands) | Issue actions to be performed in your test |
|
||||
| [Finding Elements](https://on.cypress.io/guides/finding-elements) | Traverse the DOM, find elements, make assertions |
|
||||
| [Making Assertions](https://on.cypress.io/guides/making-assertions) | Set expectations for the behavior |
|
||||
| [Network Requests](https://on.cypress.io/guides/network-requests-xhr) | Handle AJAX/XHR Requests |
|
||||
| [Continuous Integration](https://on.cypress.io/guides/continuous-integration) | Integrate with CI Providers |
|
||||
| [Environment Variables](https://on.cypress.io/guides/environment-variables) | Set environment variables |
|
||||
| [Stubs, Spies and Clocks](https://on.cypress.io/guides/stubs-spies-clocks) | Learn about when and why to use stubs, spies, and control clock time |
|
||||
| [Using Aliases](https://on.cypress.io/guides/using-aliases) | Represent an object as alias |
|
||||
| [Creating Fixtures](https://on.cypress.io/guides/creating-fixtures) | Mock data in fixtures |
|
||||
| [Screenshots and Videos](https://on.cypress.io/guides/screenshots-and-videos) | Capture screenshots and videos of your test run |
|
||||
| [Bundled Tools](https://on.cypress.io/guides/bundled-tools) | What is Cypress built on |
|
||||
| [Reporters](https://on.cypress.io/guides/reporters) | Customize test results with reporters |
|
||||
|
||||
| References | |
|
||||
| -------------------- | -- |
|
||||
| [CLI Tool](https://on.cypress.io/guides/cli) | Cypress CLI Tool for programmatically interacting with the Desktop Application |
|
||||
| [Error Messages](https://on.cypress.io/guides/errors) | Error messages |
|
||||
| [Anti-patterns](https://on.cypress.io/guides/anti-patterns) | Anti-patterns |
|
||||
| [Known Issues](https://on.cypress.io/guides/known-issues) | Known Issues |
|
||||
| [Web Security](https://on.cypress.io/guides/web-security) | Web Security |
|
||||
| [Browser Management](https://on.cypress.io/guides/browser-management) | Browser Management |
|
||||
| [Userland Extensions](https://on.cypress.io/guides/userland-extensions) | Userland Extensions |
|
||||
@@ -0,0 +1,141 @@
|
||||
title: Installing and Running
|
||||
---
|
||||
|
||||
# System Requirements
|
||||
|
||||
Cypress is a desktop application. This desktop application is the equivalent replacement of Selenium Server and must be running to test in Cypress.
|
||||
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "The desktop application manages your local projects. The actual testing will be done in a **browser**, not the desktop application"
|
||||
}
|
||||
[/block]
|
||||
|
||||
The desktop application can be installed in the following operating systems:
|
||||
|
||||
| Operating System |
|
||||
| ------ |
|
||||
| Linux |
|
||||
| OSX |
|
||||
|
||||
Windows is [(not yet working)](https://github.com/cypress-io/cypress/issues/74).
|
||||
|
||||
There are no dependencies to install the Desktop Application, although if you want to [use Cypress from the Command Line](https://github.com/cypress-io/cypress-cli) you will need to have `node` installed.
|
||||
|
||||
***
|
||||
|
||||
# Installing
|
||||
|
||||
You can install Cypress in 2 different ways:
|
||||
* [Cypress CLI Tool](https://github.com/cypress-io/cypress-cli)
|
||||
* [Direct Download](#section-direct-download)
|
||||
|
||||
## Command Line Tool
|
||||
|
||||
```shell
|
||||
## install the Cypress CLI tool
|
||||
npm install -g cypress-cli
|
||||
|
||||
## install the Desktop Cypress app
|
||||
cypress install
|
||||
```
|
||||
|
||||

|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "The Cypress CLI Tool contains many additional options such as installing a specific Cypress version.\n\nSee the [Cypress CLI Docs](https://github.com/cypress-io/cypress-cli#installation).",
|
||||
"title": "Cypress CLI"
|
||||
}
|
||||
[/block]
|
||||
|
||||
## Direct Download
|
||||
|
||||
You can download Cypress directly [here.](http://download.cypress.io/desktop)
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "danger",
|
||||
"body": "The vast majority of the time, Cypress will install correctly. But if you're on Linux you [might have to install some other dependencies](https://on.cypress.io/guides/continuous-integration#section-dependencies).",
|
||||
"title": "Woops, I got an error installing"
|
||||
}
|
||||
[/block]
|
||||
|
||||
***
|
||||
|
||||
# Logging In
|
||||
|
||||
After installing, you will need to login to Cypress. Login currently requires a [Github](https://github.com/) account, if you do not have an account, you will have to [create one](https://github.com/join) to use Cypress.
|
||||
|
||||
**To Login:**
|
||||
|
||||
- Open the Cypress App -- just double click the app from your OS application's folder.
|
||||
- Click "Log In with GitHub".
|
||||
- Authorize GitHub access to your account.
|
||||
|
||||

|
||||
|
||||
## Your email: `jane.doe@gmail.com` has not been authorized.
|
||||
|
||||
While in beta, the Cypress team has to whitelist the email address associated with your GitHub account in order for you to use Cypress.
|
||||
|
||||
- If you received this error and have never filled out our [Early Adopter Access](http://goo.gl/forms/4vEMwj8LNT) form, fill out this form with the email in the error so we can whitelist it. You will receive an invite during one of our future Beta invites.
|
||||
- If you received this error after receiving a Beta invite email from Cypress, please send an email to **support@cypress.io** telling us the email in the error so we can whitelist it.
|
||||
|
||||
***
|
||||
|
||||
# Adding Projects
|
||||
|
||||
After successfully logging in, you will need to add the project(s) you want to write Cypress tests in.
|
||||
|
||||
- Click :fa-plus: Add Project.
|
||||
|
||||

|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "Projects added in our Desktop Application are strictly local to your computer. They are not tracked in any way by Cypress servers and do not communicate with us until they are [setup to be recorded](https://on.cypress.io/guides/projects#section-recording-runs)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
***
|
||||
|
||||
# Running Tests from the GUI
|
||||
|
||||
To run tests:
|
||||
|
||||
- Click on the project.
|
||||
- You will then come to a page listing all files in your project's `cypress/integration` folder. If it's a new project, you'll see a message about the folder structure generated for you and also an `example_spec.js` file.
|
||||
- Click on the test file you want to run or click "Run All Tests".
|
||||
- After opening your project in Cypress, Cypress will generate a `cypress.json` file in your project:
|
||||
|
||||
```text
|
||||
<your project>/cypress.json
|
||||
```
|
||||
|
||||
This file contains a unique `projectId` and allows for specific Cypress [configuration](https://on.cypress.io/guides/configuration). It is okay to commit this file to `git`.
|
||||
|
||||
***
|
||||
|
||||
# Running Headlessly
|
||||
|
||||
While you'll find yourself working primarily in the GUI, it is helpful to be able to run your tests headlessly.
|
||||
|
||||
Once you have the [Cypress CLI Tool](https://github.com/cypress-io/cypress-cli) installed, you can simply execute:
|
||||
|
||||
```shell
|
||||
cypress run
|
||||
```
|
||||
|
||||
Additionally you can specify:
|
||||
|
||||
- a single test file
|
||||
- [a specific reporter and reporter options](https://on.cypress.io/guides/reporters)
|
||||
- a different port
|
||||
- environment variables
|
||||
|
||||
You can [read about all of these options](https://github.com/cypress-io/cypress-cli#cypress-run-1) which are documented on the Cypress CLI tool.
|
||||
@@ -0,0 +1,63 @@
|
||||
title: List of Example Apps
|
||||
---
|
||||
|
||||
Name | JS | Server | CI
|
||||
--- | --- | --- |
|
||||
[Kitchen Sink](https://github.com/cypress-io/cypress-example-kitchensink) | jQuery | Node | TravisCI, CircleCI, Codeship
|
||||
[TodoMVC](https://github.com/cypress-io/cypress-example-todomvc) | React | Node | TravisCI, CircleCI
|
||||
[PieChopper](https://github.com/cypress-io/cypress-example-piechopper) | Angular | Node | TravisCI, CircleCI
|
||||
|
||||
***
|
||||
|
||||
# [Kitchen Sink](https://github.com/cypress-io/cypress-example-kitchensink)
|
||||
|
||||
This is an example app is used to showcase every command available in Cypress. The [tests](https://github.com/cypress-io/examples-kitchen-sink/blob/master/cypress/integration/example_spec.js) cover all of the following features:
|
||||
|
||||

|
||||
|
||||
**Features:**
|
||||
|
||||
- Querying
|
||||
- Traversal
|
||||
- Actions
|
||||
- Viewport
|
||||
- Navigation
|
||||
- Aliasing
|
||||
- Waiting
|
||||
- Network Requests
|
||||
- Fixtures
|
||||
- Local Storage
|
||||
- Cookies
|
||||
|
||||
***
|
||||
|
||||
# [TodoMVC](https://github.com/cypress-io/cypress-example-todomvc)
|
||||
|
||||
This repo compares [Cypress Tests](https://github.com/cypress-io/cypress-example-todomvc/blob/master/cypress/integration/app_spec.js) to [official TodoMVC Tests](https://github.com/tastejs/todomvc/blob/master/tests/test.js). This gives you a good comparison of writing and running tests in Cypress versus vanilla Selenium.
|
||||
|
||||

|
||||
|
||||
**Features:**
|
||||
|
||||
- Querying
|
||||
- Custom Commands
|
||||
- Aliasing
|
||||
- Navigation
|
||||
|
||||
***
|
||||
|
||||
# [PieChopper](https://github.com/cypress-io/cypress-example-piechopper)
|
||||
|
||||
This is a single page application with a decent amount of features. The [tests](https://github.com/cypress-io/cypress-example-piechopper/blob/master/cypress/integration/app_spec.js) involve a lot of form submissions.
|
||||
|
||||

|
||||
|
||||
**Features:**
|
||||
|
||||
- Querying
|
||||
- Forms
|
||||
- Scroll Tests
|
||||
- Network Requests
|
||||
- XHR Stubbing
|
||||
- Dialogs
|
||||
- Responsive Tests
|
||||
@@ -0,0 +1,47 @@
|
||||
title: Our Goals
|
||||
---
|
||||
|
||||
# Problems with current front-end testing tools
|
||||
|
||||
There are clear benefits to testing code. But many *web applications* are not fully covered in tests. Why? There are many testing tools for the front end, but most (if not all) suffer from some problems.
|
||||
|
||||
* **Poor Setup:** Testing environments take too long to setup.
|
||||
* **Unreliable:** Tests are often brittle, and randomly fail.
|
||||
* **Time consuming:** Running an entire test suite takes too long (sometimes hours).
|
||||
* **No Cross Browser Support:** Debugging across browsers and browser versions is very time consuming.
|
||||
* **Obscure Error Messages:** Error messages are obtuse, indirect, and increase the time it takes to debug.
|
||||
* **Coupled dependencies:** Integration tests are often coupled directly to the server.
|
||||
* **Lacking fixture support:** Handling mock data, or fixtures, is difficult.
|
||||
* **Don't encourage TDD:** Testing often occurs *after* features are built because there isn't an apparent test-driven development (TDD) flow.
|
||||
* **Lack of integration testing:** Even if unit testing JavaScript is reasonably simple, unit testing alone does not verify your application is fully functioning.
|
||||
* **Async hell:** Handling complicated asynchronous logic that is found on most modern single-page JavaScript applications is impossible.
|
||||
* **No Visibility:** Testing through a console is obscure and doesn't give full visibility on the problems your users will face using your web application.
|
||||
* **Buggy:** Selenium drivers differ in implementation details which means code breaks across different browsers and browser versions.
|
||||
|
||||
These are just a few reasons why it's often difficult to test modern web applications. Often it takes longer to write a passing test for a feature, than to actually build the feature.
|
||||
|
||||
There is a lot of mental friction when writing tests. Testing just becomes another layer to cut through. Because testing is often brittle, we lose confidence that our tests are delivering any additional value.
|
||||
|
||||
Because of this complexity, most organizations have an entire Quality Assurance (QA) department dedicated to these tasks.
|
||||
|
||||
> Cypress aims to solve the biggest difficulties when it comes to testing web applications. It aims to reduce the mental effort required to write tests. Cypress works in your typical development workflow (in the browser) and allows you to see your application while it's being tested. This enables you to practice TDD since there is no context shift between testing and development.
|
||||
|
||||
***
|
||||
|
||||
# Goals of Cypress
|
||||
|
||||
* **Easy Setup:** Allow you to write your first test in less than 5 minutes.
|
||||
* **Automated:** Allow you to drive your application with tests instead of manual interactions.
|
||||
* **Easy Integration:** Require zero code changes to your existing application.
|
||||
* **In-Browser Testing:** Integrate testing within your normal development process.
|
||||
* **JavaScript:** Allow you to write your test suite in JavaScript.
|
||||
* **Enjoyable:** Make writing tests an enjoyable, fun experience.
|
||||
* **Opinionated:** Encourage writing good tests.
|
||||
* **Clear error messages:** Provide **clear**, debuggable error messages.
|
||||
* **Intelligent Network Requests:** Make dealing with `AJAX/XHR` ridiculously simple.
|
||||
* **Cross-browser support:** Provide cross-browser testing and debugging **without** leaving Google Chrome and work in all modern browsers (`IE11+`)
|
||||
* **CI Integration:** Instantly integrate any Continuous Integration provider.
|
||||
* **Accessible:** Work with any JavaScript framework (current and future).
|
||||
* **Flexible:** Replace server side testing tools like `Capybara`.
|
||||
* **Integrate with Server:** Allow you to communicate directly to a backend server for seeding / querying.
|
||||
* **Elimate Selenium:** Eliminate the need to code or deal with `Selenium`.
|
||||
@@ -0,0 +1,86 @@
|
||||
title: Using the Cypress Runner
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Cypress runs tests in a unique interactive runner that allows you to see commands as they execute while also viewing the application under test.
|
||||
|
||||

|
||||
|
||||
***
|
||||
|
||||
# Test Runner Components:
|
||||
|
||||
## Command Log
|
||||
|
||||
The lefthand side of the test runner is a visual representation of your test suite. Each test block is properly nested and each test, when clicked, displays every Cypress command and assertion executed within the test's block as well as any command or assertion executed in relevant `before`, `beforeEach`, `afterEach`, and `after` hooks.
|
||||
|
||||
<img width="436" alt="screen shot 2017-03-06 at 2 03 49 pm" src="https://cloud.githubusercontent.com/assets/1271364/23626797/1a6a59f6-027c-11e7-9ca5-7451b97557a9.png">
|
||||
|
||||
**Hovering on Commands**
|
||||
|
||||
Each command and assertion, when hovered over, restores the Application Under Test (righthand side) to the state it was in when that command executed. This allows you to 'time-travel' back to previous states of your application when testing.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "By default, Cypress keeps 50 tests worth of snapshots and command data for time traveling. If you are seeing extremely high memory consumption in your browser, you may want to lower the `numTestsKeptInMemory` in your [configuration](https://on.cypress.io/guides/configuration#section-global)."
|
||||
}
|
||||
[/block]
|
||||
|
||||
|
||||
**Clicking on Commands**
|
||||
|
||||
Each command, assertion, or error, when clicked on, displays extra information in the dev tools console. Clicking also 'pins' the Application Under Test (righthand side) to it's previous state when the command executed.
|
||||
|
||||

|
||||
|
||||
|
||||
***
|
||||
|
||||
## Instrument Panel
|
||||
|
||||
For certain commands like [`cy.route()`](https://on.cypress.io/api/route), [`cy.stub()`](https://on.cypress.io/api/stub), and [`cy.spy()`](https://on.cypress.io/api/spy), an extra instrument panel is displayed above the test to give more information about the state of your tests.
|
||||
|
||||
*Routes*
|
||||
|
||||

|
||||
|
||||
*Stubs*
|
||||
|
||||

|
||||
|
||||
*Spies*
|
||||
|
||||

|
||||
|
||||
## Application Under Test
|
||||
|
||||
The righthand side of the test runner is used to display the Application Under Test (AUT: the application that was navigated to using a [`cy.visit()`](https://on.cypress.io/api/visit) or any subsequent routing calls made from the visited application.
|
||||
|
||||
In the example below, we wrote the following code in our test file:
|
||||
|
||||
```javascript
|
||||
cy.visit('https://example.cypress.io')
|
||||
|
||||
cy.title().should('include', 'Kitchen Sink')
|
||||
```
|
||||
|
||||
In the corresponding Application Preview below, you can see `https://example.cypress.io` is being displayed in the righthand side. Not only is the application visible, but it is fully interactable. You can open your developer tools to inspect elements as you would your normal application. The DOM is completely available for debugging.
|
||||
|
||||

|
||||
|
||||
The AUT also displays in the size and orientation specified in your tests. You can change the size or orientation with the [`cy.viewport()`](https://on.cypress.io/api/viewport) command or in your [Cypress configuration](https://docs.cypress.io/docs/configuration#section-viewport). If the AUT does not fit within the current browser window, it is scaled appropriately to fit within the window.
|
||||
|
||||
The current size and scale of the AUT is displayed in the top right corner of the window.
|
||||
|
||||
The image below shows that our application is displaying at `1000px` width, `660px` height and scaled to `100%`.
|
||||
|
||||

|
||||
|
||||
|
||||
*Note: The righthand side may also be used to display syntax errors in your test file that prevent the tests from running.*
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
title: Writing Your First Test
|
||||
---
|
||||
|
||||
# Folder Structure
|
||||
|
||||
After adding a new project, Cypress will automatically scaffold out a suggested folder structure. By default it will create:
|
||||
|
||||
```text
|
||||
/cypress
|
||||
/cypress/fixtures
|
||||
/cypress/integration
|
||||
/cypress/support
|
||||
```
|
||||
|
||||
Cypress also adds placeholder files to help get you started with examples in each folder.
|
||||
|
||||
**Example JSON fixture**
|
||||
```text
|
||||
/cypress/fixtures/example.json
|
||||
```
|
||||
|
||||
**Example Integration Test**
|
||||
```text
|
||||
/cypress/integration/example_spec.js
|
||||
```
|
||||
|
||||
**Example JavaScript Support Files**
|
||||
```text
|
||||
/cypress/support/commands.js
|
||||
/cypress/support/defaults.js
|
||||
/cypress/support/index.js
|
||||
```
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "[Check out our example recipe using support files to import common utilities](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/es2015_commonjs_modules_spec.js)",
|
||||
"title": "Using Support files for common functionality"
|
||||
}
|
||||
[/block]
|
||||
|
||||
**Configuring Folder Structure**
|
||||
|
||||
While Cypress allows for configuration of where your tests, fixtures, and support files are located, if you're starting your first project, we recommend you use the above structure.
|
||||
|
||||
You can modify the folder configuration in your `cypress.json`. See [configuration](https://on.cypress.io/guides/configuration) for more detail.
|
||||
|
||||
***
|
||||
|
||||
# Test Files
|
||||
|
||||
Test files may be written as `.js`, `.jsx`, `.coffee`, or `cjsx` files.
|
||||
|
||||
Cypress supports ES2015, ES2016, ES2017, and JSX. ES2015 modules and CommonJS modules are also supported, so you can `import` or `require` both npm packages and local modules.
|
||||
|
||||
[block:callout]
|
||||
{
|
||||
"type": "info",
|
||||
"body": "[Check out our example recipe using ES2015 and CommonJS modules](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/es2015_commonjs_modules_spec.js)",
|
||||
"title": "Importing ES2015 or CommonJS modules"
|
||||
}
|
||||
[/block]
|
||||
|
||||
To see an example of every command used in Cypress, open the [`example_spec.js`](https://github.com/cypress-io/cypress-example-kitchensink/blob/master/cypress/integration/example_spec.js) within your `cypress/integration` folder.
|
||||
|
||||
To start writing tests for your app, simply create a new file like `app_spec.js` within your `cypress/integration` folder. Refresh your tests list in the Cypress GUI and your new file should have appeared in the list.
|
||||
|
||||
***
|
||||
|
||||
# How to Write Tests
|
||||
|
||||
Cypress is built on top of [Mocha](https://on.cypress.io/guides/bundled-tools#section-mocha) and uses its `bdd` interface. Tests you write in Cypress will mostly adhere to this style.
|
||||
|
||||
If you're familiar with writing tests in JavaScript, then writing tests in Cypress will be a breeze.
|
||||
|
||||
We're still working on introductory docs and videos. If you want to see Cypress in action, [check out some examples](https://on.cypress.io/guides/all-example-apps) of applications using Cypress tests and [check out some example recipes we've written](https://github.com/cypress-io/cypress-example-recipes) for special use cases.
|
||||
|
||||
## BDD Interface
|
||||
|
||||
The BDD interface borrowed from [Mocha](https://on.cypress.io/guides/bundled-tools#section-mocha) provides `describe()`, `context()`, `it()` and `specify()`.
|
||||
|
||||
`context()` is identical to `describe()` and `specify()` is identical to `it()`, so choose whatever terminology works best for you.
|
||||
|
||||
```javascript
|
||||
// -- Start: Our Application Code --
|
||||
function add (a, b) {
|
||||
return a + b
|
||||
}
|
||||
|
||||
function subtract (a, b) {
|
||||
return a - b
|
||||
}
|
||||
|
||||
function divide (a, b) {
|
||||
return a / b
|
||||
}
|
||||
|
||||
function multiply (a, b) {
|
||||
return a * b
|
||||
}
|
||||
// -- End: Our Application Code --
|
||||
|
||||
// -- Start: Our Cypress Tests --
|
||||
describe('Unit test our math functions', function() {
|
||||
context('math', function() {
|
||||
it('can add numbers', function() {
|
||||
expect(add(1, 2)).to.eq(3)
|
||||
})
|
||||
|
||||
it('can subtract numbers', function() {
|
||||
expect(subtract(5, 12)).to.eq(-7)
|
||||
})
|
||||
|
||||
specify('can divide numbers', function() {
|
||||
expect(divide(27, 9)).to.eq(3)
|
||||
})
|
||||
|
||||
specify('can muliple numbers', function() {
|
||||
expect(multiply(5, 4)).to.eq(20)
|
||||
})
|
||||
})
|
||||
})
|
||||
// -- End: Our Cypress Tests --
|
||||
|
||||
```
|
||||
|
||||
## Hooks
|
||||
|
||||
Cypress also provides hooks (borrowed from [Mocha](https://on.cypress.io/guides/bundled-tools#section-mocha)).
|
||||
|
||||
These are helpful to set conditions that you want run before a set of tests or before each test. They're also helpful to clean up conditions after a set of tests or after each test.
|
||||
|
||||
```javascript
|
||||
describe('Hooks', function() {
|
||||
before(function() {
|
||||
// runs before all tests in this block
|
||||
})
|
||||
|
||||
after(function() {
|
||||
// runs after all tests in this block
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
// runs before each test in this block
|
||||
})
|
||||
|
||||
afterEach(function() {
|
||||
// runs after each test in this block
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**The order of hook and test execution is as follows:**
|
||||
|
||||
- All `before()` hooks run (once)
|
||||
- Any `beforeEach()` hooks run
|
||||
- Tests run
|
||||
- Any `afterEach()` hooks run
|
||||
- All `after()` hooks run (once)
|
||||
|
||||
## Excluding and Including Tests
|
||||
|
||||
To run a specified suite or test simply append `.only()` to the function. All nested suites will also be executed.
|
||||
|
||||
```javascript
|
||||
// -- Start: Our Application Code --
|
||||
function fizzbuzz (num) {
|
||||
if (num % 3 === 0 && num % 5 === 0) {
|
||||
return "fizzbuzz"
|
||||
}
|
||||
|
||||
if (num % 3 === 0) {
|
||||
return "fizz"
|
||||
}
|
||||
|
||||
if (num % 5 === 0) {
|
||||
return "buzz"
|
||||
}
|
||||
}
|
||||
// -- End: Our Application Code --
|
||||
|
||||
// -- Start: Our Cypress Tests --
|
||||
describe('Unit Test FizzBuzz', function(){
|
||||
beforeEach(function(){
|
||||
this.numsExpectedToEq = (arr, expected) =>
|
||||
arr.forEach((num) => {
|
||||
expect(fizzbuzz(num)).to.eq(expected)
|
||||
})
|
||||
})
|
||||
|
||||
// Only this test and it's beforeEach code would run
|
||||
it.only('returns "fizz" when number is multiple of 3', function(){
|
||||
this.numsExpectedToEq([9, 12, 18], "fizz")
|
||||
})
|
||||
|
||||
it('returns "buzz" when number is multiple of 5', function(){
|
||||
this.numsExpectedToEq([10, 20, 25], "buzz")
|
||||
})
|
||||
|
||||
it('returns "fizzbuzz" when number is multiple of both 3 and 5', function(){
|
||||
this.numsExpectedToEq([15, 30, 60], "fizzbuzz")
|
||||
})
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
To skip a specified suite or test simply append `.skip()` to the function. All nested suites will also be skipped.
|
||||
|
||||
```javascript
|
||||
it.skip('returns "fizz" when number is multiple of 3', function(){
|
||||
this.numsExpectedToEq([9, 12, 18], "fizz")
|
||||
})
|
||||
```
|
||||
|
||||
## Dynamically Generate Tests
|
||||
|
||||
You can dynamically generate tests using JavaScript.
|
||||
|
||||
```javascript
|
||||
describe('if your app uses jQuery', function(){
|
||||
['mouseover', 'mouseout', 'mouseenter', 'mouseleave'].forEach((event) => {
|
||||
it('triggers event: ' + event, function(){
|
||||
// if your app uses jQuery, then we can trigger a jQuery
|
||||
// event that causes the event callback to fire
|
||||
cy
|
||||
.get('#with-jquery').invoke('trigger', event)
|
||||
.get('#messages').should('contain', 'the event ' + event + 'was fired')
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
The code above will produce a suite with 4 tests:
|
||||
|
||||
```bash
|
||||
> if your app uses jQuery
|
||||
> triggers event: 'mouseover'
|
||||
> triggers event: 'mouseout'
|
||||
> triggers event: 'mouseenter'
|
||||
> triggers event: 'mouseleave'
|
||||
```
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"projectNames": {
|
||||
"staging": "cypress",
|
||||
"production": "cypress"
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"cypress": {
|
||||
"v0.0": {
|
||||
"documentation": "cypress/v0.0/documentation",
|
||||
"customPages": "cypress/v0.0/customPages",
|
||||
"customContent": {
|
||||
"appearance": {
|
||||
"html_body": "cypress/v0.0/customContent/appearance/landing_page.html",
|
||||
"stylesheet": "cypress/v0.0/customContent/appearance/styles.css"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1.0": {
|
||||
"documentation": "cypress/v1.0/documentation",
|
||||
"customPages": "cypress/v1.0/customPages",
|
||||
"customContent": {
|
||||
"appearance": {
|
||||
"html_body": "cypress/v0.0/customContent/appearance/landing_page.html",
|
||||
"stylesheet": "cypress/v0.0/customContent/appearance/styles.css"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
menu:
|
||||
docs: Docs
|
||||
api: API
|
||||
news: News
|
||||
plugins: Plugins
|
||||
themes: Themes
|
||||
search: Search
|
||||
|
||||
index:
|
||||
get_started: Get started
|
||||
|
||||
page:
|
||||
contents: Contents
|
||||
back_to_top: Back to Top
|
||||
improve: Improve this doc
|
||||
prev: Prev
|
||||
next: Next
|
||||
last_updated: "Last updated: %s"
|
||||
|
||||
sidebar:
|
||||
docs:
|
||||
welcome: Welcome
|
||||
intro: Intro
|
||||
our_goals: Our Goals
|
||||
getting_started: Getting Started
|
||||
installing_and_running: Installing and Running
|
||||
writing_your_first_test: Writing Your First Test
|
||||
using_the_cypress_runner: Using the Cypress Runner
|
||||
examples: Examples
|
||||
list_of_example_apps: List of Example Apps
|
||||
list_of_example_recipes: List of Example Recipes
|
||||
dashboard: Dashboard
|
||||
features: Features
|
||||
projects: Projects
|
||||
runs: Runs
|
||||
organizations: Organizations
|
||||
guides: Guides
|
||||
configuration: Configuration
|
||||
issuing_commands: Issuing Commands
|
||||
finding_elements: Finding Elements
|
||||
making_assertions: Making Assertions
|
||||
network_requests: Network Requests
|
||||
continuous_integration: Continuous Integration
|
||||
environment_variables: Environment Variables
|
||||
stubs_spies_and_clocks: Stubs, Spies, and Clocks
|
||||
using_aliases: Using Aliases
|
||||
creating_fixtures: Creating Fixtures
|
||||
screenshots_and_videos: Screenshots and Videos
|
||||
bundled_tools: Bundled Tools
|
||||
reporters: Reporters
|
||||
references: References
|
||||
cli_tool: CLI Tool
|
||||
error_messages: Error Messages
|
||||
anti-patterns: Anti-patterns
|
||||
known_issues: Known Issues
|
||||
web_security: Web Security
|
||||
browser_management: Browser Management
|
||||
userland_extensions: Userland Extensions
|
||||
api:
|
||||
welcome: Welcome
|
||||
api: api
|
||||
commands: Commands
|
||||
and: and
|
||||
as: as
|
||||
blur: blur
|
||||
check: check
|
||||
children: children
|
||||
clear: clear
|
||||
clear_cookie: clear_cookie
|
||||
clear_cookies: clear_cookies
|
||||
clear_local_storage: clear_local_storage
|
||||
click: click
|
||||
clock: clock
|
||||
closest: closest
|
||||
contains: contains
|
||||
dblclick: dblclick
|
||||
debug: debug
|
||||
document: document
|
||||
each: each
|
||||
end: end
|
||||
eq: eq
|
||||
exec: exec
|
||||
filter: filter
|
||||
find: find
|
||||
first: first
|
||||
fixture: fixture
|
||||
focus: focus
|
||||
focused: focused
|
||||
get: get
|
||||
get_cookie: get_cookie
|
||||
get_cookies: get_cookies
|
||||
go: go
|
||||
hash: hash
|
||||
hover: hover
|
||||
invoke: invoke
|
||||
its: its
|
||||
last: last
|
||||
location: location
|
||||
log: log
|
||||
next: next
|
||||
next_all: next_all
|
||||
next_until: next_until
|
||||
not: not
|
||||
parent: parent
|
||||
parents: parents
|
||||
parents_until: parents_until
|
||||
read_file: read_file
|
||||
reload: reload
|
||||
request: request
|
||||
root: root
|
||||
route: route
|
||||
screenshot: screenshot
|
||||
select: select
|
||||
server: server
|
||||
set_cookie: set_cookie
|
||||
should: should
|
||||
siblings: siblings
|
||||
spread: spread
|
||||
spy: spy
|
||||
stub: stub
|
||||
submit: submit
|
||||
then: then
|
||||
tick: tick
|
||||
title: title
|
||||
type: type
|
||||
uncheck: uncheck
|
||||
url: url
|
||||
viewport: viewport
|
||||
visit: visit
|
||||
wait: wait
|
||||
window: window
|
||||
within: within
|
||||
wrap: wrap
|
||||
write_file: write_file
|
||||
utilities: Utilities
|
||||
_: _
|
||||
$: $
|
||||
minimatch: minimatch
|
||||
blob: blob
|
||||
promise: promise
|
||||
cypress_api: Cypress API
|
||||
config: config
|
||||
env: env
|
||||
cypress_commands: commands
|
||||
cookies: cookies
|
||||
dom: dom
|
||||
cypress_server: server
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<header id="banner" class="wrapper">
|
||||
<div class="inner">
|
||||
<h2 id="banner-title">{{ page.subtitle }}</h2>
|
||||
<div id="banner-share">{{ partial('partial/share') }}</div>
|
||||
</div>
|
||||
</header>
|
||||
<div id="content-wrap">
|
||||
<div class="wrapper">
|
||||
<div class="inner">
|
||||
{{ page.content }}
|
||||
<div id="intro-get-started-wrap">
|
||||
<a href="docs/" id="intro-get-started-link">{{ __('index.get_started') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ page.lang }}">
|
||||
{{ partial('partial/head') }}
|
||||
<body>
|
||||
<div id="container">
|
||||
{{ partial('partial/header') }}
|
||||
{{ body }}
|
||||
{{ partial('partial/footer') }}
|
||||
</div>
|
||||
<div id="mobile-nav-dimmer"></div>
|
||||
{{ partial('partial/mobile_nav') }}
|
||||
{{ partial('partial/after_footer') }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,34 @@
|
||||
<div id="content-wrap">
|
||||
<div id="content" class="wrapper">
|
||||
<div id="content-inner">
|
||||
<article class="article-container" itemscope itemtype="http://schema.org/Article">
|
||||
<div class="article-inner">
|
||||
<div class="article">
|
||||
<div class="inner">
|
||||
<header class="article-header">
|
||||
<h1 class="article-title" itemprop="name">{{ page.title }}</h1>
|
||||
<a href="{{ raw_link(page.source) }}" class="article-edit-link" title="{{ __('page.improve') }}"><i class="fa fa-pencil"></i></a>
|
||||
</header>
|
||||
<div class="article-content" itemprop="articleBody">
|
||||
{{ page_anchor(page.content) }}
|
||||
</div>
|
||||
<footer class="article-footer">
|
||||
<time class="article-footer-updated" datetime="{{ date_xml(page.updated) }}" itemprop="dateModified">{{ __('page.last_updated', date(page.updated)) }}</time>
|
||||
{{ page_nav() }}
|
||||
</footer>
|
||||
{{ partial('partial/comment') }}
|
||||
</div>
|
||||
</div>
|
||||
<aside id="article-toc" role="navigation">
|
||||
<div id="article-toc-inner">
|
||||
<strong class="sidebar-title">{{ __('page.contents') }}</strong>
|
||||
{{ toc(page.content, {list_number: false}) }}
|
||||
<a href="#" id="article-toc-top">{{ __('page.back_to_top') }}</a>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</article>
|
||||
{{ partial('partial/sidebar') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,21 @@
|
||||
<!-- Scripts -->
|
||||
<!-- build:js build/js/main.js -->
|
||||
{# {{ js('js/lang_select') }} #}
|
||||
{{ js('js/scrollingelement') }}
|
||||
{{ js('js/toc') }}
|
||||
{{ js('js/mobile_nav') }}
|
||||
<!-- endbuild -->
|
||||
<script src="https://cdn.jsdelivr.net/retinajs/1.3.0/retina.min.js" async></script>
|
||||
|
||||
<!-- Algolia -->
|
||||
{% if config.algolia[page.lang] %}
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
document.getElementById('search-input-wrap').classList.add('on');
|
||||
docsearch({
|
||||
apiKey: '{{ config.algolia[page.lang].api_key }}',
|
||||
indexName: '{{ config.algolia[page.lang].index_name }}',
|
||||
inputSelector: '#search-input'
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{% if page.comments && config.disqus_shortname %}
|
||||
<section id="comments">
|
||||
<div id="disqus_thread"></div>
|
||||
</section>
|
||||
<script>
|
||||
var disqus_shortname = '{{ config.disqus_shortname }}';
|
||||
var disqus_url = '{{ url }}';
|
||||
var disqus_title = {{ JSON.stringify(page.title) }};
|
||||
var disqus_config = function(){
|
||||
this.language = '{{ disqus_lang() }}';
|
||||
};
|
||||
(function(){
|
||||
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
||||
dsq.src = 'https://go.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,7 @@
|
||||
<footer id="footer" class="wrapper">
|
||||
<div class="inner">
|
||||
<div id="footer-copyright">
|
||||
© {{ moment(Date.now()).year() }} <a href="https://cypress.io" target="_blank">{{ config.author }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% if config.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{ config.google_analytics }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,35 @@
|
||||
<head prefix="og: http://ogp.me/ns#">
|
||||
<meta charset="utf-8">
|
||||
<title>{% if page.title %}{{ page.title }} | {% endif %}{{ config.title }}</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- Canonical links -->
|
||||
<link rel="canonical" href="{{ url }}">
|
||||
<!-- Alternative links -->
|
||||
{% if page.layout == 'page' or page.layout == 'index' %}
|
||||
{% for lang in site.data.languages %}
|
||||
<link rel="alternative" hreflang="{{ loop.key }}" href="{{ canonical_url(loop.key) }}">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<!-- Icon -->
|
||||
<link rel="icon" type="image/x-icon" href="{{ url_for('icon/favicon.ico') }}" sizes="16x16" />
|
||||
|
||||
<!-- CSS -->
|
||||
<!-- build:css build/css/cypress.css -->
|
||||
{{ css('css/cypress') }}
|
||||
<!-- endbuild -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:300,300i,400,400i,500,500i,600,600i" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css">
|
||||
<!-- RSS -->
|
||||
{{ feed_tag('atom.xml') }}
|
||||
<!-- Open Graph -->
|
||||
{{ open_graph({
|
||||
fb_admins: config.fb_admins,
|
||||
twitter_site: config.twitter
|
||||
}) }}
|
||||
<!-- Google Analytics -->
|
||||
{{ partial('google_analytics') }}
|
||||
<!-- Github Button -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</head>
|
||||
@@ -0,0 +1,30 @@
|
||||
<header id="header" class="wrapper">
|
||||
<div id="header-inner" class="inner">
|
||||
<h1 id="logo-wrap">
|
||||
<a href="{{ url_for_lang('') }}" id="logo">Cypress</a>
|
||||
</h1>
|
||||
<nav id="main-nav">
|
||||
{{ header_menu('main-nav') }}
|
||||
<a href="https://github.com/{{ config.github }}" class="main-nav-link"><i class="fa fa-github-alt"></i></a>
|
||||
<div id="search-input-wrap">
|
||||
<div id="search-input-icon">
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
<input type="search" id="search-input" placeholder="Search...">
|
||||
</div>
|
||||
</nav>
|
||||
{# <div id="lang-select-wrap">
|
||||
<label id="lang-select-label"><i class="fa fa-globe"></i><span>{{ lang_name(page.lang) }}</span></label>
|
||||
<select id="lang-select" data-canonical="{{ canonical_path_for_nav() }}">
|
||||
{% for lang in site.data.languages %}
|
||||
<option value="{{ loop.key }}"{% if page.lang === loop.key %} selected{% endif %}>{{ lang_name(loop.key) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div> #}
|
||||
<a id="mobile-nav-toggle">
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
<span class="mobile-nav-toggle-bar"></span>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,21 @@
|
||||
<nav id="mobile-nav">
|
||||
<div id="mobile-nav-inner">
|
||||
<ul id="mobile-nav-list">
|
||||
{{ header_menu('mobile-nav') }}
|
||||
<li class="mobile-nav-item">
|
||||
<a href="https://github.com/{{ config.github }}" class="mobile-nav-link" rel="external" target="_blank">GitHub</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% if page.layout == 'page' %}
|
||||
{{ doc_sidebar('mobile-nav') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{# <div id="mobile-lang-select-wrap">
|
||||
<span id="mobile-lang-select-label"><i class="fa fa-globe"></i><span>{{ lang_name(page.lang) }}</span></span>
|
||||
<select id="mobile-lang-select" data-canonical="{{ canonical_path_for_nav() }}">
|
||||
{% for lang in site.data.languages %}
|
||||
<option value="{{ loop.key }}"{% if page.lang === loop.key %} selected{% endif %}>{{ lang_name(loop.key) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div> #}
|
||||
</nav>
|
||||
@@ -0,0 +1,9 @@
|
||||
<li class="plugin on">
|
||||
<a href="{{ plugin.link }}" class="plugin-name" target="_blank">{{ plugin.name }}</a>
|
||||
<p class="plugin-desc">{{ plugin.description }}</p>
|
||||
<div class="plugin-tag-list">
|
||||
{% for tag in plugin.tags %}
|
||||
<a href="#{{ tag }}" class="plugin-tag">{{ tag }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
@@ -0,0 +1,16 @@
|
||||
<article class="article post" itemscope itemtype="http://schema.org/Article">
|
||||
<header class="article-header">
|
||||
{% if is_post() %}
|
||||
<h1 class="article-title" itemprop="name">{{ post.title }}</h1>
|
||||
{% else %}
|
||||
<h1>
|
||||
<a href="{{ url_for(post.path) }}" class="article-title" itemprop="name">{{ post.title }}</a>
|
||||
</h1>
|
||||
{% endif %}
|
||||
<a href="{{ url_for(post.path) }}" class="article-date">{{ time_tag(post.date) }}</a>
|
||||
</header>
|
||||
<div class="article-content" itemprop="articleBody">
|
||||
{{ page_anchor(post.content) }}
|
||||
</div>
|
||||
{{ partial('partial/comment') }}
|
||||
</article>
|
||||
@@ -0,0 +1,11 @@
|
||||
<!-- GitHub Star -->
|
||||
<a class="github-button" href="https://github.com/hexojs/hexo" data-count-href="/hexojs/hexo/stargazers" data-count-api="/repos/hexojs/hexo#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star hexojs/hexo on GitHub">Star</a>
|
||||
<!-- GitHub fork -->
|
||||
<a class="github-button" href="https://github.com/hexojs/hexo/fork" data-count-href="/hexojs/hexo/network" data-count-api="/repos/hexojs/hexo#forks_count" data-count-aria-label="# forks on GitHub" aria-label="Fork hexojs/hexo on GitHub">Fork</a>
|
||||
<!-- Tweet button -->
|
||||
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://hexo.io/" data-text="Hexo - A fast, simple & powerful blog framework powered by Node.js." data-hashtags="hexo,nodejs">Tweet</a>
|
||||
<!-- Twitter follow button -->
|
||||
<a href="https://twitter.com/hexojs" class="twitter-follow-button" data-show-count="false">Follow @hexojs</a>
|
||||
<script>
|
||||
window.twttr=(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);t._e=[];t.ready=function(f){t._e.push(f);};return t;}(document,"script","twitter-wjs"));
|
||||
</script>
|
||||
@@ -0,0 +1,3 @@
|
||||
<aside id="sidebar" role="navigation">
|
||||
<div class="inner">{{ doc_sidebar('sidebar') }}</div>
|
||||
</aside>
|
||||
@@ -0,0 +1,15 @@
|
||||
<li class="plugin on">
|
||||
<div class="plugin-screenshot">
|
||||
<img src="{{ url_for('themes/screenshots/' + plugin.name + '.png') }}" class="plugin-screenshot-img">
|
||||
{% if plugin.preview %}
|
||||
<a href="{{ plugin.preview }}" class="plugin-preview-link" target="_blank"><i class="fa fa-eye"></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="{{ plugin.link }}" class="plugin-name" target="_blank">{{ plugin.name }}</a>
|
||||
<p class="plugin-desc">{{ plugin.description }}</p>
|
||||
<div class="plugin-tag-list">
|
||||
{% for tag in plugin.tags %}
|
||||
<a href="#{{ tag }}" class="plugin-tag">{{ tag }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
@@ -0,0 +1,7 @@
|
||||
<div id="content-wrap">
|
||||
<div class="wrapper">
|
||||
<div class="inner">
|
||||
{{ partial('partial/post', {post: page}) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,334 @@
|
||||
html, body, a, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, abbr, acronym, address, big, cite, del, dfn, table, caption, td, th, ins, img, em, kbd, q, s, samp, small, strike, strong, sup, sub, var, tt, dl, dt, dd, ol, ul, li, form, fieldset, label, tr, thead, tfoot, tbody, legend {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-weight: inherit;
|
||||
font-style: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
background: $color-background;
|
||||
font-size: 15px;
|
||||
font-family: $font-sans;
|
||||
color: $color-default;
|
||||
text-rendering: optimizeLegibility;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
&.article-title:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
|
||||
table, caption, td, th {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: inherit;
|
||||
&:before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
&:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
button, select, input, input[type="submit"]::-moz-focus-inner, input[type="button"]::-moz-focus-inner, input[type="reset"]::-moz-focus-inner, button::-moz-focus-inner {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
.inner {
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
#article-toc-inner {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 220px;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
#content-wrap {
|
||||
background: $white;
|
||||
border-top: 1px solid $color-background;
|
||||
border-bottom: 1px solid $color-background;
|
||||
margin: -1px 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
#header {
|
||||
display: none;
|
||||
}
|
||||
.article {
|
||||
padding: 0;
|
||||
}
|
||||
.article-anchor {
|
||||
display: none !important;
|
||||
}
|
||||
.article-content {
|
||||
font-size: 12pt;
|
||||
a {
|
||||
color: $color-default;
|
||||
text-decoration: underline;
|
||||
&:after {
|
||||
content: "(" attr(href) ")";
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.article-footer {
|
||||
display: none;
|
||||
}
|
||||
.article-footer-prev {
|
||||
display: none;
|
||||
}
|
||||
.article-footer-next {
|
||||
display: none;
|
||||
}
|
||||
#comments {
|
||||
display: none;
|
||||
}
|
||||
#footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.toc-link {
|
||||
font-family: $font-title;
|
||||
display: block;
|
||||
color: $color-default;
|
||||
text-decoration: none;
|
||||
padding: 7px 0;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
&.current {
|
||||
color: $color-link;
|
||||
}
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
#content {
|
||||
position: relative;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
#content-inner {
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.post {
|
||||
margin: 0 auto;
|
||||
float: none;
|
||||
.article-title {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
#container {
|
||||
transition: 0.4s;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.fixed #article-toc-inner {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.article-heading:hover .article-anchor {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// Old Styles
|
||||
|
||||
.landing-heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#jumbotron {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div>.highlight-box {
|
||||
margin-top: 40px;
|
||||
display: block;
|
||||
border: 2px solid #ddd;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #ec4f5c;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div>.highlight-box:hover {
|
||||
color: #d32f3d;
|
||||
border: 2px solid #ccc;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div:nth-child(2)>.highlight-box {
|
||||
color: #08bf88;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div:nth-child(2)>.highlight-box:hover {
|
||||
color: #069167;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div:nth-child(3)>.highlight-box {
|
||||
color: #f5a327;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div:nth-child(3)>.highlight-box:hover {
|
||||
color: #ce810d;
|
||||
}
|
||||
|
||||
|
||||
#landing-page .highlight-boxes.chat>div>.highlight-box {
|
||||
color: #0094ff;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes.chat>div>.highlight-box:hover {
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes.chat>div>.highlight-box i, #landing-page .highlight-boxes.chat>div>.highlight-box h3{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#landing-page .highlight-boxes>div>.highlight-box:hover>p {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.highlight-box i {
|
||||
display: block;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
#landing-page h1 {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#landing-page h2 {
|
||||
margin-top: 2em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#landing-page p {
|
||||
color: #888;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#landing-page h4 {
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-weight: bold;
|
||||
padding-bottom: 10px;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#landing-page ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#landing-page ul>li {
|
||||
line-height: 2em; ;
|
||||
}
|
||||
|
||||
#landing-page .row>.col-xs-6:first-child {
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/*-------Tables---------*/
|
||||
|
||||
.docs-content th {
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.docs-content td {
|
||||
border-bottom: 0;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.docs-content tbody>tr {
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.docs-content tr:nth-child(even) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.docs-content table {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
thead>tr>th {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
thead>tr>th:empty {
|
||||
padding: 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#footer {
|
||||
padding: 40px 0;
|
||||
color: $white_60;
|
||||
font-family: $font-title;
|
||||
position: relative;
|
||||
background: $color-background;
|
||||
text-align: center;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
transition: 0.2s;
|
||||
&:hover {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
#footer-copyright {
|
||||
line-height: 1.4;
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
#footer-links {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.footer-link {
|
||||
font-size: 30px;
|
||||
margin-left: 20px;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#header {
|
||||
position: relative;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#header-inner {
|
||||
display: box;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
@media screen and(max-width: 768px) {
|
||||
#header-inner {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
#logo-wrap {
|
||||
box-flex: 1;
|
||||
flex: 0 50px;
|
||||
}
|
||||
#logo {
|
||||
text-indent: 101%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
background: url("/logo.svg");
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-size: 50px 50px;
|
||||
display: block;
|
||||
}
|
||||
#main-nav {
|
||||
display: none;
|
||||
box-flex: 1;
|
||||
flex: 1 auto;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.main-nav-link {
|
||||
color: $white-80;
|
||||
text-decoration: none;
|
||||
line-height: 50px;
|
||||
opacity: 0.7;
|
||||
transition: 0.2s;
|
||||
font-family: $font-title;
|
||||
display: inline-block;
|
||||
padding: 0 15px;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
#search-input-wrap {
|
||||
display: none;
|
||||
padding-left: 6px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid $color-gray;
|
||||
&.on {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
#search-input-icon {
|
||||
color: $white;
|
||||
padding-right: 0.5em;
|
||||
display: inline-block;
|
||||
opacity: 0.7;
|
||||
}
|
||||
#search-input {
|
||||
background: none;
|
||||
font-size: inherit;
|
||||
font-family: $font-title;
|
||||
color: $white;
|
||||
outline: none;
|
||||
}
|
||||
// #lang-select-wrap {
|
||||
// display: none;
|
||||
// position: relative;
|
||||
// }
|
||||
// #lang-select-label {
|
||||
// color: $white;
|
||||
// opacity: 0.7;
|
||||
// font-family: $font-title;
|
||||
// line-height: 50px;
|
||||
// span {
|
||||
// padding-left: 8px;
|
||||
// }
|
||||
// i {
|
||||
// opacity: 0.7;
|
||||
// }
|
||||
// }
|
||||
// #lang-select {
|
||||
// opacity: 0;
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// font-size: inherit;
|
||||
// }
|
||||
@@ -0,0 +1,212 @@
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-weight: inherit;
|
||||
font-style: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: $font-mono;
|
||||
color: $color-emperor;
|
||||
background: $color-gallery;
|
||||
font-size: 0.95em;
|
||||
padding: 10px 15px;
|
||||
line-height: 22px;
|
||||
code {
|
||||
border: none;
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
.comment {
|
||||
color: $color-stack;
|
||||
}
|
||||
.title {
|
||||
color: $color-stack;
|
||||
}
|
||||
.variable {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.attribute {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.tag {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.regexp {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.ruby {
|
||||
.constant {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.symbol {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.class .title {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.function .title {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
.title .keyword {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
}
|
||||
.xml {
|
||||
.pi {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.doctype {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.cdata {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.tag .title {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
}
|
||||
.css {
|
||||
.id {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.class {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.pseudo {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.hexcolor {
|
||||
color: $color-boston-blue;
|
||||
}
|
||||
.rules .attribute {
|
||||
color: $color-limeade;
|
||||
}
|
||||
}
|
||||
.number {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.preprocessor {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.built-in {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.literal {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.params {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.constant {
|
||||
color: $color-carrot-orange;
|
||||
}
|
||||
.class {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.string {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.value {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.inheritance {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.header {
|
||||
color: $color-limeade;
|
||||
}
|
||||
.function {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
.python {
|
||||
.decorator {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
.title {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
}
|
||||
.javascript {
|
||||
.title {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
.function {
|
||||
color: $color-trendy-pink;
|
||||
}
|
||||
}
|
||||
.keyword {
|
||||
color: $color-trendy-pink;
|
||||
}
|
||||
.html .doctype {
|
||||
color: $color-persian-red;
|
||||
}
|
||||
.perl .sub {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
.coffeescript .title {
|
||||
color: $color-san-marino;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-weight: inherit;
|
||||
font-style: inherit;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: $font-mono;
|
||||
color: $color-emperor;
|
||||
background: $color-gallery;
|
||||
font-size: 0.95em;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: $color-gallery;
|
||||
padding: 10px 15px;
|
||||
color: $color-emperor;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
table {
|
||||
margin: 0 !important;
|
||||
border: 0;
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
td {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
figcaption {
|
||||
margin: -5px 0 5px;
|
||||
font-size: 0.9em;
|
||||
color: $color-gray;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
a {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
pre {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
.line {
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#banner {
|
||||
color: $white-80;
|
||||
text-align: center;
|
||||
}
|
||||
#banner-title {
|
||||
padding-top: 20px;
|
||||
font-size: 40px;
|
||||
line-height: 1.15;
|
||||
font-weight: 300;
|
||||
font-family: $font-title;
|
||||
}
|
||||
#banner-start {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
#banner-start-command {
|
||||
background: $color-outer-space;
|
||||
font-family: $font-mono;
|
||||
display: inline-block;
|
||||
padding: 15px 20px;
|
||||
&:before {
|
||||
opacity: 0.5;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
#banner-start-link {
|
||||
color: $white;
|
||||
background: $color-link;
|
||||
display: inline-block;
|
||||
padding: 15px;
|
||||
text-decoration: none;
|
||||
transition: 0.2s;
|
||||
&:hover {
|
||||
background: $color-link-hover;
|
||||
}
|
||||
}
|
||||
#banner-share {
|
||||
display: none;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
#intro-feature-list {
|
||||
padding-top: 20px;
|
||||
display: box;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
.intro-feature-wrap {
|
||||
padding-top: 20px;
|
||||
}
|
||||
.intro-feature {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
.intro-feature-icon {
|
||||
color: $color-link;
|
||||
font-size: 36px;
|
||||
padding-bottom: 26px;
|
||||
text-align: center;
|
||||
}
|
||||
.intro-feature-title {
|
||||
color: $color-link;
|
||||
font-family: $font-title;
|
||||
font-size: 24px;
|
||||
}
|
||||
.intro-feature-desc {
|
||||
margin: 1.6em 0;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
#intro-cmd-wrap {
|
||||
max-width: 700px;
|
||||
background: $color-gallery;
|
||||
padding: 15px 0;
|
||||
margin: 25px -20px 0;
|
||||
}
|
||||
.intro-cmd-item {
|
||||
font-size: 16px;
|
||||
font-family: $font-mono;
|
||||
line-height: 2;
|
||||
padding: 0 30px;
|
||||
&:before {
|
||||
color: $color-link;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
#intro-get-started-wrap {
|
||||
text-align: center;
|
||||
}
|
||||
#intro-get-started-link {
|
||||
font-size: 18px;
|
||||
font-family: $font-title;
|
||||
display: inline-block;
|
||||
color: $color-link;
|
||||
text-decoration: none;
|
||||
margin: 40px 0;
|
||||
border: 3px solid;
|
||||
border-color: $color-link-hover;
|
||||
padding: 12px 24px;
|
||||
position: relative;
|
||||
transition: 0.2s;
|
||||
&:hover {
|
||||
background: $color-link-hover;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
@media screen {
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
.wrapper {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.inner {
|
||||
padding: 0 20px;
|
||||
}
|
||||
#article-toc-inner {
|
||||
padding: 0 20px;
|
||||
}
|
||||
.post {
|
||||
max-width: 800px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and(min-width: 769px) {
|
||||
#main-nav {
|
||||
display: block;
|
||||
}
|
||||
#lang-select-wrap {
|
||||
display: block;
|
||||
}
|
||||
#banner-title {
|
||||
padding-top: 100px;
|
||||
font-size: 50px;
|
||||
}
|
||||
#banner-start {
|
||||
padding: 60px 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
#banner-share {
|
||||
display: block;
|
||||
}
|
||||
#intro-feature-list {
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.intro-feature-wrap {
|
||||
box-flex: 1;
|
||||
flex: 0 0 50%;
|
||||
padding-top: 50px;
|
||||
}
|
||||
.intro-feature {
|
||||
text-align: left;
|
||||
padding-left: 70px;
|
||||
}
|
||||
.intro-feature-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 20px;
|
||||
font-size: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
#intro-cmd-wrap {
|
||||
margin: 50px auto 0;
|
||||
}
|
||||
#sidebar {
|
||||
display: block;
|
||||
}
|
||||
#content-inner {
|
||||
margin-left: 220px;
|
||||
}
|
||||
.article-container {
|
||||
float: right;
|
||||
width: 100%;
|
||||
}
|
||||
.article-inner {
|
||||
margin-right: 220px;
|
||||
}
|
||||
#article-toc {
|
||||
display: block;
|
||||
}
|
||||
.article-edit-link {
|
||||
display: block;
|
||||
}
|
||||
#mobile-nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
#footer {
|
||||
text-align: left;
|
||||
}
|
||||
#footer-copyright {
|
||||
float: left;
|
||||
}
|
||||
#footer-links {
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#mobile-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 260px;
|
||||
left: -260px;
|
||||
height: 100%;
|
||||
background: $color-background;
|
||||
transition: 0.4s;
|
||||
font-family: $font-title;
|
||||
}
|
||||
.mobile-nav-on {
|
||||
#mobile-nav {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
#mobile-nav-toggle {
|
||||
opacity: 1;
|
||||
}
|
||||
.mobile-nav-toggle-bar {
|
||||
&:first-child {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
&:nth-child(2) {
|
||||
opacity: 0;
|
||||
}
|
||||
&:last-child {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
#container {
|
||||
transform: translateX(260px);
|
||||
overflow: hidden;
|
||||
}
|
||||
#mobile-nav-dimmer {
|
||||
opacity: 0.7;
|
||||
transform: translateX(-100%);
|
||||
transition: opacity 0.4s;
|
||||
}
|
||||
}
|
||||
#mobile-nav-inner {
|
||||
overflow-y: auto;
|
||||
padding: 10px 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 40px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
#mobile-nav-toggle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 20px;
|
||||
width: 25px;
|
||||
height: 20px;
|
||||
margin: auto;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
&:active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.mobile-nav-toggle-bar {
|
||||
background: $white;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
transition: 0.4s;
|
||||
transform-origin: 0;
|
||||
border-radius: 2px;
|
||||
&:first-child {
|
||||
top: 0;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
top: 9px;
|
||||
}
|
||||
&:last-child {
|
||||
top: 18px;
|
||||
}
|
||||
}
|
||||
.mobile-nav-link {
|
||||
color: $white;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.mobile-nav-title {
|
||||
color: $color-link;
|
||||
font-weight: bold;
|
||||
padding: 10px 15px;
|
||||
line-height: 1;
|
||||
display: block;
|
||||
border-top: 1px solid $color-default;
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#mobile-nav-dimmer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: $black;
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s, transform 0s 0.4s;
|
||||
}
|
||||
|
||||
#mobile-lang-select-wrap {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: $color-background;
|
||||
border-top: 1px solid $color-default;
|
||||
}
|
||||
#mobile-lang-select-label {
|
||||
line-height: 40px;
|
||||
color: $white;
|
||||
padding: 10px 15px;
|
||||
i {
|
||||
opacity: 0.7;
|
||||
}
|
||||
span {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
#mobile-lang-select {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
.article-date {
|
||||
color: $color-gray;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
margin-top: 1em;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
.article-edit-link {
|
||||
float: right;
|
||||
color: $color-pink-swan;
|
||||
font-size: 24px;
|
||||
line-height: 36px;
|
||||
transition: 0.2s;
|
||||
display: none;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
.article-anchor {
|
||||
margin-left: 10px;
|
||||
display: none;
|
||||
&:before {
|
||||
content: "#";
|
||||
}
|
||||
}
|
||||
.article-content {
|
||||
line-height: 1.6em;
|
||||
color: $color-default;
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
ol {
|
||||
margin: 1em 0;
|
||||
margin-left: 20px;
|
||||
list-style: decimal;
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ol {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
margin: 1em 0;
|
||||
margin-left: 20px;
|
||||
list-style: disc;
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ol {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
dl {
|
||||
margin: 1em 0;
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ol {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
max-width: 100%;
|
||||
border: 1px solid $color-border;
|
||||
th {
|
||||
font-weight: bold;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
td {
|
||||
padding: 5px 15px;
|
||||
}
|
||||
tr:nth-child(2n) {
|
||||
background: $color-gallery;
|
||||
}
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
border: 1px solid $color-border;
|
||||
border-left: 5px solid $color-alto;
|
||||
footer {
|
||||
margin: 1em 0;
|
||||
font-style: italic;
|
||||
cite {
|
||||
&:before {
|
||||
content: "—";
|
||||
padding: 0 0.3em;
|
||||
}
|
||||
a {
|
||||
color: color-grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
iframe {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.highlight {
|
||||
margin: 1em 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.3em;
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
h4 {
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
h5 {
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
h6 {
|
||||
line-height: 1em;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: $color-link;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
li {
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0;
|
||||
}
|
||||
iframe {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.highlight {
|
||||
margin: 1em 0;
|
||||
}
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
video {
|
||||
max-width: 100%;
|
||||
}
|
||||
.note {
|
||||
&.tip {
|
||||
border-left-color: $color-yellow-sea;
|
||||
}
|
||||
&.info {
|
||||
border-left-color: $color-link-hover;
|
||||
}
|
||||
&.warn {
|
||||
border-left-color: $red;
|
||||
}
|
||||
}
|
||||
.note-title {
|
||||
margin: 1em 0;
|
||||
display: block;
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.article-footer {
|
||||
margin: 1em 0;
|
||||
border-top: 1px solid $color-border;
|
||||
text-align: center;
|
||||
color: $color-gray;
|
||||
line-height: 1em;
|
||||
padding-top: 1em;
|
||||
position: relative;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
.article-footer-prev {
|
||||
color: $color-link;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-family: $font-title;
|
||||
text-transform: uppercase;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
span {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
.article-footer-next {
|
||||
color: $color-link;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-family: $font-title;
|
||||
text-transform: uppercase;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
span {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
.article-footer-updated {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
|
||||
#article-toc-top {
|
||||
margin-top: 2em;
|
||||
font-size: 0.9em;
|
||||
text-decoration: none;
|
||||
color: $color-default;
|
||||
display: block;
|
||||
margin-bottom: 40px;
|
||||
font-family: $font-title;
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
.article-header {
|
||||
padding-bottom: 20px;
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
.article-title {
|
||||
float: left;
|
||||
font-family: $font-title;
|
||||
font-size: 36px;
|
||||
font-weight: 300;
|
||||
text-decoration: none;
|
||||
color: $color-default;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.article-inner {
|
||||
&:before {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
.article {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 40px 0;
|
||||
}
|
||||
#article-toc {
|
||||
display: none;
|
||||
float: right;
|
||||
width: 220px;
|
||||
margin-right: -220px;
|
||||
opacity: 0.8;
|
||||
&.fixed {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 220px;
|
||||
}
|
||||
}
|
||||
.toc-child {
|
||||
padding-left: 1em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#sidebar {
|
||||
width: 220px;
|
||||
float: left;
|
||||
padding-bottom: 40px;
|
||||
opacity: 0.8;
|
||||
margin-left: -220px;
|
||||
display: none;
|
||||
}
|
||||
.sidebar-title {
|
||||
margin-top: 20px;
|
||||
font-size: 0.75;
|
||||
padding: 10px 0;
|
||||
font-family: $font-title;
|
||||
font-weight: 400;
|
||||
color: #ccc;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.sidebar-link {
|
||||
font-family: $font-title;
|
||||
display: block;
|
||||
color: $color-default;
|
||||
text-decoration: none;
|
||||
padding: 7px 0;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
&.current {
|
||||
color: $color-link;
|
||||
font-weight: bold;
|
||||
}
|
||||
&:hover {
|
||||
color: $color-link-hover;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
//colors
|
||||
$black: #000;
|
||||
|
||||
$white: #fff;
|
||||
$white-80: rgba(255,255,255,0.8);
|
||||
$white-60: rgba(255,255,255,0.6);
|
||||
|
||||
$red: #f00;
|
||||
|
||||
$color-gray: #999;
|
||||
$color-default: #444;
|
||||
$color-border: #e3e3e3;
|
||||
$color-link: #0094ff;
|
||||
$color-link-hover: #005999;
|
||||
$color-background: #24262F;
|
||||
|
||||
$color-gallery: #eee;
|
||||
$color-alto: #ddd;
|
||||
$color-pink-swan: #bbb;
|
||||
|
||||
$color-outer-space: #283542;
|
||||
$color-yellow-sea: #fa0;
|
||||
$color-emperor: #4d4d4c;
|
||||
$color-stack: #8e908c;
|
||||
$color-persian-red: #c82829;
|
||||
$color-carrot-orange: #f5871f;
|
||||
$color-limeade: #718c00;
|
||||
$color-boston-blue: #3e999f;
|
||||
$color-san-marino: #4271ae;
|
||||
$color-trendy-pink: #8959a8;
|
||||
|
||||
// Typography
|
||||
$font-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
$font-serif: Garamond, Georgia, "Times New Roman", serif;
|
||||
$font-mono: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
$font-title: "Fira Sans", font-sans;
|
||||
$font-size: 15px;
|
||||
$line-height: 1.6em;
|
||||
|
||||
// Layout
|
||||
$max-width: 1200px;
|
||||
$gutter-width: 20px;
|
||||
$sidebar-width: 220px;
|
||||
$mobile-nav-width: 260px;
|
||||
|
||||
// Media queries
|
||||
$mq-mobile: "screen and (max-width: 768px)";
|
||||
$mq-normal: "screen and (min-width: 769px)";
|
||||
$mq-tablet: "screen and (min-width: 480px)";
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
@import "_variables";
|
||||
|
||||
@import "_partial/base";
|
||||
@import "_partial/header";
|
||||
@import "_partial/index";
|
||||
@import "_partial/sidebar";
|
||||
@import "_partial/page";
|
||||
@import "_partial/mobile_nav";
|
||||
@import "_partial/footer";
|
||||
@import "_partial/highlight";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
function changeLang(){
|
||||
var lang = this.value;
|
||||
var canonical = this.dataset.canonical;
|
||||
if (lang === 'en') lang = '';
|
||||
if (lang) lang += '/';
|
||||
|
||||
location.href = '/' + lang + canonical;
|
||||
}
|
||||
|
||||
document.getElementById('lang-select').addEventListener('change', changeLang);
|
||||
document.getElementById('mobile-lang-select').addEventListener('change', changeLang);
|
||||
})();
|
||||
@@ -0,0 +1,23 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
var navToggle = document.getElementById('mobile-nav-toggle');
|
||||
var container = document.getElementById('container');
|
||||
var dimmer = document.getElementById('mobile-nav-dimmer');
|
||||
var CLASS_NAME = 'mobile-nav-on';
|
||||
if (!navToggle) return;
|
||||
|
||||
navToggle.addEventListener('click', function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
body.classList.toggle(CLASS_NAME);
|
||||
});
|
||||
|
||||
dimmer.addEventListener('click', function(e){
|
||||
if (!body.classList.contains(CLASS_NAME)) return;
|
||||
|
||||
e.preventDefault();
|
||||
body.classList.remove(CLASS_NAME);
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,112 @@
|
||||
/*! https://mths.be/scrollingelement v1.5.2 by @diegoperini & @mathias | MIT license */
|
||||
if (!('scrollingElement' in document)) (function() {
|
||||
|
||||
function computeStyle(element) {
|
||||
if (window.getComputedStyle) {
|
||||
// Support Firefox < 4 which throws on a single parameter.
|
||||
return getComputedStyle(element, null);
|
||||
}
|
||||
// Support Internet Explorer < 9.
|
||||
return element.currentStyle;
|
||||
}
|
||||
|
||||
function isBodyElement(element) {
|
||||
// The `instanceof` check gives the correct result for e.g. `body` in a
|
||||
// non-HTML namespace.
|
||||
if (window.HTMLBodyElement) {
|
||||
return element instanceof HTMLBodyElement;
|
||||
}
|
||||
// Fall back to a `tagName` check for old browsers.
|
||||
return /body/i.test(element.tagName);
|
||||
}
|
||||
|
||||
function getNextBodyElement(frameset) {
|
||||
// We use this function to be correct per spec in case `document.body` is
|
||||
// a `frameset` but there exists a later `body`. Since `document.body` is
|
||||
// a `frameset`, we know the root is an `html`, and there was no `body`
|
||||
// before the `frameset`, so we just need to look at siblings after the
|
||||
// `frameset`.
|
||||
var current = frameset;
|
||||
while (current = current.nextSibling) {
|
||||
if (current.nodeType == 1 && isBodyElement(current)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
// No `body` found.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Note: standards mode / quirks mode can be toggled at runtime via
|
||||
// `document.write`.
|
||||
var isCompliantCached;
|
||||
var isCompliant = function() {
|
||||
var isStandardsMode = /^CSS1/.test(document.compatMode);
|
||||
if (!isStandardsMode) {
|
||||
// In quirks mode, the result is equivalent to the non-compliant
|
||||
// standards mode behavior.
|
||||
return false;
|
||||
}
|
||||
if (isCompliantCached === void 0) {
|
||||
// When called for the first time, check whether the browser is
|
||||
// standard-compliant, and cache the result.
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.height = '1px';
|
||||
(document.body || document.documentElement || document).appendChild(iframe);
|
||||
var doc = iframe.contentWindow.document;
|
||||
doc.write('<!DOCTYPE html><div style="height:9999em">x</div>');
|
||||
doc.close();
|
||||
isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight;
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
}
|
||||
return isCompliantCached;
|
||||
};
|
||||
|
||||
function isRendered(style) {
|
||||
return style.display != 'none' && !(style.visibility == 'collapse' &&
|
||||
/^table-(.+-group|row|column)$/.test(style.display));
|
||||
}
|
||||
|
||||
function isScrollable(body) {
|
||||
// A `body` element is scrollable if `body` and `html` both have
|
||||
// non-`visible` overflow and are both being rendered.
|
||||
var bodyStyle = computeStyle(body);
|
||||
var htmlStyle = computeStyle(document.documentElement);
|
||||
return bodyStyle.overflow != 'visible' && htmlStyle.overflow != 'visible' &&
|
||||
isRendered(bodyStyle) && isRendered(htmlStyle);
|
||||
}
|
||||
|
||||
var scrollingElement = function() {
|
||||
if (isCompliant()) {
|
||||
return document.documentElement;
|
||||
}
|
||||
var body = document.body;
|
||||
// Note: `document.body` could be a `frameset` element, or `null`.
|
||||
// `tagName` is uppercase in HTML, but lowercase in XML.
|
||||
var isFrameset = body && !/body/i.test(body.tagName);
|
||||
body = isFrameset ? getNextBodyElement(body) : body;
|
||||
// If `body` is itself scrollable, it is not the `scrollingElement`.
|
||||
return body && isScrollable(body) ? null : body;
|
||||
};
|
||||
|
||||
if (Object.defineProperty) {
|
||||
// Support modern browsers that lack a native implementation.
|
||||
Object.defineProperty(document, 'scrollingElement', {
|
||||
'get': scrollingElement
|
||||
});
|
||||
} else if (document.__defineGetter__) {
|
||||
// Support Firefox ≤ 3.6.9, Safari ≤ 4.1.3.
|
||||
document.__defineGetter__('scrollingElement', scrollingElement);
|
||||
} else {
|
||||
// IE ≤ 4 lacks `attachEvent`, so it only gets this one assignment. IE ≤ 7
|
||||
// gets it too, but the value is updated later (see `propertychange`).
|
||||
document.scrollingElement = scrollingElement();
|
||||
document.attachEvent && document.attachEvent('onpropertychange', function() {
|
||||
// This is for IE ≤ 7 only.
|
||||
// A `propertychange` event fires when `<body>` is parsed because
|
||||
// `document.activeElement` then changes.
|
||||
if (window.event.propertyName == 'activeElement') {
|
||||
document.scrollingElement = scrollingElement();
|
||||
}
|
||||
});
|
||||
}
|
||||
}());
|
||||
@@ -0,0 +1,31 @@
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var header = document.getElementById('header');
|
||||
var toc = document.getElementById('article-toc');
|
||||
var tocTop = document.getElementById('article-toc-top');
|
||||
var headerHeight = header.clientHeight;
|
||||
|
||||
if (!toc) return;
|
||||
|
||||
function updateSidebarPosition(){
|
||||
var scrollTop = document.scrollingElement.scrollTop;
|
||||
|
||||
if (scrollTop > headerHeight){
|
||||
toc.classList.add('fixed');
|
||||
} else {
|
||||
toc.classList.remove('fixed');
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function(){
|
||||
window.requestAnimationFrame(updateSidebarPosition);
|
||||
});
|
||||
|
||||
updateSidebarPosition();
|
||||
|
||||
tocTop.addEventListener('click', function(e){
|
||||
e.preventDefault();
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user