@modern-js/server 1.4.9 → 1.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.eslintrc.js +8 -0
  2. package/CHANGELOG.md +56 -0
  3. package/dist/js/modern/constants.js +1 -1
  4. package/dist/js/modern/dev-tools/dev-server-plugin.js +2 -5
  5. package/dist/js/modern/dev-tools/watcher/index.js +1 -2
  6. package/dist/js/modern/server/dev-server-split.js +4 -4
  7. package/dist/js/modern/server/dev-server.js +2 -3
  8. package/dist/js/node/constants.js +1 -1
  9. package/dist/js/node/dev-tools/dev-server-plugin.js +2 -5
  10. package/dist/js/node/dev-tools/watcher/index.js +1 -3
  11. package/dist/js/node/server/dev-server-split.js +4 -4
  12. package/dist/js/node/server/dev-server.js +2 -3
  13. package/dist/types/dev-tools/watcher/index.d.ts +2 -2
  14. package/dist/types/server/dev-server-split.d.ts +2 -2
  15. package/dist/types/types.d.ts +1 -1
  16. package/package.json +10 -10
  17. package/tests/.eslintrc.js +0 -6
  18. package/tests/dev.test.ts +0 -130
  19. package/tests/fixtures/mock/exist/config/mock/index.ts +0 -11
  20. package/tests/fixtures/mock/module-error/config/mock/index.ts +0 -1
  21. package/tests/fixtures/mock/type-error/config/mock/index.ts +0 -3
  22. package/tests/fixtures/mock/zero/config/mock/index.ts +0 -1
  23. package/tests/fixtures/pure/config/mock/index.ts +0 -11
  24. package/tests/fixtures/pure/modern.config.js +0 -5
  25. package/tests/fixtures/pure/package.json +0 -21
  26. package/tests/fixtures/pure/src/App.css +0 -119
  27. package/tests/fixtures/pure/src/App.tsx +0 -43
  28. package/tests/fixtures/pure/tsconfig.json +0 -12
  29. package/tests/fixtures/watch/a.ts +0 -3
  30. package/tests/fixtures/watch/index.ts +0 -5
  31. package/tests/fixtures/watch/stats.txt +0 -1
  32. package/tests/helper.ts +0 -3
  33. package/tests/https.test.ts +0 -17
  34. package/tests/launch-editor.test.ts +0 -58
  35. package/tests/mock.test.ts +0 -150
  36. package/tests/server.test.ts +0 -238
  37. package/tests/tsconfig.json +0 -12
  38. package/tests/watcher.test.ts +0 -231
package/.eslintrc.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['@modern-js'],
4
+ parserOptions: {
5
+ tsconfigRootDir: __dirname,
6
+ project: ['./tsconfig.json'],
7
+ },
8
+ };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,61 @@
1
1
  # @modern-js/server
2
2
 
3
+ ## 1.4.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 6fa74d5f: add internal metrics and logger
8
+ - Updated dependencies [0ee4bb4e]
9
+ - Updated dependencies [a4c5fe78]
10
+ - Updated dependencies [6fa74d5f]
11
+ - @modern-js/utils@1.7.0
12
+ - @modern-js/prod-server@1.1.3
13
+ - @modern-js/server-utils@1.2.4
14
+
15
+ ## 1.4.11
16
+
17
+ ### Patch Changes
18
+
19
+ - a0475f1a: fix: missing @babel/core peer dependencies
20
+ - 895fa0ff: chore: using "workspace:\*" in devDependencies
21
+ - 247e2005: support devServer.devMiddleware, same as webpack-dev-server
22
+ - Updated dependencies [2d155c4c]
23
+ - Updated dependencies [a0499e4f]
24
+ - Updated dependencies [123e432d]
25
+ - Updated dependencies [e5a9b26d]
26
+ - Updated dependencies [0b26b93b]
27
+ - Updated dependencies [123e432d]
28
+ - Updated dependencies [f9f66ef9]
29
+ - Updated dependencies [592edabc]
30
+ - Updated dependencies [895fa0ff]
31
+ - Updated dependencies [3578913e]
32
+ - Updated dependencies [1c3beab3]
33
+ - @modern-js/utils@1.6.0
34
+ - @modern-js/prod-server@1.1.2
35
+ - @modern-js/bff-utils@1.2.4
36
+ - @modern-js/server-utils@1.2.4
37
+
38
+ ## 1.4.10
39
+
40
+ ### Patch Changes
41
+
42
+ - 6cffe99d: chore:
43
+ remove react eslint rules for `modern-js` rule set.
44
+ add .eslintrc for each package to speed up linting
45
+ - 04ae5262: chore: bump @modern-js/utils to v1.4.1 in dependencies
46
+ - 60f7d8bf: feat: add tests dir to npmignore
47
+ - 28ac120a: fix: remove unused webpack/hot/dev-server entry
48
+ - Updated dependencies [b8599d09]
49
+ - Updated dependencies [6cffe99d]
50
+ - Updated dependencies [04ae5262]
51
+ - Updated dependencies [60f7d8bf]
52
+ - Updated dependencies [3bf4f8b0]
53
+ - @modern-js/utils@1.5.0
54
+ - @modern-js/bff-utils@1.2.3
55
+ - @modern-js/hmr-client@1.2.5
56
+ - @modern-js/prod-server@1.1.1
57
+ - @modern-js/server-utils@1.2.3
58
+
3
59
  ## 1.4.9
