Compare commits

..

40 Commits

Author SHA1 Message Date
Steven
21fe0a2006 Publish Stable
- @now/build-utils@1.1.0
 - now@16.6.0
 - now-client@5.2.4
 - @now/next@2.1.0
 - @now/node@1.2.0
 - @now/static-build@0.13.0
2019-11-21 13:14:17 -05:00
Steven
23acd3cec6 Publish Canary
- @now/build-utils@1.0.1-canary.4
 - now@16.5.3-canary.6
 - @now/routing-utils@1.3.4-canary.2
2019-11-21 11:45:19 -05:00
Steven
7892f88a42 [now-build-utils] Ignore engines for yarn run (#3341)
Fixes a confusing error message.

<details>
<summary>Click to view error message</summary>
<pre>> Ready! Available at http://localhost:3000
> Building @now/node:index.js
Installing dependencies...
Running "yarn run now-build"
yarn run v1.17.3
error @: The engine "node" is incompatible with this module. Expected version "10.x". Got "12.13.1"
error Commands cannot run with an incompatible environment.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Error: Exited with 1
    at ChildProcess.<anonymous> (/Users/styfle/Library/Caches/co.zeit.now/dev/builders/node_modules/@now/node/dist/index.js:78518:24)
    at ChildProcess.emit (events.js:210:5)
    at ChildProcess.EventEmitter.emit (domain.js:475:20)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5) {
  message: 'Exited with 1'
}</pre>
</details>



The `--ignore-engines` flag was added to `yarn install` many months ago but not `yarn run`.

This PR adds the flag to `yarn run`.

This is useful in `now dev` when the user might have a different Node version installed than what is specified by `engines` in `package.json`.
2019-11-21 16:41:55 +00:00
Steven
aae0e3bec7 Revert [now-cli][now-routing-utils] Add support for v4 builders #3311 (#3333)
Reverts #3311

Previously, we thought we were going to use version 4 to support builder rewrites/redirects => routes. But that is no longer necessary. So instead version 4 will be builders that accept multiple file entrypoints.

Until v4 can be implemented, this reverts v4 changes.

Additionally, I added a helpful error message when the CLI does not support the builder version. In a future PR, we will add better version locking to avoid this type of version mismatch.
2019-11-21 15:49:33 +00:00
Steven
0f8bf39421 Publish Canary
- now@16.5.3-canary.5
 - @now/next@2.0.1-canary.1
 - @now/node@1.1.3-canary.2
 - @now/static-build@0.12.3-canary.2