4
60
 
5
61
  ### Patch Changes
@@ -8,7 +8,7 @@ export const DEFAULT_DEV_OPTIONS = {
8
8
  host: 'localhost'
9
9
  },
10
10
  https: false,
11
- dev: {
11
+ devMiddleware: {
12
12
  writeToDisk: true
13
13
  },
14
14
  watch: true,
@@ -26,10 +26,7 @@ export default class DevServerPlugin {
26
26
  const path = `&path=${client.path}`;
27
27
  const port = `&port=${client.port}`;
28
28
  const clientEntry = `${require.resolve('@modern-js/hmr-client')}?${host}${path}${port}`;
29
-
30
- const hotEntry = require.resolve('webpack/hot/dev-server');
31
-
32
- const additionalEntries = [clientEntry, hotEntry]; // use a hook to add entries if available
29
+ const additionalEntries = [clientEntry]; // use a hook to add entries if available
33
30
 
34
31
  for (const additionalEntry of additionalEntries) {
35
32
  new EntryPlugin(compiler.context, additionalEntry, {
@@ -41,7 +38,7 @@ export default class DevServerPlugin {
41
38
  const compilerOptions = compiler.options;
42
39
  compilerOptions.plugins = compilerOptions.plugins || [];
43
40
 
44
- if (hotEntry && !compilerOptions.plugins.find(p => p.constructor === Webpack.HotModuleReplacementPlugin)) {
41
+ if (!compilerOptions.plugins.find(p => p.constructor === Webpack.HotModuleReplacementPlugin)) {
45
42
  // apply the HMR plugin, if it didn't exist before.
46
43
  const plugin = new Webpack.HotModuleReplacementPlugin();
47
44
  plugin.apply(compiler);
@@ -1,6 +1,5 @@
1
1
  import path from 'path';
2
- import { fs } from '@modern-js/utils';
3
- import chokidar from 'chokidar';
2
+ import { fs, chokidar } from '@modern-js/utils';
4
3
  import { DependencyTree } from "./dependency-tree";
5
4
  import { StatsCache } from "./stats-cache";
6
5
  export const getWatchedFiles = watcher => {
@@ -9,9 +9,9 @@ export class ModernSSRDevServer extends ModernDevServer {
9
9
  return routes.filter(route => route.isSSR);
10
10
  }
11
11
 
12
- async preServerInit() {
12
+ async setupBeforeProdMiddleware() {
13
13
  if (this.runMode === RUN_MODE.FULL) {
14
- await super.preServerInit();
14
+ await super.setupBeforeProdMiddleware();
15
15
  }
16
16
  }
17
17
 
@@ -31,9 +31,9 @@ export class ModernAPIDevServer extends ModernDevServer {
31
31
  return routes.filter(route => route.isApi);
32
32
  }
33
33
 
34
- async preServerInit() {
34
+ async setupBeforeProdMiddleware() {
35
35
  if (this.runMode === RUN_MODE.FULL) {
36
- await super.preServerInit();
36
+ await super.setupBeforeProdMiddleware();
37
37
  }
38
38
  }
39
39
 
@@ -260,12 +260,11 @@ export class ModernDevServer extends ModernServer {
260
260
  const {
261
261
  conf
262
262
  } = this;
263
- this.devMiddleware = webpackDevMiddleware(compiler, {
263
+ this.devMiddleware = webpackDevMiddleware(compiler, _objectSpread({
264
264
  headers: (_conf$tools2 = conf.tools) === null || _conf$tools2 === void 0 ? void 0 : (_conf$tools2$devServe = _conf$tools2.devServer) === null || _conf$tools2$devServe === void 0 ? void 0 : _conf$tools2$devServe.headers,
265
265
  publicPath: '/',
266
- writeToDisk: this.dev.dev.writeToDisk,
267
266
  stats: false
268
- });
267
+ }, this.dev.devMiddleware));
269
268
  return (ctx, next) => {
270
269
  const {
271
270
  req,
@@ -16,7 +16,7 @@ const DEFAULT_DEV_OPTIONS = {
16
16
  host: 'localhost'
17
17
  },
18
18
  https: false,
19
- dev: {
19
+ devMiddleware: {
20
20
  writeToDisk: true
21
21
  },
22
22
  watch: true,
@@ -38,10 +38,7 @@ class DevServerPlugin {
38
38
  const path = `&path=${client.path}`;
39
39
  const port = `&port=${client.port}`;
40
40
  const clientEntry = `${require.resolve('@modern-js/hmr-client')}?${host}${path}${port}`;
41
-
42
- const hotEntry = require.resolve('webpack/hot/dev-server');
43
-
44
- const additionalEntries = [clientEntry, hotEntry]; // use a hook to add entries if available
41
+ const additionalEntries = [clientEntry]; // use a hook to add entries if available
45
42
 
46
43
  for (const additionalEntry of additionalEntries) {
47
44
  new EntryPlugin(compiler.context, additionalEntry, {
@@ -53,7 +50,7 @@ class DevServerPlugin {
53
50
  const compilerOptions = compiler.options;
54
51
  compilerOptions.plugins = compilerOptions.plugins || [];
55
52
 
56
- if (hotEntry && !compilerOptions.plugins.find(p => p.constructor === _webpack.default.HotModuleReplacementPlugin)) {
53
+ if (!compilerOptions.plugins.find(p => p.constructor === _webpack.default.HotModuleReplacementPlugin)) {
57
54
  // apply the HMR plugin, if it didn't exist before.
58
55
  const plugin = new _webpack.default.HotModuleReplacementPlugin();
59
56
  plugin.apply(compiler);
@@ -9,8 +9,6 @@ var _path = _interopRequireDefault(require("path"));
9
9
 
10
10
  var _utils = require("@modern-js/utils");
11
11
 
12
- var _chokidar = _interopRequireDefault(require("chokidar"));
13
-
14
12
  var _dependencyTree = require("./dependency-tree");
15
13
 
16
14
  var _statsCache = require("./stats-cache");
@@ -41,7 +39,7 @@ class Watcher {
41
39
  const filenames = watched.map(filename => filename.replace(/\\/g, '/'));
42
40
  const cache = new _statsCache.StatsCache();
43
41
 
44
- const watcher = _chokidar.default.watch(filenames, options);
42
+ const watcher = _utils.chokidar.watch(filenames, options);
45
43
 
46
44
  watcher.on('ready', () => {
47
45
  cache.add(getWatchedFiles(watcher));
@@ -18,9 +18,9 @@ class ModernSSRDevServer extends _devServer.ModernDevServer {
18
18
  return routes.filter(route => route.isSSR);
19
19
  }
20
20
 
21
- async preServerInit() {
21
+ async setupBeforeProdMiddleware() {
22
22
  if (this.runMode === _prodServer.RUN_MODE.FULL) {
23
- await super.preServerInit();
23
+ await super.setupBeforeProdMiddleware();
24
24
  }
25
25
  }
26
26
 
@@ -43,9 +43,9 @@ class ModernAPIDevServer extends _devServer.ModernDevServer {
43
43
  return routes.filter(route => route.isApi);
44
44
  }
45
45
 
46
- async preServerInit() {
46
+ async setupBeforeProdMiddleware() {
47
47
  if (this.runMode === _prodServer.RUN_MODE.FULL) {
48
- await super.preServerInit();
48
+ await super.setupBeforeProdMiddleware();
49
49
  }
50
50
  }
51
51
 
@@ -284,12 +284,11 @@ class ModernDevServer extends _prodServer.ModernServer {
284
284
  const {
285
285
  conf
286
286
  } = this;
287
- this.devMiddleware = (0, _webpackDevMiddleware.default)(compiler, {
287
+ this.devMiddleware = (0, _webpackDevMiddleware.default)(compiler, _objectSpread({
288
288
  headers: (_conf$tools2 = conf.tools) === null || _conf$tools2 === void 0 ? void 0 : (_conf$tools2$devServe = _conf$tools2.devServer) === null || _conf$tools2$devServe === void 0 ? void 0 : _conf$tools2$devServe.headers,
289
289
  publicPath: '/',
290
- writeToDisk: this.dev.dev.writeToDisk,
291
290
  stats: false
292
- });
291
+ }, this.dev.devMiddleware));
293
292
  return (ctx, next) => {
294
293
  const {
295
294
  req,
@@ -1,5 +1,5 @@
1
- import chokidar, { FSWatcher, WatchOptions } from 'chokidar';
2
- export declare const getWatchedFiles: (watcher: chokidar.FSWatcher) => string[];
1
+ import { FSWatcher, WatchOptions } from '@modern-js/utils';
2
+ export declare const getWatchedFiles: (watcher: FSWatcher) => string[];
3
3
  export default class Watcher {
4
4
  private dependencyTree;
5
5
  private watcher;
@@ -5,12 +5,12 @@ import { ModernDevServer } from './dev-server';
5
5
  export declare class ModernSSRDevServer extends ModernDevServer {
6
6
  protected prepareAPIHandler(_m: ApiServerMode, _: APIServerStartInput['config']): any;
7
7
  protected filterRoutes(routes: ModernRouteInterface[]): ModernRouteInterface[];
8
- protected preServerInit(): Promise<void>;
8
+ protected setupBeforeProdMiddleware(): Promise<void>;
9
9
  protected emitRouteHook(_: HookNames, _input: any): Promise<void>;
10
10
  }
11
11
  export declare class ModernAPIDevServer extends ModernDevServer {
12
12
  protected prepareWebHandler(_: APIServerStartInput['config']): any;
13
13
  protected filterRoutes(routes: ModernRouteInterface[]): ModernRouteInterface[];
14
- protected preServerInit(): Promise<void>;
14
+ protected setupBeforeProdMiddleware(): Promise<void>;
15
15
  protected emitRouteHook(_: HookNames, _input: any): Promise<void>;
16
16
  }
@@ -9,7 +9,7 @@ export declare type DevServerOptions = {
9
9
  host: string;
10
10
  progress?: boolean;
11
11
  };
12
- dev: {
12
+ devMiddleware: {
13
13
  writeToDisk: boolean | ((filename: string) => boolean);
14
14
  };
15
15
  watch: boolean;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.4.9",
14
+ "version": "1.4.12",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -28,13 +28,13 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
+ "@babel/core": "7.16.7",
31
32
  "@babel/register": "^7.15.3",
32
- "@modern-js/bff-utils": "^1.2.2",
33
- "@modern-js/hmr-client": "^1.2.3",
34
- "@modern-js/prod-server": "^1.0.6",
35
- "@modern-js/server-utils": "^1.2.2",
36
- "@modern-js/utils": "^1.3.7",
37
- "chokidar": "^3.5.2",
33
+ "@modern-js/bff-utils": "^1.2.4",
34
+ "@modern-js/hmr-client": "^1.2.5",
35
+ "@modern-js/prod-server": "^1.1.3",
36
+ "@modern-js/server-utils": "^1.2.4",
37
+ "@modern-js/utils": "^1.7.0",
38
38
  "devcert": "^1.1.3",
39
39
  "launch-editor": "^2.2.1",
40
40
  "minimatch": "^3.0.4",
@@ -44,9 +44,9 @@
44
44
  "ws": "^8.2.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@modern-js/core": "1.6.1",
48
- "@modern-js/server-core": "1.2.5",
49
- "@modern-js/types": "^1.3.6",
47
+ "@modern-js/core": "1.10.0",
48
+ "@modern-js/server-core": "1.3.3",
49
+ "@modern-js/types": "1.5.2",
50
50
  "@scripts/build": "0.0.0",
51
51
  "@scripts/jest-config": "0.0.0",
52
52
  "@types/jest": "^26",
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- extends: ['@modern-js'],
3
- parserOptions: {
4
- project: require.resolve('./tsconfig.json'),
5
- },
6
- };
package/tests/dev.test.ts DELETED
@@ -1,130 +0,0 @@
1
- import http from 'http';
2
- import { webpack, HotModuleReplacementPlugin } from 'webpack';
3
- import SocketServer from '../src/dev-tools/socket-server';
4
- import DevServerPlugin from '../src/dev-tools/dev-server-plugin';
5
-
6
- function getRandomPort() {
7
- return Math.floor(Math.random() * (8000 - 1024)) + 1024;
8
- }
9
-
10
- describe('test dev tools', () => {
11
- test('should socket server work correctly', () => {
12
- const port = getRandomPort();
13
- const socketServer: any = new SocketServer({
14
- client: {
15
- port: port.toString(),
16
- overlay: false,
17
- logging: 'error',
18
- path: '/',
19
- host: '127.0.0.1',
20
- },
21
- dev: {
22
- writeToDisk: false,
23
- },
24
- watch: true,
25
- hot: true,
26
- liveReload: true,
27
- });
28
- const app = http.createServer((req, res) => {
29
- res.end();
30
- });
31
-
32
- socketServer.prepare(app);
33
- expect(socketServer.app).toBe(app);
34
- expect(socketServer.stats).toBeUndefined();
35
-
36
- const mockStats = {
37
- toJson: () => ({}),
38
- };
39
- socketServer.updateStats(mockStats);
40
- expect(socketServer.stats).toBe(mockStats);
41
-
42
- const socket = {
43
- state: 1,
44
- readyState: 1,
45
- data: '',
46
- close() {
47
- socket.state = 0;
48
- },
49
- send(data: string) {
50
- socket.data = data;
51
- },
52
- on() {
53
- // empty
54
- },
55
- };
56
-
57
- socketServer.onConnect(socket);
58
-
59
- socketServer.sockets = [socket];
60
- socketServer.sockWrite('test');
61
- expect(socket.data).toBe(JSON.stringify({ type: 'test' }));
62
-
63
- socketServer.singleWrite(socket, 'single');
64
- expect(socket.data).toBe(JSON.stringify({ type: 'single' }));
65
-
66
- socketServer.close();
67
- expect(socket.state).toBe(0);
68
- app.close();
69
- });
70
-
71
- test('should dev server plugin work correctly with hot plugin', () => {
72
- const compiler = webpack({
73
- plugins: [new HotModuleReplacementPlugin()],
74
- });
75
- new DevServerPlugin({
76
- client: {
77
- port: '8080',
78
- overlay: false,
79
- logging: 'error',
80
- path: '/',
81
- host: '127.0.0.1',
82
- },
83
- dev: {
84
- writeToDisk: false,
85
- },
86
- watch: true,
87
- hot: true,
88
- liveReload: true,
89
- }).apply(compiler);
90
-
91
- // expect(compiler.options.entry)
92
- const entryPluginHook = compiler.hooks.compilation.taps.filter(
93
- tap => tap.name === 'EntryPlugin',
94
- );
95
- const hotPluginHook = compiler.hooks.compilation.taps.filter(
96
- tap => tap.name === 'HotModuleReplacementPlugin',
97
- );
98
- expect(entryPluginHook.length).toBe(3);
99
- expect(hotPluginHook.length).toBe(1);
100
- });
101
-
102
- test('should dev server plugin work correctly', () => {
103
- const compiler = webpack({});
104
- new DevServerPlugin({
105
- client: {
106
- port: '8080',
107
- overlay: false,
108
- logging: 'error',
109
- path: '/',
110
- host: '127.0.0.1',
111
- },
112
- dev: {
113
- writeToDisk: false,
114
- },
115
- watch: true,
116
- hot: true,
117
- liveReload: true,
118
- }).apply(compiler);
119
-
120
- // expect(compiler.options.entry)
121
- const entryPluginHook = compiler.hooks.compilation.taps.filter(
122
- tap => tap.name === 'EntryPlugin',
123
- );
124
- const hotPluginHook = compiler.hooks.compilation.taps.filter(
125
- tap => tap.name === 'HotModuleReplacementPlugin',
126
- );
127
- expect(entryPluginHook.length).toBe(3);
128
- expect(hotPluginHook.length).toBe(1);
129
- });
130
- });
@@ -1,11 +0,0 @@
1
- export default {
2
- 'GET /api/getInfo': { data: [1, 2, 3, 4] },
3
-
4
- '/api/getExample': { id: 1 },
5
-
6
- 'GET /api/addInfo': (req: any, res: any) => {
7
- setTimeout(() => {
8
- res.end('delay 2000ms');
9
- }, 2000);
10
- },
11
- };
@@ -1 +0,0 @@
1
- export default null;
@@ -1,3 +0,0 @@
1
- export default {
2
- 'GET /api/getInfo': 'foo',
3
- };
@@ -1 +0,0 @@
1
- export default {};
@@ -1,11 +0,0 @@
1
- export default {
2
- 'GET /api/getInfo': { data: [1, 2, 3, 4] },
3
-
4
- '/api/getExample': { id: 1 },
5
-
6
- 'GET /api/addInfo': (req: any, res: any) => {
7
- setTimeout(() => {
8
- res.end('delay 2000ms');
9
- }, 2000);
10
- },
11
- };
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- server: {
3
- ssr: true,
4
- },
5
- };
@@ -1,21 +0,0 @@
1
- {
2
- "name": "deploy",
3
- "version": "0.1.0",
4
- "scripts": {
5
- "reset": "del-cli node_modules",
6
- "dev": "modern dev",
7
- "build": "modern build",
8
- "start": "modern start",
9
- "new": "modern new",
10
- "lint": "modern lint",
11
- "deploy": "modern deploy"
12
- },
13
- "dependencies": {},
14
- "devDependencies": {},
15
- "modernConfig": {
16
- "runtime": {
17
- "router": true,
18
- "state": true
19
- }
20
- }
21
- }
@@ -1,119 +0,0 @@
1
- html,
2
- body {
3
- padding: 0;
4
- margin: 0;
5
- font-family: nunito_for_arco, Helvetica Neue, Helvetica, PingFang SC,
6
- Hiragino Sans GB, Microsoft YaHei, 微软雅黑, Arial, sans-serif;
7
- }
8
-
9
- * {
10
- -webkit-font-smoothing: antialiased;
11
- -moz-osx-font-smoothing: grayscale;
12
- box-sizing: border-box;
13
- }
14
-
15
- .container {
16
- min-height: 100vh;
17
- max-width: 100%;
18
- display: flex;
19
- flex-direction: column;
20
- justify-content: center;
21
- align-items: center;
22
- }
23
-
24
- main {
25
- padding: 5rem 0;
26
- flex: 1;
27
- display: flex;
28
- flex-direction: column;
29
- justify-content: center;
30
- align-items: center;
31
- }
32
-
33
- .footer {
34
- width: 100%;
35
- height: 80px;
36
- border-top: 1px solid #eaeaea;
37
- display: flex;
38
- justify-content: center;
39
- align-items: center;
40
- background-color: #470000;
41
- }
42
-
43
- .footer a {
44
- display: flex;
45
- justify-content: center;
46
- align-items: center;
47
- flex-grow: 1;
48
- color: #f4f4f4;
49
- text-decoration: none;
50
- font-size: 1.1rem;
51
- }
52
-
53
- .logo {
54
- margin-bottom: 2rem;
55
- }
56
-
57
- .logo svg {
58
- width: 450px;
59
- height: 132px;
60
- }
61
-
62
- .description {
63
- text-align: center;
64
- line-height: 1.5;
65
- font-size: 1.5rem;
66
- }
67
-
68
- .code {
69
- background: #fafafa;
70
- border-radius: 5px;
71
- padding: 0.75rem;
72
- font-size: 1.1rem;
73
- font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
74
- Bitstream Vera Sans Mono, Courier New, monospace;
75
- }
76
-
77
- @media (max-width: 600px) {
78
- .grid {
79
- width: 100%;
80
- flex-direction: column;
81
- }
82
- }
83
-
84
- .grid {
85
- display: flex;
86
- align-items: center;
87
- justify-content: center;
88
- flex-wrap: wrap;
89
- width: 800px;
90
- margin-top: 3rem;
91
- }
92
-
93
- .card {
94
- margin: 1rem;
95
- padding: 1.5rem;
96
- display: flex;
97
- align-items: center;
98
- justify-content: center;
99
- height: 100px;
100
- color: inherit;
101
- text-decoration: none;
102
- border: 1px solid #470000;
103
- color: #470000;
104
- transition: color 0.15s ease, border-color 0.15s ease;
105
- width: 45%;
106
- }
107
-
108
- .card:hover,
109
- .card:focus,
110
- .card:active {
111
- transform: scale(1.05);
112
- transition: 0.1s ease-in-out;
113
- }
114
-
115
- .card h2 {
116
- font-size: 1.5rem;
117
- margin: 0;
118
- padding: 0;
119
- }