2019-11-20 15:33:13 -05:00
Steven
36fd96cc6c Publish Canary
- @now/build-utils@1.0.1-canary.3
2019-11-20 11:19:07 -05:00
Steven
3de08e9f3b [now-build-utils] Fix canary selection for static build (#3339)
We expect `now@canary` to use canary builders. This PR fixes a bug where a zero config deployment was selecting `@now/static-build` instead of `@now/static-build@canary`.
2019-11-20 16:17:55 +00:00
Steven
3e739724b3 Publish Canary
- @now/build-utils@1.0.1-canary.2
 - now@16.5.3-canary.4
 - now-client@5.2.4-canary.2
 - @now/node@1.1.3-canary.1
 - @now/static-build@0.12.3-canary.1
2019-11-20 08:55:18 -05:00
Nathan Rajlich
847e538c69 [now-cli] Render an error message when the --token content is invalid (#3335)
Fixes #3334.

```
$ node ~/now-cli/dist/index.js --token $'he˚ll,o\n'
> Error! You defined "--token", but its contents are invalid. Must not contain: "\n", ",", "˚"
> More details: https://err.sh/now/invalid-token-value
```
2019-11-20 11:05:45 +00:00
Nathan Rajlich
64684dd486 [now-build-utils] Run detectors unit tests (#3336)
Renames `test/unit.test.detectors.ts` -> `test/unit.detectors.test.ts`
and adjusts npm `test-unit` command.

Jest only runs tests for files that end in `*.test.ts` or `*.test.js`.
2019-11-19 18:48:15 -08:00
Steven
a229747249 [now-build-utils][now-static-build][now-node] Add node 12.x (#3330)
This PR adds support for Node 12 when the user defines `engines` in their `package.json`
2019-11-20 02:34:01 +00:00
Nathan Rajlich
d1b59c3543 [now-build-utils] Add framework detector functions (#3296)
* [now-build-utils] Add framework detector functions

As described in [PRODUCT-399]. This is similar in nature to the
current framework detection logic in static-build, however the detectors
are now functions which allow for detection of frameworks without
a `package.json` file (i.e. jekyll), and also includes detection of
build and dev commands for use in project settings.

* Dedup `aggregate-error` dep in yarn.lock

* Simplify `hasDependency()`

* Adjust hugo detect logic

* Add "jekyll" detector

* Add "next" detector

* Optimize "gatsby" detector

Check the `package.json` first

* Add optimization to check "package.json" based detectors first

They're by far the most common and only rely on checking the single
`package.json` file. If no pkg-based detector succeeds then the non-pkg
detectors are consulted afterwards.

* Add "vue" detector

* Add "angular" detector

* Add "polymer" detector

* Add "svelte" detector

* Add "create-react-app-ejected" detector

* Add "gridsome" detector

* Add "umi" detector

* Add "sapper" detector

* Add "saber" detector

* Add "stencil" detector

* Add CRA ejected commands

* Add "brunch" detector

* Add "middleman" detector

* Add missing commands

* `buildCommand` is required

* Add initial unit tests

* Fix unit tests on Circle

* Move "jest" and "ts-jest" to the root of the monorepo

* Fix integration tests

* Fix test again

* Update packages/now-build-utils/src/detectors/middleman.ts

Co-Authored-By: Steven <steven@ceriously.com>

* Move `@types/jest` to root level package.json

* Update packages/now-build-utils/src/detectors/ember.ts

Co-Authored-By: Steven <steven@ceriously.com>

* Add `cachePattern`

* Address PR comments

* Add missing `$PORT` entries for devCommands

* Add `firstTruthy()` tests

* Revert some changes

Maybe it fixes CI build?

* Test remove `yaml` module

* Update packages/now-build-utils/src/detectors/next.ts

* Remove `toml`

* Test out "@iarna/toml" module

* Fix build

* Test out "js-yaml" module

* Add new routing properties

* Rename `test/unit.test.ts` to `test/unit.test.detectors.ts`

* Remove `@types/yaml`
2019-11-19 17:16:49 -08:00
JJ Kasper
b241441e37 Publish Canary
- now@16.5.3-canary.3
 - @now/next@2.0.1-canary.0
2019-11-19 15:06:43 -06:00
JJ Kasper
40bfa25b1b [now-next] Fix custom routes order (#3327)
This updates the routes order to make sure `_next/*` routes are at the top so that custom `rewrites`/`redirects` don't conflict with them

x-ref: https://github.com/zeit/next.js/issues/9081#issuecomment-555161265
2019-11-19 21:05:02 +00:00
Nathan Rajlich
c5a4386c1d [now-cli] Update @zeit/fun to v0.10.4 (#3332)
Possibly fixes #3323 (because of zeit/fun#43).
2019-11-19 20:32:36 +00:00
Nathan Rajlich
b3aa3be4b8 [CircleCI] Remove rsync apt-get install (#3329)
Used to be used in the now-cli build script when it was a bash script.
Now it's a TypeScript file and the `cpy` module is used instead.
2019-11-19 08:55:42 +01:00
Steven
528aefcc1e [now-cli] Handle uv_cwd error when cwd is deleted (#3326)
Converts `reportError()` to typescript and adds an ignore list.

In particular, `uv_cwd` comes from `process.cwd()` so we don't need to track these errors in the case the user deletes their current working directory.

This is a follow up to #3194 which handled only one scenario.
2019-11-18 22:27:46 +00:00
Andy
620ee2b7e4 [now-cli] Ensure that stdin exists when calling setRawMode (#3321)
Ensure that `stdin` exists when calling `setRawMode`.

[Error on Sentry](https://sentry.io/organizations/zeithq/issues/1310516610/?project=1323225)

[PRODUCT-637]

[PRODUCT-637]: https://zeit.atlassian.net/browse/PRODUCT-637
2019-11-18 21:22:29 +00:00
Andy Bitz
d55acc246a Publish Canary
- @now/build-utils@1.0.1-canary.1
2019-11-18 11:54:08 +01:00
Andy
2a59db3029 [now-build-utils] Ensure function paths are relative to the project and improve the error message (#3312)
* [now-build-utils] Ensure function paths are relative to the project and improve the error message

* Update packages/now-build-utils/src/detect-builders.ts

Co-Authored-By: Steven <steven@ceriously.com>

* Update packages/now-build-utils/src/detect-builders.ts

Co-Authored-By: Steven <steven@ceriously.com>
2019-11-15 18:56:23 +01:00
Andy Bitz
990dec0fec Publish Stable
- @now/next@2.0.0
2019-11-15 15:33:18 +01:00
Andy
162b17b249 [now-next] Make lambda memory more reliable (#3319) 2019-11-15 15:28:28 +01:00
Steven
e0aea30618 Publish Canary
- now@16.5.3-canary.2
 - @now/routing-utils@1.3.4-canary.1
2019-11-14 16:00:47 -05:00
Steven
49cba94178 [now-cli][now-routing-utils] Add support for v4 builders (#3311)
- Add now dev `BuildResultV4` type similar to V3 but no routes, only superstatic keys
- Add validation to `@now/routing-utils` to ensure V4 Builders do not return `routes`

Note, no builders have been changed yet because this needs to be shipped first so we can bump build-utils and then builders will work in production. Then in a separate PR, we can update builders to V4.
2019-11-14 20:48:13 +00:00
Steven
7dd87815f3 Publish Canary
- now@16.5.3-canary.1
 - now-client@5.2.4-canary.1
2019-11-14 14:18:50 -05:00
Steven
f6fdde816f [now-client] Fix publish output (#3315)
Fixes #3310

The root `package.json` file is copied to `dist` by tsc because of a relative import. This causes npm `files` property to be nested and therefore skip publishing most of the files.

```ts
import pkg from '../../package.json';
```

Disabling `resolveJsonModule` and using `require()` instead fixed it.

However, this change caused `now-cli` build to fail so I had to change the way `now-client` gets imported.
2019-11-14 19:09:03 +00:00
Steven
4c8c6ff236 [script] Cleanup changelog script (#3306)
This script is only used for stable releases so we should filter out canary publish commits.
2019-11-14 18:31:04 +00:00
Steven
46b615a963 [now-cli] Fix localConfig when file is above the target directory (#3293)
Fixes #3209
2019-11-14 18:00:39 +00:00
Steven
8e293dd633 Publish Canary
- gatsby-plugin-now@1.2.6-canary.0
 - @now/build-utils@1.0.1-canary.0
 - @now/cgi@1.0.1-canary.0
 - now@16.5.3-canary.0
 - now-client@5.2.4-canary.0
 - @now/go@1.0.1-canary.0
 - @now/next@1.0.6-canary.0
 - @now/node-bridge@1.2.7-canary.1
 - @now/node@1.1.3-canary.0
 - @now/python@1.0.1-canary.0
 - @now/routing-utils@1.3.4-canary.0
 - @now/ruby@1.0.1-canary.0
 - @now/static-build@0.12.3-canary.0
2019-11-13 10:28:12 -05:00
Thew Dhanat
e040753b27 [now-node] Ignore babel.config.js (#3295)
@now/node shouldn't read user's Babel configuration.
Fix #3280
2019-11-13 14:36:33 +00:00
Andy
463aaf094d [now-cli] Make lambda memory test more consistent (#3301)
Make lambda memory test more consistent
2019-11-13 11:21:53 +00:00
Steven
bf867b028d [tests] Always test now-cli (#3305)
Previously, only the changed package's tests would run.

This PR makes sure that the changed package + `now-cli` tests run every time.
2019-11-13 02:32:02 +00:00
Steven
6dfefc2fe4 Publish Stable
- gatsby-plugin-now@1.2.5
 - now@16.5.2
 - @now/node@1.1.2
 - @now/static-build@0.12.2
2019-11-12 18:52:28 -05:00
Steven
9ba8a8454c Bump versions 2019-11-12 18:51:32 -05:00
Steven
9c72839bfa Empty commit 2019-11-12 18:48:26 -05:00
Steven
2e24c92799 Publish Canary
- gatsby-plugin-now@1.2.4-canary.0
 - @now/node@1.1.1-canary.0
 - @now/static-build@0.12.1-canary.0
2019-11-12 18:18:17 -05:00
Andy
fa98c8aeeb Revert "[now-static-build] Inject gatsby-plugin-now in Gatsby deployments (#3182)" (#3303)
This reverts the following gatsby changes:

- Reverts #3182
- Reverts #3260
- Reverts #3212
2019-11-12 23:13:39 +00:00
Steven
f92e3496b1 [now-node] Bump now-node-bridge (#3304)
A trivial change to follow up to #3300 so that the latest `@now/node-bridge` is bundled with `ncc`.
2019-11-12 22:37:49 +00:00
Steven
0ceea76aa4 Publish Canary
- now@16.5.1-canary.0
 - @now/node-bridge@1.2.7-canary.0
2019-11-12 14:57:22 -05:00
Steven
897d11a1e1 [now-node] Disable default node timeout (#3300)
Node had a default [timeout](https://nodejs.org/api/http.html#http_server_timeout) of 2 minutes until Node 13.x so we'll need to manually disable the timeout so that the `maxDuration` config works properly.
2019-11-12 19:54:05 +00:00
186 changed files with 16836 additions and 579 deletions

View File

@@ -63,9 +63,6 @@ jobs:
working_directory: ~/repo
steps:
- checkout
- run:
name: Installing apt dependencies
command: sudo apt install -y rsync
- attach_workspace:
at: .
- run:

View File

@@ -4,6 +4,9 @@ dist
# gatsby-plugin-now
packages/gatsby-plugin-now/test/fixtures
# now-build-utils
packages/now-build-utils/test/fixtures
# now-cli
packages/now-cli/@types
packages/now-cli/download

View File

@@ -283,6 +283,7 @@ This is a [JavaScript class](https://developer.mozilla.org/en-US/docs/Web/JavaSc
This is an abstract enumeration type that is implemented by one of the following possible `String` values:
- `nodejs12.x`
- `nodejs10.x`
- `nodejs8.10`
- `go1.x`

View File

@@ -12,7 +12,12 @@ if (!commit) {
throw new Error('Unable to find last publish commit');
}
const log = execSync(`git log --pretty=format:"- %s [%an]" ${commit}...HEAD`).toString().trim();
const log = execSync(`git log --pretty=format:"- %s [%an]" ${commit}...HEAD`)
.toString()
.trim()
.split('\n')
.filter(line => !line.startsWith('- Publish Canary '))
.join('\n');
console.log(`Changes since the last publish commit ${commit}:`);
console.log(`Changes since the last Stable release (${commit.slice(0, 7)}):`);
console.log(`\n${log}\n`);

View File

@@ -0,0 +1,11 @@
# Invalid Token Value
#### Why This Error Occurred
The `--token` flag was specified, but its contents are invalid.
#### Possible Ways to Fix It
The `--token` flag must only contain numbers (0-9) and letters from the alphabet (a-z and A-Z). This needs to be the token of the user account as which you'd like to act.
You can either get the token from the `./now/auth.json` file located in your user directory or [from the dashboard](https://zeit.co/account/tokens).

View File

@@ -6,6 +6,10 @@ const REDIRECT_FILE_NAME = '__now_routes_g4t5bY.json';
exports.onPostBuild = async ({ store }) => {
const { redirects, program } = store.getState();
if (!redirects.length === 0) {
return;
}
const routes = [{ handle: 'filesystem' }];
for (const redirect of redirects) {
@@ -22,30 +26,8 @@ exports.onPostBuild = async ({ store }) => {
}
}
// we implement gatsby's recommendations
// https://www.gatsbyjs.org/docs/caching/
const finalRoutes = [
{
src: '^/static/(.*)$',
headers: { 'cache-control': 'public,max-age=31536000,immutable' },
continue: true,
},
{
src: '^/.*\\.(js|css)$',
headers: { 'cache-control': 'public,max-age=31536000,immutable' },
continue: true,
},
{
src: '^/(sw\\.js|app-data\\.json|.*\\.html|page-data/.*)$',
headers: { 'cache-control': 'public,max-age=0,must-revalidate' },
continue: true,
},
...routes,
{ src: '.*', status: 404, dest: '/404.html' },
];
await writeFile(
path.join(program.directory, 'public', REDIRECT_FILE_NAME),
JSON.stringify(finalRoutes)
JSON.stringify(routes)
);
};

View File

@@ -1,6 +1,6 @@
{
"name": "gatsby-plugin-now",
"version": "1.2.3",
"version": "1.2.6-canary.0",
"main": "index.js",
"license": "MIT",
"homepage": "https://zeit.co/guides/deploying-gatsby-with-now",

View File

@@ -1,7 +1,24 @@
# gatsby-plugin-now
⚠️ The use of this plugin is deprecated. ZEIT Now supports Gatsby Redirects out-of-the-box and does not require the use a plugin.
---
This plugin generates [Now Routes](https://zeit.co/docs/v2/advanced/routes) for [redirects](https://www.gatsbyjs.org/docs/actions/#createRedirect) you configured for to your Gatsby project.
### Usage
1. Install the plugin:
```
npm install gatsby-plugin-now --save-dev
```
2. Add it to the configuration file:
```
// gatsby-config.js
module.exports = {
plugins: [
'gatsby-plugin-now'
]
}
```
3. [Deploy your project to ZEIT Now](https://www.gatsbyjs.org/docs/deploying-to-zeit-now/)

View File

@@ -2,27 +2,6 @@
exports[`test generated now routes 1`] = `
Array [
Object {
"continue": true,
"headers": Object {
"cache-control": "public,max-age=31536000,immutable",
},
"src": "^/static/(.*)$",
},
Object {
"continue": true,
"headers": Object {
"cache-control": "public,max-age=31536000,immutable",
},
"src": "^/.*\\\\.(js|css)$",
},
Object {
"continue": true,
"headers": Object {
"cache-control": "public,max-age=0,must-revalidate",
},
"src": "^/(sw\\\\.js|app-data\\\\.json|.*\\\\.html|page-data/.*)$",
},
Object {
"headers": Object {
"Location": "/",
@@ -103,10 +82,5 @@ Array [
"src": "/randorect",
"status": 302,
},
Object {
"dest": "/404.html",
"src": ".*",
"status": 404,
},
]
`;

View File

@@ -1,3 +1,4 @@
?.js
dist
test/symlinks-out
test/symlinks.zip

View File

@@ -1,6 +1,12 @@
#!/bin/sh
set -eu
out="dist"
rm -rf "$out"
tsc
rm dist/index.js
ncc build src/index.ts -o dist/main
mv dist/main/index.js dist/index.js
rm -rf dist/main
rm "$out/index.js"
ncc build "src/index.ts" -o "$out/main"
mv "$out/main/index.js" "$out/index.js"
rm -rf "$out/main"

View File

@@ -0,0 +1,5 @@
module.exports = {
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
};

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "1.0.0",
"version": "1.1.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -12,20 +12,24 @@
},
"scripts": {
"build": "./build.sh",
"test-unit": "jest --env node --verbose --runInBand test/unit.test.js",
"test-unit": "jest --env node --verbose --runInBand test/unit.*test.*",
"test-integration-once": "jest --env node --verbose --runInBand test/integration.test.js",
"prepublishOnly": "./build.sh"
},
"devDependencies": {
"@iarna/toml": "2.2.3",
"@types/async-retry": "^1.2.1",
"@types/cross-spawn": "6.0.0",
"@types/end-of-stream": "^1.4.0",
"@types/fs-extra": "^5.0.5",
"@types/glob": "^7.1.1",
"@types/jest": "24.0.22",
"@types/js-yaml": "3.12.1",
"@types/multistream": "2.1.1",
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",
"async-sema": "2.1.4",
"cross-spawn": "6.0.5",
@@ -34,10 +38,13 @@
"fs-extra": "7.0.0",
"glob": "7.1.3",
"into-stream": "5.0.0",
"jest": "24.9.0",
"js-yaml": "3.13.1",
"minimatch": "3.0.4",
"multistream": "2.1.1",
"node-fetch": "2.2.0",
"semver": "6.1.1",
"ts-jest": "24.1.0",
"typescript": "3.5.2",
"yazl": "2.4.3"
}

View File

@@ -96,6 +96,8 @@ async function detectFrontBuilder(
builders: Builder[],
options: Options
): Promise<Builder> {
const { tag } = options;
const withTag = tag ? `@${tag}` : '';
for (const [dependency, builder] of getBuilders(options)) {
const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
@@ -121,7 +123,7 @@ async function detectFrontBuilder(
}
// By default we'll choose the `static-build` builder
return { src, use: '@now/static-build', config };
return { src, use: `@now/static-build${withTag}`, config };
}
// Files that match a specific pattern will get ignored
@@ -286,6 +288,13 @@ function validateFunctions(files: string[], { functions = {} }: Options) {
};
}
if (path.startsWith('/')) {
return {
code: 'invalid_function_source',
message: `The function path "${path}" is invalid. The path must be relative to your project root and therefore cannot start with a slash.`,
};
}
if (files.some(f => f === path || minimatch(f, path)) === false) {
return {
code: 'invalid_function_source',
@@ -318,7 +327,7 @@ function validateFunctions(files: string[], { functions = {} }: Options) {
if (typeof func.includeFiles !== 'string') {
return {
code: 'invalid_function_property',
message: `The property \`includeFiles\` must be a string.`
message: `The property \`includeFiles\` must be a string.`,
};
}
}
@@ -327,7 +336,7 @@ function validateFunctions(files: string[], { functions = {} }: Options) {
if (typeof func.excludeFiles !== 'string') {
return {
code: 'invalid_function_property',
message: `The property \`excludeFiles\` must be a string.`
message: `The property \`excludeFiles\` must be a string.`,
};
}
}

View File

@@ -0,0 +1,23 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectAngular({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasAngular = await hasDependency('@angular/cli');
if (!hasAngular) return false;
return {
buildCommand: ['ng', 'build'],
buildDirectory: 'dist',
devCommand: ['ng', 'serve', '--port', '$PORT'],
minNodeRange: '10.x',
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,17 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectBrunch({
fs: { hasDependency, exists },
}: DetectorParameters): Promise<DetectorResult> {
const hasBrunch = await hasDependency('brunch');
if (!hasBrunch) return false;
const hasConfig = await exists('brunch-config.js');
if (!hasConfig) return false;
return {
buildCommand: ['brunch', 'build', '--production'],
buildDirectory: 'public',
devCommand: ['brunch', 'watch', '--server', '--port', '$PORT'],
};
}

View File

@@ -0,0 +1,40 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectCreateReactAppEjected({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasReactDevUtils = await hasDependency('react-dev-utils');
if (!hasReactDevUtils) {
return false;
}
return {
buildCommand: ['node', 'scripts/build.js'],
buildDirectory: 'build',
devCommand: ['node', 'scripts/start.js'],
devEnv: { BROWSER: 'none' },
routes: [
{
src: '/static/(.*)',
headers: { 'cache-control': 's-maxage=31536000, immutable' },
continue: true,
},
{
src: '/service-worker.js',
headers: { 'cache-control': 's-maxage=0' },
continue: true,
},
{
src: '/sockjs-node/(.*)',
dest: '/sockjs-node/$1',
},
{
handle: 'filesystem',
},
{
src: '/(.*)',
headers: { 'cache-control': 's-maxage=0' },
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,40 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectCreateReactApp({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasReactScripts = await hasDependency('react-scripts');
if (!hasReactScripts) {
return false;
}
return {
buildCommand: ['react-scripts', 'build'],
buildDirectory: 'build',
devCommand: ['react-scripts', 'start'],
devEnv: { BROWSER: 'none' },
routes: [
{
src: '/static/(.*)',
headers: { 'cache-control': 's-maxage=31536000, immutable' },
continue: true,
},
{
src: '/service-worker.js',
headers: { 'cache-control': 's-maxage=0' },
continue: true,
},
{
src: '/sockjs-node/(.*)',
dest: '/sockjs-node/$1',
},
{
handle: 'filesystem',
},
{
src: '/(.*)',
headers: { 'cache-control': 's-maxage=0' },
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,13 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectDocusaurus({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasDocusaurus = await hasDependency('docusaurus');
if (!hasDocusaurus) return false;
return {
buildCommand: ['docusaurus-build'],
buildDirectory: 'build',
devCommand: ['docusaurus-start', '--port', '$PORT'],
};
}

View File

@@ -0,0 +1,20 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectEleventy({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasEleventy = await hasDependency('@11ty/eleventy');
if (!hasEleventy) return false;
return {
buildCommand: ['npx', '@11ty/eleventy'],
buildDirectory: '_site',
devCommand: [
'npx',
'@11ty/eleventy',
'--serve',
'--watch',
'--port',
'$PORT',
],
};
}

View File

@@ -0,0 +1,22 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectEmber({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasEmber = await hasDependency('ember-cli');
if (!hasEmber) return false;
return {
buildCommand: ['ember', 'build'],
buildDirectory: 'dist',
devCommand: ['ember', 'serve', '--port', '$PORT'],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,116 @@
import yaml from 'js-yaml';
import toml from '@iarna/toml';
import { PackageJson } from '../types';
/**
* `DetectorFilesystem` is an abstract class that represents a virtual filesystem
* to perform read-only operations on in order to detect which framework is being
* used.
*
* Its abstract methods must be implemented by a subclass that perform the actual
* FS operations. Example subclasses could be implemented as:
*
* - Local filesystem, which proxies the FS operations to the equivalent `fs`
* module functions.
* - HTTP filesystem, which implements the FS operations over an HTTP server
* and does not require a local copy of the files.
* - `Files` filesystem, which operates on a virtual `Files` object (i.e. from
* the `glob()` function) which could include `FileFsRef`, `FileBlob`, etc.
*
* This base class implements various helper functions for common tasks (i.e.
* read and parse a JSON file). It also includes caching for all FS operations
* so that multiple detector functions de-dup read operations on the same file
* to reduce network/filesystem overhead.
*
* **NOTE:** It's important that all instance methods in this base class are
* bound to `this` so that the `fs` object may be destructured in the detector
* functions. The easiest way to do this is to use the `=` syntax when defining
* methods in this class definition.
*/
export default abstract class DetectorFilesystem {
protected abstract _readFile(name: string): Promise<Buffer>;
protected abstract _exists(name: string): Promise<boolean>;
private existsCache: Map<string, Promise<boolean>>;
private readFileCache: Map<string, Promise<Buffer>>;
private readJsonCache: Map<string, Promise<any>>;
constructor() {
this.existsCache = new Map();
this.readFileCache = new Map();
this.readJsonCache = new Map();
}
public exists = async (name: string): Promise<boolean> => {
let p = this.existsCache.get(name);
if (!p) {
p = this._exists(name);
this.existsCache.set(name, p);
}
return p;
};
public readFile = async (name: string): Promise<Buffer> => {
let p = this.readFileCache.get(name);
if (!p) {
p = this._readFile(name);
this.readFileCache.set(name, p);
}
return p;
};
public readJson = async <T>(name: string): Promise<T> => {
let p = this.readJsonCache.get(name);
if (!p) {
p = this.readFile(name).then(d => JSON.parse(d.toString('utf8')));
this.readJsonCache.set(name, p);
}
return p;
};
public readFileOrNull = async (name: string): Promise<Buffer | null> => {
return nullEnoent(this.readFile(name));
};
public readJsonOrNull = async <T>(name: string): Promise<T | null> => {
return nullEnoent(this.readJson<T>(name));
};
public readPackageJson = async (): Promise<PackageJson | null> => {
return await this.readJsonOrNull<PackageJson>('package.json');
};
public readConfigFile = async <T>(...names: string[]): Promise<T | null> => {
for (const name of names) {
const data = await this.readFileOrNull(name);
if (data) {
const str = data.toString('utf8');
if (name.endsWith('.json')) {
return JSON.parse(str);
} else if (name.endsWith('.toml')) {
return (toml.parse(str) as unknown) as T;
} else if (name.endsWith('.yaml') || name.endsWith('.yml')) {
return yaml.safeLoad(str, { filename: name });
}
}
}
return null;
};
public hasDependency = async (name: string): Promise<boolean> => {
const pkg = await this.readPackageJson();
const { dependencies = {}, devDependencies = {} } = pkg || {};
return name in dependencies || name in devDependencies;
};
}
async function nullEnoent<T>(p: Promise<T>): Promise<T | null> {
try {
return await p;
} catch (err) {
if (err.code === 'ENOENT') {
return null;
}
throw err;
}
}

View File

@@ -0,0 +1,16 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectGatsby({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasGatsby = await hasDependency('gatsby');
if (!hasGatsby) {
return false;
}
return {
buildCommand: ['gatsby', 'build'],
buildDirectory: 'public',
devCommand: ['gatsby', 'develop', '-p', '$PORT'],
cachePattern: '.cache/**',
};
}

View File

@@ -0,0 +1,15 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectGridsome({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasGridsome = await hasDependency('gridsome');
if (!hasGridsome) {
return false;
}
return {
buildCommand: ['gridsome', 'build'],
buildDirectory: 'dist',
devCommand: ['gridsome', 'develop', '-p', '$PORT'],
};
}

View File

@@ -0,0 +1,13 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectHexo({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasHexo = await hasDependency('hexo');
if (!hasHexo) return false;
return {
buildCommand: ['hexo', 'generate'],
buildDirectory: 'public',
devCommand: ['hexo', 'server', '--port', '$PORT'],
};
}

View File

@@ -0,0 +1,26 @@
import { DetectorParameters, DetectorResult } from '../types';
/**
* https://gohugo.io/getting-started/configuration/#configuration-file
*/
interface HugoConfig {
publishDir?: string;
}
export default async function detectHugo({
fs: { readConfigFile },
}: DetectorParameters): Promise<DetectorResult> {
const config = await readConfigFile<HugoConfig>(
'config.toml',
'config.yaml',
'config.json'
);
if (!config) {
return false;
}
return {
buildCommand: ['hugo'],
buildDirectory: config.publishDir || 'public',
devCommand: ['hugo', 'server', '-D', '-w', '-p', '$PORT'],
};
}

View File

@@ -0,0 +1,85 @@
import AggregateError from 'aggregate-error';
import { Detector, DetectorParameters, DetectorResult } from '../types';
import angular from './angular';
import brunch from './brunch';
import createReactApp from './create-react-app';
import createReactAppEjected from './create-react-app-ejected';
import docusaurus from './docusaurus';
import eleventy from './eleventy';
import ember from './ember';
import gatsby from './gatsby';
import gridsome from './gridsome';
import hexo from './hexo';
import hugo from './hugo';
import jekyll from './jekyll';
import middleman from './middleman';
import next from './next';
import polymer from './polymer';
import preact from './preact';
import saber from './saber';
import sapper from './sapper';
import stencil from './stencil';
import svelte from './svelte';
import umi from './umi';
import vue from './vue';
export const pkgDetectors: Detector[] = [
angular,
brunch,
createReactApp,
createReactAppEjected,
docusaurus,
eleventy,
ember,
gatsby,
gridsome,
hexo,
next,
polymer,
preact,
saber,
sapper,
stencil,
svelte,
umi,
vue,
];
export const detectors: Detector[] = [hugo, jekyll, middleman];
export function firstTruthy<T>(promises: Promise<T>[]) {
return new Promise<T>((resolve, reject) => {
const errors: Array<Error> = [];
let unresolved = promises.length;
for (const p of promises) {
p.then(v => {
if (v || --unresolved === 0) {
resolve(v);
}
}).catch(err => {
errors.push(err);
if (--unresolved === 0) {
reject(new AggregateError(errors));
}
});
}
});
}
export async function detectDefaults(
params: DetectorParameters
): Promise<DetectorResult> {
// The `package.json` detectors are run first, since they share the common
// file read of `package.json` and are the most popular frameworks
let d: Detector[] = params.pkgDetectors || pkgDetectors;
let result: DetectorResult = await firstTruthy(
d.map(detector => detector(params))
);
if (!result) {
// If no `package.json` framework was detected then check the non-pkg ones
d = params.detectors || detectors;
result = await firstTruthy(d.map(detector => detector(params)));
}
return result;
}

View File

@@ -0,0 +1,30 @@
import { DetectorParameters, DetectorResult } from '../types';
/**
* https://jekyllrb.com/docs/configuration/options/
*/
interface JekyllConfig {
destination?: string;
}
export default async function detectJekyll({
fs: { readConfigFile },
}: DetectorParameters): Promise<DetectorResult> {
const config = await readConfigFile<JekyllConfig>('_config.yml');
if (!config) {
return false;
}
return {
buildCommand: ['jekyll', 'build'],
buildDirectory: config.destination || '_site',
devCommand: [
'bundle',
'exec',
'jekyll',
'serve',
'--watch',
'--port',
'$PORT',
],
};
}

View File

@@ -0,0 +1,14 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectMiddleman({
fs: { exists },
}: DetectorParameters): Promise<DetectorResult> {
const hasConfig = await exists('config.rb');
if (!hasConfig) return false;
return {
buildCommand: ['bundle', 'exec', 'middleman', 'build'],
buildDirectory: 'build',
devCommand: ['bundle', 'exec', 'middleman', 'server', '-p', '$PORT'],
};
}

View File

@@ -0,0 +1,13 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectNext({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasNext = await hasDependency('next');
if (!hasNext) return false;
return {
buildCommand: ['next', 'build'],
buildDirectory: 'build',
devCommand: ['next', '-p', '$PORT'],
};
}

View File

@@ -0,0 +1,22 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectPolymer({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasPolymer = await hasDependency('polymer-cli');
if (!hasPolymer) return false;
return {
buildCommand: ['polymer', 'build'],
buildDirectory: 'build',
devCommand: ['polymer', 'serve', '--port', '$PORT'],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,22 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectPreact({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasPreact = await hasDependency('preact-cli');
if (!hasPreact) return false;
return {
buildCommand: ['preact', 'build'],
buildDirectory: 'build',
devCommand: ['preact', 'watch', '--port', '$PORT'],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,27 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectSaber({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasSaber = await hasDependency('saber');
if (!hasSaber) return false;
return {
buildCommand: ['saber', 'build'],
buildDirectory: 'public',
devCommand: ['saber', '--port', '$PORT'],
routes: [
{
src: '/_saber/.*',
headers: { 'cache-control': 'max-age=31536000, immutable' },
},
{
handle: 'filesystem',
},
{
src: '.*',
status: 404,
dest: '404.html',
},
],
};
}

View File

@@ -0,0 +1,13 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectSapper({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasSapper = await hasDependency('sapper');
if (!hasSapper) return false;
return {
buildCommand: ['sapper', 'export'],
buildDirectory: '__sapper__/export',
devCommand: ['sapper', 'dev', '--port', '$PORT'],
};
}

View File

@@ -0,0 +1,30 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectStencil({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasStencil = await hasDependency('@stencil/core');
if (!hasStencil) return false;
return {
buildCommand: ['stencil', 'build'],
buildDirectory: 'www',
devCommand: [
'stencil',
'build',
'--dev',
'--watch',
'--serve',
'--port',
'$PORT',
],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,22 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectSvelte({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasSvelte = await hasDependency('sirv-cli');
if (!hasSvelte) return false;
return {
buildCommand: ['rollup', '-c'],
buildDirectory: 'public',
devCommand: ['sirv', 'public', '--single', '--dev', ' --port', '$PORT'],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,22 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectUmiJS({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasUmi = await hasDependency('umi');
if (!hasUmi) return false;
return {
buildCommand: ['umi', 'build'],
buildDirectory: 'dist',
devCommand: ['umi', 'dev', '--port', '$PORT'],
routes: [
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
};
}

View File

@@ -0,0 +1,32 @@
import { DetectorParameters, DetectorResult } from '../types';
export default async function detectVue({
fs: { hasDependency },
}: DetectorParameters): Promise<DetectorResult> {
const hasVue = await hasDependency('@vue/cli-service');
if (!hasVue) return false;
return {
buildCommand: ['vue-cli-service', 'build'],
buildDirectory: 'dist',
devCommand: ['vue-cli-service', 'serve', '--port', '$PORT'],
routes: [
{
src: '^/[^/]*\\.(js|txt|ico|json)',
headers: { 'cache-control': 'max-age=300' },
continue: true,
},
{
src: '^/(img|js|css|fonts|media)/.*',
headers: { 'cache-control': 'max-age=31536000, immutable' },
continue: true,
},
{
handle: 'filesystem',
},
{
src: '^.*',
dest: '/index.html',
},
],
};
}

View File

@@ -3,6 +3,7 @@ import { NodeVersion } from '../types';
import debug from '../debug';
const supportedOptions: NodeVersion[] = [
{ major: 12, range: '12.x', runtime: 'nodejs12.x' },
{ major: 10, range: '10.x', runtime: 'nodejs10.x' },
{ major: 8, range: '8.10.x', runtime: 'nodejs8.10' },
];
@@ -22,7 +23,7 @@ export async function getSupportedNodeVersion(
if (!engineRange) {
if (!silent) {
debug(
'missing `engines` in `package.json`, using default range: ' +
'Missing `engines` in `package.json`, using default range: ' +
selection.range
);
}
@@ -43,9 +44,10 @@ export async function getSupportedNodeVersion(
} else {
if (!silent) {
throw new Error(
'found `engines` in `package.json` with an unsupported node range: ' +
'Found `engines` in `package.json` with an unsupported node range: ' +
engineRange +
'\nplease use `10.x` or `8.10.x` instead'
'\nPlease use one of the following supported ranges: ' +
JSON.stringify(supportedOptions.map(o => o.range))
);
}
}

View File

@@ -247,7 +247,11 @@ export async function runPackageJsonScript(
await spawnAsync('npm', ['run', scriptName], opts);
} else {
console.log(`Running "yarn run ${scriptName}"`);
await spawnAsync('yarn', ['--cwd', destPath, 'run', scriptName], opts);
await spawnAsync(
'yarn',
['--ignore-engines', '--cwd', destPath, 'run', scriptName],
opts
);
}
return true;

View File

@@ -22,6 +22,7 @@ import streamToBuffer from './fs/stream-to-buffer';
import shouldServe from './should-serve';
import { detectBuilders } from './detect-builders';
import { detectRoutes } from './detect-routes';
import DetectorFilesystem from './detectors/filesystem';
import debug from './debug';
export {
@@ -29,6 +30,7 @@ export {
FileFsRef,
FileRef,
Lambda,
DetectorFilesystem,
createLambda,
Prerender,
download,
@@ -53,4 +55,5 @@ export {
getLambdaOptionsFromFunction,
};
export { detectDefaults } from './detectors';
export * from './types';

View File

@@ -1,5 +1,6 @@
import FileRef from './file-ref';
import FileFsRef from './file-fs-ref';
import DetectorFilesystem from './detectors/filesystem';
export interface Env {
[name: string]: string | undefined;
@@ -320,3 +321,50 @@ export interface BuilderFunctions {
excludeFiles?: string;
};
}
export interface NowRewrite {
source: string;
destination: string;
}
export interface NowRedirect {
source: string;
destination: string;
statusCode?: number;
}
export interface NowHeader {
source: string;
headers: NowHeaderKeyValue[];
}
export interface NowHeaderKeyValue {
key: string;
value: string;
}
export type Detector = (params: DetectorParameters) => Promise<DetectorResult>;
export interface DetectorParameters {
fs: DetectorFilesystem;
detectors?: Detector[];
pkgDetectors?: Detector[];
}
export interface DetectorOutput {
buildCommand: string[];
buildDirectory: string;
buildEnv?: Env;
devCommand?: string[];
devEnv?: Env;
minNodeRange?: string;
cachePattern?: string;
routes?: Route[];
cleanUrls?: boolean;
rewrites?: NowRewrite[];
redirects?: NowRedirect[];
headers?: NowHeader[];
trailingSlash?: boolean;
}
export type DetectorResult = DetectorOutput | false;

View File

@@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View File

@@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

View File

@@ -0,0 +1,27 @@
# Angular
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.3.17.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@@ -0,0 +1,114 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angular": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angular",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "angular:build"
},
"configurations": {
"production": {
"browserTarget": "angular:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angular:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": ["**/node_modules/**"]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "angular:serve"
},
"configurations": {
"production": {
"devServerTarget": "angular:serve:production"
}
}
}
}
}
},
"defaultProject": "angular"
}

View File

@@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -0,0 +1,32 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: ['./src/**/*.e2e-spec.ts'],
capabilities: {
browserName: 'chrome',
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {},
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json'),
});
jasmine
.getEnv()
.addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
},
};

View File

@@ -0,0 +1,28 @@
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('angular app is running!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser
.manage()
.logs()
.get(logging.Type.BROWSER);
expect(logs).not.toContain(
jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry)
);
});
});

View File

@@ -0,0 +1,13 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css('app-root .content span')).getText() as Promise<
string
>;
}
}

View File

@@ -0,0 +1,9 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": ["jasmine", "jasminewd2", "node"]
}
}

View File

@@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/angular'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true,
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};

View File

@@ -0,0 +1,47 @@
{
"name": "angular",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~8.2.13",
"@angular/common": "~8.2.13",
"@angular/compiler": "~8.2.13",
"@angular/core": "~8.2.13",
"@angular/forms": "~8.2.13",
"@angular/platform-browser": "~8.2.13",
"@angular/platform-browser-dynamic": "~8.2.13",
"@angular/router": "~8.2.13",
"rxjs": "~6.4.0",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.803.17",
"@angular/cli": "~8.3.17",
"@angular/compiler-cli": "~8.2.13",
"@angular/language-service": "~8.2.13",
"@types/node": "~8.9.4",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.5.3"
}
}

View File

@@ -0,0 +1,536 @@
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
:host {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px;
color: #333;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 8px 0;
}
p {
margin: 0;
}
.spacer {
flex: 1;
}
.toolbar {
height: 60px;
margin: -8px;
display: flex;
align-items: center;
background-color: #1976d2;
color: white;
font-weight: 600;
}
.toolbar img {
margin: 0 16px;
}
.toolbar #twitter-logo {
height: 40px;
margin: 0 16px;
}
.toolbar #twitter-logo:hover {
opacity: 0.8;
}
.content {
display: flex;
margin: 32px auto;
padding: 0 16px;
max-width: 960px;
flex-direction: column;
align-items: center;
}
svg.material-icons {
height: 24px;
width: auto;
}
svg.material-icons:not(:last-child) {
margin-right: 8px;
}
.card svg.material-icons path {
fill: #888;
}
.card-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 16px;
}
.card {
border-radius: 4px;
border: 1px solid #eee;
background-color: #fafafa;
height: 40px;
width: 200px;
margin: 0 8px 16px;
padding: 16px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
transition: all 0.2s ease-in-out;
line-height: 24px;
}
.card-container .card:not(:last-child) {
margin-right: 0;
}
.card.card-small {
height: 16px;
width: 168px;
}
.card-container .card:not(.highlight-card) {
cursor: pointer;
}
.card-container .card:not(.highlight-card):hover {
transform: translateY(-3px);
box-shadow: 0 4px 17px rgba(black, 0.35);
}
.card-container .card:not(.highlight-card):hover .material-icons path {
fill: rgb(105, 103, 103);
}
.card.highlight-card {
background-color: #1976d2;
color: white;
font-weight: 600;
border: none;
width: auto;
min-width: 30%;
position: relative;
}
.card.card.highlight-card span {
margin-left: 60px;
}
svg#rocket {
width: 80px;
position: absolute;
left: -10px;
top: -24px;
}
svg#rocket-smoke {
height: 100vh;
position: absolute;
top: 10px;
right: 180px;
z-index: -10;
}
a,
a:visited,
a:hover {
color: #1976d2;
text-decoration: none;
}
a:hover {
color: #125699;
}
.terminal {
position: relative;
width: 80%;
max-width: 600px;
border-radius: 6px;
padding-top: 45px;
margin-top: 8px;
overflow: hidden;
background-color: rgb(15, 15, 16);
}
.terminal::before {
content: "\2022 \2022 \2022";
position: absolute;
top: 0;
left: 0;
height: 4px;
background: rgb(58, 58, 58);
color: #c2c3c4;
width: 100%;
font-size: 2rem;
line-height: 0;
padding: 14px 0;
text-indent: 4px;
}
.terminal pre {
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;
color: white;
padding: 0 1rem 1rem;
margin: 0;
}
.circle-link {
height: 40px;
width: 40px;
border-radius: 40px;
margin: 8px;
background-color: white;
border: 1px solid #eeeeee;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
transition: 1s ease-out;
}
.circle-link:hover {
transform: translateY(-0.25rem);
box-shadow: 0px 3px 15px rgba(0, 0, 0, 0.2);
}
footer {
margin-top: 8px;
display: flex;
align-items: center;
line-height: 20px;
}
footer a {
display: flex;
align-items: center;
}
.github-star-badge {
color: #24292e;
display: flex;
align-items: center;
font-size: 12px;
padding: 3px 10px;
border: 1px solid rgba(27,31,35,.2);
border-radius: 3px;
background-image: linear-gradient(-180deg,#fafbfc,#eff3f6 90%);
margin-left: 4px;
font-weight: 600;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
}
.github-star-badge:hover {
background-image: linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);
border-color: rgba(27,31,35,.35);
background-position: -.5em;
}
.github-star-badge .material-icons {
height: 16px;
width: 16px;
margin-right: 4px;
}
svg#clouds {
position: fixed;
bottom: -160px;
left: -230px;
z-index: -10;
width: 1920px;
}
/* Responsive Styles */
@media screen and (max-width: 767px) {
.card-container > *:not(.circle-link) ,
.terminal {
width: 100%;
}
.card:not(.highlight-card) {
height: 16px;
margin: 8px 0;
}
.card.highlight-card span {
margin-left: 72px;
}
svg#rocket-smoke {
right: 120px;
transform: rotate(-5deg);
}
}
@media screen and (max-width: 575px) {
svg#rocket-smoke {
display: none;
visibility: hidden;
}
}
</style>
<!-- Toolbar -->
<div class="toolbar" role="banner">
<img
width="40"
alt="Angular Logo"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="
/>
<span>Welcome</span>
<div class="spacer"></div>
<a aria-label="Angular on twitter" target="_blank" rel="noopener" href="https://twitter.com/angular" title="Twitter">
<svg id="twitter-logo" height="24" data-name="Logo — FIXED" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<defs>
<style>
.cls-1 {
fill: none;
}
.cls-2 {
fill: #ffffff;
}
</style>
</defs>
<rect class="cls-1" width="400" height="400" />
<path class="cls-2" d="M153.62,301.59c94.34,0,145.94-78.16,145.94-145.94,0-2.22,0-4.43-.15-6.63A104.36,104.36,0,0,0,325,122.47a102.38,102.38,0,0,1-29.46,8.07,51.47,51.47,0,0,0,22.55-28.37,102.79,102.79,0,0,1-32.57,12.45,51.34,51.34,0,0,0-87.41,46.78A145.62,145.62,0,0,1,92.4,107.81a51.33,51.33,0,0,0,15.88,68.47A50.91,50.91,0,0,1,85,169.86c0,.21,0,.43,0,.65a51.31,51.31,0,0,0,41.15,50.28,51.21,51.21,0,0,1-23.16.88,51.35,51.35,0,0,0,47.92,35.62,102.92,102.92,0,0,1-63.7,22A104.41,104.41,0,0,1,75,278.55a145.21,145.21,0,0,0,78.62,23"
/>
</svg>
</a>
</div>
<div class="content" role="main">
<!-- Highlight Card -->
<div class="card highlight-card card-small">
<svg id="rocket" alt="Rocket Ship" xmlns="http://www.w3.org/2000/svg" width="101.678" height="101.678" viewBox="0 0 101.678 101.678">
<g id="Group_83" data-name="Group 83" transform="translate(-141 -696)">
<circle id="Ellipse_8" data-name="Ellipse 8" cx="50.839" cy="50.839" r="50.839" transform="translate(141 696)" fill="#dd0031"/>
<g id="Group_47" data-name="Group 47" transform="translate(165.185 720.185)">
<path id="Path_33" data-name="Path 33" d="M3.4,42.615a3.084,3.084,0,0,0,3.553,3.553,21.419,21.419,0,0,0,12.215-6.107L9.511,30.4A21.419,21.419,0,0,0,3.4,42.615Z" transform="translate(0.371 3.363)" fill="#fff"/>
<path id="Path_34" data-name="Path 34" d="M53.3,3.221A3.09,3.09,0,0,0,50.081,0,48.227,48.227,0,0,0,18.322,13.437c-6-1.666-14.991-1.221-18.322,7.218A33.892,33.892,0,0,1,9.439,25.1l-.333.666a3.013,3.013,0,0,0,.555,3.553L23.985,43.641a2.9,2.9,0,0,0,3.553.555l.666-.333A33.892,33.892,0,0,1,32.647,53.3c8.55-3.664,8.884-12.326,7.218-18.322A48.227,48.227,0,0,0,53.3,3.221ZM34.424,9.772a6.439,6.439,0,1,1,9.106,9.106,6.368,6.368,0,0,1-9.106,0A6.467,6.467,0,0,1,34.424,9.772Z" transform="translate(0 0.005)" fill="#fff"/>
</g>
</g>
</svg>
<span>{{ title }} app is running!</span>
<svg id="rocket-smoke" alt="Rocket Ship Smoke" xmlns="http://www.w3.org/2000/svg" width="516.119" height="1083.632" viewBox="0 0 516.119 1083.632">
<path id="Path_40" data-name="Path 40" d="M644.6,141S143.02,215.537,147.049,870.207s342.774,201.755,342.774,201.755S404.659,847.213,388.815,762.2c-27.116-145.51-11.551-384.124,271.9-609.1C671.15,139.365,644.6,141,644.6,141Z" transform="translate(-147.025 -140.939)" fill="#f5f5f5"/>
</svg>
</div>
<!-- Resources -->
<h2>Resources</h2>
<p>Here are some links to help you get started:</p>
<div class="card-container">
<a class="card" target="_blank" rel="noopener" href="https://angular.io/tutorial">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></svg>
<span>Learn Angular</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg> </a>
<a class="card" target="_blank" rel="noopener" href="https://angular.io/cli">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
<span>CLI Documentation</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
</a>
<a class="card" target="_blank" rel="noopener" href="https://blog.angular.io/">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/></svg>
<span>Angular Blog</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
</a>
</div>
<!-- Next Steps -->
<h2>Next Steps</h2>
<p>What do you want to do next with your app?</p>
<input type="hidden" #selection>
<div class="card-container">
<div class="card card-small" (click)="selection.value = 'component'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>New Component</span>
</div>
<div class="card card-small" (click)="selection.value = 'material'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Angular Material</span>
</div>
<div class="card card-small" (click)="selection.value = 'dependency'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Add Dependency</span>
</div>
<div class="card card-small" (click)="selection.value = 'test'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Run and Watch Tests</span>
</div>
<div class="card card-small" (click)="selection.value = 'build'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Build for Production</span>
</div>
</div>
<!-- Terminal -->
<div class="terminal" [ngSwitch]="selection.value">
<pre *ngSwitchDefault>ng generate component xyz</pre>
<pre *ngSwitchCase="'material'">ng add @angular/material</pre>
<pre *ngSwitchCase="'dependency'">ng add _____</pre>
<pre *ngSwitchCase="'test'">ng test</pre>
<pre *ngSwitchCase="'build'">ng build --prod</pre>
</div>
<!-- Links -->
<div class="card-container">
<a class="circle-link" title="Animations" href="https://angular.io/guide/animations" target="_blank" rel="noopener">
<svg id="Group_20" data-name="Group 20" xmlns="http://www.w3.org/2000/svg" width="21.813" height="23.453" viewBox="0 0 21.813 23.453">
<path id="Path_15" data-name="Path 15" d="M4099.584,972.736h0l-10.882,3.9,1.637,14.4,9.245,5.153,9.245-5.153,1.686-14.4Z" transform="translate(-4088.702 -972.736)" fill="#ffa726"/>
<path id="Path_16" data-name="Path 16" d="M4181.516,972.736v23.453l9.245-5.153,1.686-14.4Z" transform="translate(-4170.633 -972.736)" fill="#fb8c00"/>
<path id="Path_17" data-name="Path 17" d="M4137.529,1076.127l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1058.315)" fill="#ffe0b2"/>
<path id="Path_18" data-name="Path 18" d="M4137.529,1051.705l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1036.757)" fill="#fff3e0"/>
<path id="Path_19" data-name="Path 19" d="M4137.529,1027.283l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1015.199)" fill="#fff"/>
</svg>
</a>
<a class="circle-link" title="CLI" href="https://cli.angular.io/" target="_blank" rel="noopener">
<svg alt="Angular CLI Logo" xmlns="http://www.w3.org/2000/svg" width="21.762" height="23.447" viewBox="0 0 21.762 23.447">
<g id="Group_21" data-name="Group 21" transform="translate(0)">
<path id="Path_20" data-name="Path 20" d="M2660.313,313.618h0l-10.833,3.9,1.637,14.4,9.2,5.152,9.244-5.152,1.685-14.4Z" transform="translate(-2649.48 -313.618)" fill="#37474f"/>
<path id="Path_21" data-name="Path 21" d="M2741.883,313.618v23.447l9.244-5.152,1.685-14.4Z" transform="translate(-2731.05 -313.618)" fill="#263238"/>
<path id="Path_22" data-name="Path 22" d="M2692.293,379.169h11.724V368.618h-11.724Zm11.159-.6h-10.608v-9.345h10.621v9.345Z" transform="translate(-2687.274 -362.17)" fill="#fff"/>
<path id="Path_23" data-name="Path 23" d="M2709.331,393.688l.4.416,2.265-2.28-2.294-2.294-.4.4,1.893,1.893Z" transform="translate(-2702.289 -380.631)" fill="#fff"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="3.517" height="0.469" transform="translate(9.709 13.744)" fill="#fff"/>
</g>
</svg>
</a>
<a class="circle-link" title="Augury" href="https://augury.rangle.io/" target="_blank" rel="noopener">
<svg alt="Angular Augury Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="21.81" height="23.447" viewBox="0 0 21.81 23.447">
<defs>
<clipPath id="clip-path">
<rect id="Rectangle_13" data-name="Rectangle 13" width="10.338" height="10.27" fill="none"/>
</clipPath>
</defs>
<g id="Group_25" data-name="Group 25" transform="translate(0)">
<path id="Path_24" data-name="Path 24" d="M3780.155,311.417h0l-10.881,3.9,1.637,14.4,9.244,5.152,9.244-5.152,1.685-14.4Z" transform="translate(-3769.274 -311.417)" fill="#4a3493"/>
<path id="Path_25" data-name="Path 25" d="M3862.088,311.417v23.447l9.244-5.152,1.685-14.4Z" transform="translate(-3851.207 -311.417)" fill="#311b92"/>
<g id="Group_24" data-name="Group 24" transform="translate(6.194 6.73)" opacity="0.5">
<g id="Group_23" data-name="Group 23" transform="translate(0 0)">
<g id="Group_22" data-name="Group 22" clip-path="url(#clip-path)">
<path id="Path_26" data-name="Path 26" d="M3832.4,373.252a5.168,5.168,0,1,1-5.828-4.383,5.216,5.216,0,0,1,2.574.3,3.017,3.017,0,1,0,3.252,4.086Z" transform="translate(-3822.107 -368.821)" fill="#fff"/>
</g>
</g>
</g>
<path id="Path_27" data-name="Path 27" d="M3830.582,370.848a5.162,5.162,0,1,1-3.254-4.086,3.017,3.017,0,1,0,3.252,4.086Z" transform="translate(-3814.311 -359.969)" fill="#fff"/>
</g>
</svg>
</a>
<a class="circle-link" title="Protractor" href="https://www.protractortest.org/" target="_blank" rel="noopener">
<svg alt="Angular Protractor Logo" xmlns="http://www.w3.org/2000/svg" width="21.81" height="23.447" viewBox="0 0 21.81 23.447">
<g id="Group_26" data-name="Group 26" transform="translate(0)">
<path id="Path_28" data-name="Path 28" d="M4620.155,311.417h0l-10.881,3.9,1.637,14.4,9.244,5.152,9.244-5.152,1.685-14.4Z" transform="translate(-4609.274 -311.417)" fill="#e13439"/>
<path id="Path_29" data-name="Path 29" d="M4702.088,311.417v23.447l9.244-5.152,1.685-14.4Z" transform="translate(-4691.207 -311.417)" fill="#b52f32"/>
<path id="Path_30" data-name="Path 30" d="M4651.044,369.58v-.421h1.483a7.6,7.6,0,0,0-2.106-5.052l-1.123,1.123-.3-.3,1.122-1.121a7.588,7.588,0,0,0-4.946-2.055v1.482h-.421v-1.485a7.589,7.589,0,0,0-5.051,2.058l1.122,1.121-.3.3-1.123-1.123a7.591,7.591,0,0,0-2.106,5.052h1.482v.421h-1.489v1.734h15.241V369.58Zm-10.966-.263a4.835,4.835,0,0,1,9.67,0Z" transform="translate(-4634.008 -355.852)" fill="#fff"/>
</g>
</svg>
</a>
<a class="circle-link" title="Find a Local Meetup" href="https://www.meetup.com/find/?keywords=angular" target="_blank" rel="noopener">
<svg alt="Meetup Logo" xmlns="http://www.w3.org/2000/svg" width="24.607" height="23.447" viewBox="0 0 24.607 23.447">
<path id="logo--mSwarm" d="M21.221,14.95A4.393,4.393,0,0,1,17.6,19.281a4.452,4.452,0,0,1-.8.069c-.09,0-.125.035-.154.117a2.939,2.939,0,0,1-2.506,2.091,2.868,2.868,0,0,1-2.248-.624.168.168,0,0,0-.245-.005,3.926,3.926,0,0,1-2.589.741,4.015,4.015,0,0,1-3.7-3.347,2.7,2.7,0,0,1-.043-.38c0-.106-.042-.146-.143-.166a3.524,3.524,0,0,1-1.516-.69A3.623,3.623,0,0,1,2.23,14.557a3.66,3.66,0,0,1,1.077-3.085.138.138,0,0,0,.026-.2,3.348,3.348,0,0,1-.451-1.821,3.46,3.46,0,0,1,2.749-3.28.44.44,0,0,0,.355-.281,5.072,5.072,0,0,1,3.863-3,5.028,5.028,0,0,1,3.555.666.31.31,0,0,0,.271.03A4.5,4.5,0,0,1,18.3,4.7a4.4,4.4,0,0,1,1.334,2.751,3.658,3.658,0,0,1,.022.706.131.131,0,0,0,.1.157,2.432,2.432,0,0,1,1.574,1.645,2.464,2.464,0,0,1-.7,2.616c-.065.064-.051.1-.014.166A4.321,4.321,0,0,1,21.221,14.95ZM13.4,14.607a2.09,2.09,0,0,0,1.409,1.982,4.7,4.7,0,0,0,1.275.221,1.807,1.807,0,0,0,.9-.151.542.542,0,0,0,.321-.545.558.558,0,0,0-.359-.534,1.2,1.2,0,0,0-.254-.078c-.262-.047-.526-.086-.787-.138a.674.674,0,0,1-.617-.75,3.394,3.394,0,0,1,.218-1.109c.217-.658.509-1.286.79-1.918a15.609,15.609,0,0,0,.745-1.86,1.95,1.95,0,0,0,.06-1.073,1.286,1.286,0,0,0-1.051-1.033,1.977,1.977,0,0,0-1.521.2.339.339,0,0,1-.446-.042c-.1-.092-.2-.189-.307-.284a1.214,1.214,0,0,0-1.643-.061,7.563,7.563,0,0,1-.614.512A.588.588,0,0,1,10.883,8c-.215-.115-.437-.215-.659-.316a2.153,2.153,0,0,0-.695-.248A2.091,2.091,0,0,0,7.541,8.562a9.915,9.915,0,0,0-.405.986c-.559,1.545-1.015,3.123-1.487,4.7a1.528,1.528,0,0,0,.634,1.777,1.755,1.755,0,0,0,1.5.211,1.35,1.35,0,0,0,.824-.858c.543-1.281,1.032-2.584,1.55-3.875.142-.355.28-.712.432-1.064a.548.548,0,0,1,.851-.24.622.622,0,0,1,.185.539,2.161,2.161,0,0,1-.181.621c-.337.852-.68,1.7-1.018,2.552a2.564,2.564,0,0,0-.173.528.624.624,0,0,0,.333.71,1.073,1.073,0,0,0,.814.034,1.22,1.22,0,0,0,.657-.655q.758-1.488,1.511-2.978.35-.687.709-1.37a1.073,1.073,0,0,1,.357-.434.43.43,0,0,1,.463-.016.373.373,0,0,1,.153.387.7.7,0,0,1-.057.236c-.065.157-.127.316-.2.469-.42.883-.846,1.763-1.262,2.648A2.463,2.463,0,0,0,13.4,14.607Zm5.888,6.508a1.09,1.09,0,0,0-2.179.006,1.09,1.09,0,0,0,2.179-.006ZM1.028,12.139a1.038,1.038,0,1,0,.01-2.075,1.038,1.038,0,0,0-.01,2.075ZM13.782.528a1.027,1.027,0,1,0-.011,2.055A1.027,1.027,0,0,0,13.782.528ZM22.21,6.95a.882.882,0,0,0-1.763.011A.882.882,0,0,0,22.21,6.95ZM4.153,4.439a.785.785,0,1,0,.787-.78A.766.766,0,0,0,4.153,4.439Zm8.221,18.22a.676.676,0,1,0-.677.666A.671.671,0,0,0,12.374,22.658ZM22.872,12.2a.674.674,0,0,0-.665.665.656.656,0,0,0,.655.643.634.634,0,0,0,.655-.644A.654.654,0,0,0,22.872,12.2ZM7.171-.123A.546.546,0,0,0,6.613.43a.553.553,0,1,0,1.106,0A.539.539,0,0,0,7.171-.123ZM24.119,9.234a.507.507,0,0,0-.493.488.494.494,0,0,0,.494.494.48.48,0,0,0,.487-.483A.491.491,0,0,0,24.119,9.234Zm-19.454,9.7a.5.5,0,0,0-.488-.488.491.491,0,0,0-.487.5.483.483,0,0,0,.491.479A.49.49,0,0,0,4.665,18.936Z" transform="translate(0 0.123)" fill="#f64060"/>
</svg>
</a>
<a class="circle-link" title="Join the Conversation on Gitter" href="https://gitter.im/angular/angular" target="_blank" rel="noopener">
<svg alt="Gitter Logo" xmlns="http://www.w3.org/2000/svg" width="19.447" height="19.447" viewBox="0 0 19.447 19.447">
<g id="Group_40" data-name="Group 40" transform="translate(-1612 -405)">
<rect id="Rectangle_19" data-name="Rectangle 19" width="19.447" height="19.447" transform="translate(1612 405)" fill="#e60257"/>
<g id="gitter" transform="translate(1617.795 408.636)">
<g id="Group_33" data-name="Group 33" transform="translate(0 0)">
<rect id="Rectangle_15" data-name="Rectangle 15" width="1.04" height="9.601" transform="translate(2.304 2.324)" fill="#fff"/>
<rect id="Rectangle_16" data-name="Rectangle 16" width="1.04" height="9.601" transform="translate(4.607 2.324)" fill="#fff"/>
<rect id="Rectangle_17" data-name="Rectangle 17" width="1.04" height="4.648" transform="translate(6.91 2.324)" fill="#fff"/>
<rect id="Rectangle_18" data-name="Rectangle 18" width="1.04" height="6.971" transform="translate(0 0)" fill="#fff"/>
</g>
</g>
</g>
</svg>
</a>
</div>
<!-- Footer -->
<footer>
Love Angular?&nbsp;
<a href="https://github.com/angular/angular" target="_blank" rel="noopener"> Give our repo a star.
<div class="github-star-badge">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
Star
</div>
</a>
<a href="https://github.com/angular/angular" target="_blank" rel="noopener">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" fill="#1976d2"/><path d="M0 0h24v24H0z" fill="none"/></svg>
</a>
</footer>
<svg id="clouds" alt="Gray Clouds Background" xmlns="http://www.w3.org/2000/svg" width="2611.084" height="485.677" viewBox="0 0 2611.084 485.677">
<path id="Path_39" data-name="Path 39" d="M2379.709,863.793c10-93-77-171-168-149-52-114-225-105-264,15-75,3-140,59-152,133-30,2.83-66.725,9.829-93.5,26.25-26.771-16.421-63.5-23.42-93.5-26.25-12-74-77-130-152-133-39-120-212-129-264-15-54.084-13.075-106.753,9.173-138.488,48.9-31.734-39.726-84.4-61.974-138.487-48.9-52-114-225-105-264,15a162.027,162.027,0,0,0-103.147,43.044c-30.633-45.365-87.1-72.091-145.206-58.044-52-114-225-105-264,15-75,3-140,59-152,133-53,5-127,23-130,83-2,42,35,72,70,86,49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33,61.112,8.015,113.854-5.72,150.492-29.764a165.62,165.62,0,0,0,110.861-3.236c47,94,178,113,251,33,31.385,4.116,60.563,2.495,86.487-3.311,25.924,5.806,55.1,7.427,86.488,3.311,73,80,204,61,251-33a165.625,165.625,0,0,0,120,0c51,13,108,15,157-5a147.188,147.188,0,0,0,33.5-18.694,147.217,147.217,0,0,0,33.5,18.694c49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33C2446.709,1093.793,2554.709,922.793,2379.709,863.793Z" transform="translate(142.69 -634.312)" fill="#eee"/>
</svg>
</div>
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->

View File

@@ -0,0 +1,31 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'angular'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('angular');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain(
'angular app is running!'
);
});
});

View File

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'angular';
}

View File

@@ -0,0 +1,12 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}

View File

@@ -0,0 +1,3 @@
export const environment = {
production: true,
};

View File

@@ -0,0 +1,16 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false,
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

View File

@@ -0,0 +1,13 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));

View File

@@ -0,0 +1,62 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

View File

@@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

View File

@@ -0,0 +1,20 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": ["src/main.ts", "src/polyfills.ts"],
"include": ["src/**/*.ts"],
"exclude": ["src/test.ts", "src/**/*.spec.ts"]
}

View File

@@ -0,0 +1,21 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom"]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jasmine", "node"]
},
"files": ["src/test.ts", "src/polyfills.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

View File

@@ -0,0 +1,57 @@
{
"extends": "tslint:recommended",
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warning"
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "kebab-case"],
"import-blacklist": [true, "rxjs/Rx"],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [true, 140],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
"no-empty": false,
"no-inferrable-types": [true, "ignore-params"],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-var-requires": false,
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [true, "single"],
"trailing-comma": false,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
},
"rulesDirectory": ["codelyzer"]
}

View File

@@ -0,0 +1,26 @@
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
*.sass-cache
# OS or Editor folders
.DS_Store
.cache
.project
.settings
.tmproj
nbproject
Thumbs.db
# NPM packages folder.
node_modules/
# Brunch output folder.
public/

View File

@@ -0,0 +1,28 @@
# Brunch + Babel/ES6
This is a modern JS skeleton for [Brunch](http://brunch.io).
## Installation
Clone this repo manually or use `brunch new dir -s es6`
## Getting started
- Install (if you don't have them):
- [Node.js](http://nodejs.org): `brew install node` on OS X
- [Brunch](http://brunch.io): `npm install -g brunch`
- Brunch plugins and app dependencies: `npm install`
- Run:
- `npm start` — watches the project with continuous rebuild. This will also launch HTTP server with [pushState](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history).
- `npm run build` — builds minified project for production
- Learn:
- `public/` dir is fully auto-generated and served by HTTP server. Write your code in `app/` dir.
- Place static files you want to be copied from `app/assets/` to `public/`.
- [Brunch site](http://brunch.io), [Getting started guide](https://github.com/brunch/brunch-guide#readme)
## ES-next
To use proposed JS features not included into ES6, do this:
- `npm install --save-dev babel-preset-stage-0`
- in `brunch-config.js`, add the preset: `presets: ['latest', 'stage-0']`

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Brunch</title>
<link rel="stylesheet" href="/app.css">
<script src="/vendor.js"></script>
<script src="/app.js"></script>
<script>require('initialize');</script>
</head>
<body>
<div class="brunch">
<a href="http://brunch.io"><img src="http://brunch.io/images/logo.png" alt="Brunch"></a>
<p>Bon Appétit.</p>
</div>
</body>

View File

@@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', () => {
// do your setup here
console.log('Initialized app');
});

View File

@@ -0,0 +1,6 @@
.brunch {
font-family: -apple-system, Sans-Serif;
text-align: center;
font-size: 24pt;
color: #3f894a;
}

View File

@@ -0,0 +1,14 @@
// See http://brunch.io for documentation.
exports.files = {
javascripts: {
joinTo: {
'vendor.js': /^(?!app)/, // Files that are not in `app` dir.
'app.js': /^app/,
},
},
stylesheets: { joinTo: 'app.css' },
};
exports.plugins = {
babel: { presets: ['latest'] },
};

View File

@@ -0,0 +1,21 @@
{
"name": "brunch-app",
"description": "Brunch.io application",
"private": true,
"author": "Brunch",
"version": "0.0.1",
"repository": "",
"scripts": {
"start": "brunch watch --server",
"build": "brunch build --production"
},
"dependencies": {},
"devDependencies": {
"auto-reload-brunch": "^2",
"babel-brunch": "~6.0",
"babel-preset-latest": "^6",
"brunch": "^2",
"clean-css-brunch": "^2",
"uglify-js-brunch": "^2"
}
}

View File

@@ -0,0 +1,69 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variable files
.env*
# gatsby files
.cache/
public
# Mac files
.DS_Store
# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity

View File

@@ -0,0 +1,4 @@
.cache
package.json
package-lock.json
public

View File

@@ -0,0 +1,7 @@
{
"endOfLine": "lf",
"semi": false,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5"
}

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 gatsbyjs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,97 @@
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
<p align="center">
<a href="https://www.gatsbyjs.org">
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
</a>
</p>
<h1 align="center">
Gatsby's default starter
</h1>
Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._
## 🚀 Quick start
1. **Create a Gatsby site.**
Use the Gatsby CLI to create a new site, specifying the default starter.
```shell
# create a new Gatsby site using the default starter
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
```
1. **Start developing.**
Navigate into your new sites directory and start it up.
```shell
cd my-default-starter/
gatsby develop
```
1. **Open the source code and start editing!**
Your site is now running at `http://localhost:8000`!
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._
Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!
## 🧐 What's inside?
A quick look at the top-level files and directories you'll see in a Gatsby project.
.
├── node_modules
├── src
├── .gitignore
├── .prettierrc
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package-lock.json
├── package.json
└── README.md
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins youd like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).
7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
9. **`LICENSE`**: Gatsby is licensed under the MIT license.
10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You wont change this file directly).**
11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the projects name, author, etc). This manifest is how npm knows which packages to install for your project.
12. **`README.md`**: A text file containing useful reference information about your project.
## 🎓 Learning Gatsby
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
## 💫 Deploy
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
<!-- AUTO-GENERATED-CONTENT:END -->

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,34 @@
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
],
}

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/node-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/ssr-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,43 @@
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"gatsby": "^2.17.6",
"gatsby-image": "^2.2.30",
"gatsby-plugin-manifest": "^2.2.25",
"gatsby-plugin-offline": "^3.0.17",
"gatsby-plugin-react-helmet": "^3.1.13",
"gatsby-plugin-sharp": "^2.2.34",
"gatsby-source-filesystem": "^2.1.35",
"gatsby-transformer-sharp": "^2.3.1",
"prop-types": "^15.7.2",
"react": "^16.11.0",
"react-dom": "^16.11.0",
"react-helmet": "^5.2.1"
},
"devDependencies": {
"prettier": "^1.18.2"
},
"keywords": [
"gatsby"
],
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}

View File

@@ -0,0 +1,42 @@
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
const Header = ({ siteTitle }) => (
<header
style={{
background: `rebeccapurple`,
marginBottom: `1.45rem`,
}}
>
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `1.45rem 1.0875rem`,
}}
>
<h1 style={{ margin: 0 }}>
<Link
to="/"
style={{
color: `white`,
textDecoration: `none`,
}}
>
{siteTitle}
</Link>
</h1>
</div>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header

View File

@@ -0,0 +1,32 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
/*
* This component is built using `gatsby-image` to automatically serve optimized
* images with lazy loading and reduced file sizes. The image is loaded using a
* `useStaticQuery`, which allows us to load the image from directly within this
* component, rather than having to pass the image data down from pages.
*
* For more information, see the docs:
* - `gatsby-image`: https://gatsby.dev/gatsby-image
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
*/
const Image = () => {
const data = useStaticQuery(graphql`
query {
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`)
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
export default Image

View File

@@ -0,0 +1,622 @@
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
progress {
vertical-align: baseline;
}
[hidden],
template {
display: none;
}
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active,
a:hover {
outline-width: 0;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: inherit;
font-weight: bolder;
}
dfn {
font-style: italic;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
mark {
background-color: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
figure {
margin: 1em 40px;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
button,
input,
optgroup,
select,
textarea {
font: inherit;
margin: 0;
}
optgroup {
font-weight: 700;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
[type="reset"],
[type="submit"],
button,
html [type="button"] {
-webkit-appearance: button;
}
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner {
border-style: none;
padding: 0;
}
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
button:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
border: 1px solid silver;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
html {
font: 112.5%/1.45em georgia, serif;
box-sizing: border-box;
overflow-y: scroll;
}
* {
box-sizing: inherit;
}
*:before {
box-sizing: inherit;
}
*:after {
box-sizing: inherit;
}
body {
color: hsla(0, 0%, 0%, 0.8);
font-family: georgia, serif;
font-weight: normal;
word-wrap: break-word;
font-kerning: normal;
-moz-font-feature-settings: "kern", "liga", "clig", "calt";
-ms-font-feature-settings: "kern", "liga", "clig", "calt";
-webkit-font-feature-settings: "kern", "liga", "clig", "calt";
font-feature-settings: "kern", "liga", "clig", "calt";
}
img {
max-width: 100%;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
h1 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 2.25rem;
line-height: 1.1;
}
h2 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.62671rem;
line-height: 1.1;
}
h3 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.38316rem;
line-height: 1.1;
}
h4 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1rem;
line-height: 1.1;
}
h5 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.85028rem;
line-height: 1.1;
}
h6 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.78405rem;
line-height: 1.1;
}
hgroup {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
ul {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
ol {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
dl {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
dd {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
p {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
figure {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
pre {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 1.45rem;
font-size: 0.85rem;
line-height: 1.42;
background: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
overflow: auto;
word-wrap: normal;
padding: 1.45rem;
}
table {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
font-size: 1rem;
line-height: 1.45rem;
border-collapse: collapse;
width: 100%;
}
fieldset {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
blockquote {
margin-left: 1.45rem;
margin-right: 1.45rem;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
form {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
noscript {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
iframe {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
hr {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: calc(1.45rem - 1px);
background: hsla(0, 0%, 0%, 0.2);
border: none;
height: 1px;
}
address {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
b {
font-weight: bold;
}
strong {
font-weight: bold;
}
dt {
font-weight: bold;
}
th {
font-weight: bold;
}
li {
margin-bottom: calc(1.45rem / 2);
}
ol li {
padding-left: 0;
}
ul li {
padding-left: 0;
}
li > ol {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
li > ul {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
blockquote *:last-child {
margin-bottom: 0;
}
li *:last-child {
margin-bottom: 0;
}
p *:last-child {
margin-bottom: 0;
}
li > p {
margin-bottom: calc(1.45rem / 2);
}
code {
font-size: 0.85rem;
line-height: 1.45rem;
}
kbd {
font-size: 0.85rem;
line-height: 1.45rem;
}
samp {
font-size: 0.85rem;
line-height: 1.45rem;
}
abbr {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
acronym {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
abbr[title] {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
text-decoration: none;
}
thead {
text-align: left;
}
td,
th {
text-align: left;
border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
font-feature-settings: "tnum";
-moz-font-feature-settings: "tnum";
-ms-font-feature-settings: "tnum";
-webkit-font-feature-settings: "tnum";
padding-left: 0.96667rem;
padding-right: 0.96667rem;
padding-top: 0.725rem;
padding-bottom: calc(0.725rem - 1px);
}
th:first-child,
td:first-child {
padding-left: 0;
}
th:last-child,
td:last-child {
padding-right: 0;
}
tt,
code {
background-color: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
"Liberation Mono", Menlo, Courier, monospace;
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
}
pre code {
background: none;
line-height: 1.42;
}
code:before,
code:after,
tt:before,
tt:after {
letter-spacing: -0.2em;
content: " ";
}
pre code:before,
pre code:after,
pre tt:before,
pre tt:after {
content: "";
}
@media only screen and (max-width: 480px) {
html {
font-size: 100%;
}
}

View File

@@ -0,0 +1,52 @@
/**
* Layout component that queries for data
* with Gatsby's useStaticQuery component
*
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import "./layout.css"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `0px 1.0875rem 1.45rem`,
paddingTop: 0,
}}
>
<main>{children}</main>
<footer>
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.org">Gatsby</a>
</footer>
</div>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout

View File

@@ -0,0 +1,88 @@
/**
* SEO component that queries for data with
* Gatsby's useStaticQuery React hook
*
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function SEO({ description, lang, meta, title }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
SEO.defaultProps = {
lang: `en`,
meta: [],
description: ``,
}
SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default SEO

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,14 @@
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
const NotFoundPage = () => (
<Layout>
<SEO title="404: Not found" />
<h1>NOT FOUND</h1>
<p>You just hit a route that doesn&#39;t exist... the sadness.</p>
</Layout>
)
export default NotFoundPage

View File

@@ -0,0 +1,21 @@
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"
const IndexPage = () => (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
<p>Welcome to your new Gatsby site.</p>
<p>Now go build something great.</p>
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
export default IndexPage

View File

@@ -0,0 +1,16 @@
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
const SecondPage = () => (
<Layout>
<SEO title="Page two" />
<h1>Hi from the second page</h1>
<p>Welcome to page 2</p>
<Link to="/">Go back to the homepage</Link>
</Layout>
)
export default SecondPage

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

Some files were not shown because too many files have changed in this diff Show More