oipage 1.7.0 → 1.8.0-alpha.0

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 (101) hide show
  1. package/.github/FUNDING.yml +11 -11
  2. package/AUTHORS.txt +6 -6
  3. package/CHANGELOG +9 -1
  4. package/LICENSE +20 -20
  5. package/README.md +1 -9
  6. package/bin/WebSocket/decodeWsFrame.js +43 -43
  7. package/bin/WebSocket/encodeWsFrame.js +28 -28
  8. package/bin/WebSocket/headersToJSON.js +26 -26
  9. package/bin/WebSocket/index.js +80 -80
  10. package/bin/data/mineTypes.json +104 -104
  11. package/bin/disk.js +42 -42
  12. package/bin/help.js +3 -0
  13. package/bin/intercept.js +15 -15
  14. package/bin/network.js +21 -21
  15. package/bin/run +5 -3
  16. package/bin/serve.d.ts +7 -0
  17. package/bin/serve.js +9 -1
  18. package/bin/template/404.html +186 -186
  19. package/bin/tools/deleteEmptyFolder.js +23 -23
  20. package/bin/tools/format.js +75 -75
  21. package/bin/tools/network.js +42 -42
  22. package/bin/tools/openBrowser.js +26 -0
  23. package/bin/tools/resolve404.js +83 -83
  24. package/bin/tools/resolveImport.js +88 -88
  25. package/bin/website-htmls/components/ui-select-file/index.html +7 -7
  26. package/bin/website-htmls/components/ui-select-file/index.js +37 -37
  27. package/bin/website-htmls/components/ui-select-file/index.scss +44 -44
  28. package/bin/website-htmls/dialogs/imageSize/index.html +54 -54
  29. package/bin/website-htmls/dialogs/imageSize/index.js +53 -53
  30. package/bin/website-htmls/dialogs/imageSize/index.scss +138 -138
  31. package/bin/website-htmls/dialogs/index.js +52 -52
  32. package/bin/website-htmls/images/addFile.svg +1 -1
  33. package/bin/website-htmls/images/img-to-pdf.svg +1 -1
  34. package/bin/website-htmls/index.html +17 -17
  35. package/bin/website-htmls/main.js +13 -13
  36. package/bin/website-htmls/pages/App/index.html +6 -6
  37. package/bin/website-htmls/pages/App/index.js +22 -22
  38. package/bin/website-htmls/pages/App/index.scss +43 -43
  39. package/bin/website-htmls/pages/appStore/index.html +5 -24
  40. package/bin/website-htmls/pages/appStore/index.js +19 -19
  41. package/bin/website-htmls/pages/appStore/index.scss +6 -4
  42. package/bin/website-htmls/pages/chart/index.html +8 -8
  43. package/bin/website-htmls/pages/chart/index.js +72 -72
  44. package/bin/website-htmls/pages/chart/index.scss +73 -72
  45. package/bin/website-htmls/pages/home/index.html +22 -0
  46. package/bin/website-htmls/pages/home/index.js +20 -0
  47. package/bin/website-htmls/pages/home/index.scss +29 -0
  48. package/bin/website-htmls/pages/image-editor/index.html +27 -27
  49. package/bin/website-htmls/pages/image-editor/index.js +106 -106
  50. package/bin/website-htmls/pages/image-editor/index.scss +47 -45
  51. package/bin/website-htmls/pages/img-to-pdf/index.html +3 -3
  52. package/bin/website-htmls/pages/img-to-pdf/index.js +44 -44
  53. package/bin/website-htmls/pages/img-to-pdf/index.scss +4 -4
  54. package/bin/website-htmls/router.config.js +26 -19
  55. package/bin/website-htmls/styles/normalize.css +94 -94
  56. package/bin/website-plugins/intercept/chart.js +33 -33
  57. package/bin/website-plugins/intercept/getPackage.js +17 -17
  58. package/bin/website-plugins/intercept/head.js +8 -8
  59. package/bin/website-plugins/intercept/index.js +8 -8
  60. package/bin/website-plugins/intercept/oipage-vislite-intercept.js +30 -30
  61. package/bin/website-plugins/intercept/oipage-zipaper-intercept.js +36 -36
  62. package/bin/website-plugins/loader/index.js +11 -11
  63. package/bin/website-plugins/loader/oipage-html-loader.js +7 -7
  64. package/bin/website-plugins/loader/oipage-scss-loader.js +149 -149
  65. package/nodejs/animation/index.d.ts +19 -19
  66. package/nodejs/animation/index.js +112 -112
  67. package/nodejs/cmdlog/index.d.ts +20 -20
  68. package/nodejs/cmdlog/index.js +75 -75
  69. package/nodejs/disk/index.d.ts +47 -47
  70. package/nodejs/disk/index.js +165 -165
  71. package/nodejs/format/index.d.ts +29 -29
  72. package/nodejs/format/index.js +107 -107
  73. package/nodejs/json/index.d.ts +9 -9
  74. package/nodejs/json/index.js +206 -206
  75. package/nodejs/logform/index.d.ts +18 -18
  76. package/nodejs/logform/index.js +94 -94
  77. package/nodejs/reader/index.d.ts +32 -32
  78. package/nodejs/reader/index.js +20 -20
  79. package/nodejs/throttle/index.d.ts +30 -30
  80. package/nodejs/throttle/index.js +50 -50
  81. package/package.json +1 -1
  82. package/web/XMLHttpRequest/index.d.ts +17 -17
  83. package/web/XMLHttpRequest/index.js +60 -60
  84. package/web/animation/index.d.ts +19 -19
  85. package/web/animation/index.js +112 -112
  86. package/web/format/index.d.ts +29 -29
  87. package/web/format/index.js +107 -107
  88. package/web/json/index.d.ts +9 -9
  89. package/web/json/index.js +206 -206
  90. package/web/onReady/index.d.ts +7 -7
  91. package/web/onReady/index.js +8 -8
  92. package/web/performChunk/index.d.ts +4 -4
  93. package/web/performChunk/index.js +19 -19
  94. package/web/reader/index.d.ts +32 -32
  95. package/web/reader/index.js +20 -20
  96. package/web/style/index.d.ts +21 -21
  97. package/web/style/index.js +19 -19
  98. package/web/throttle/index.d.ts +30 -30
  99. package/web/throttle/index.js +50 -50
  100. package/snipping/chart.png +0 -0
  101. package/snipping/image-editor.png +0 -0
@@ -0,0 +1,26 @@
1
+ const { exec } = require('child_process');
2
+ const os = require('os');
3
+
4
+ module.exports = function (url) {
5
+ const platform = os.platform();
6
+ let command;
7
+
8
+ switch (platform) {
9
+ case 'win32': // Windows
10
+ command = `start ${url}`;
11
+ break;
12
+ case 'darwin': // macOS
13
+ command = `open ${url}`;
14
+ break;
15
+ default: // Linux及其他
16
+ command = `xdg-open ${url}`;
17
+ }
18
+
19
+ exec(command, (error) => {
20
+ if (error) {
21
+ console.error(`无法打开浏览器: ${error}`);
22
+ } else {
23
+ // todo
24
+ }
25
+ });
26
+ }
@@ -1,84 +1,84 @@
1
- const { readdirSync, lstatSync, readFileSync, statSync } = require("fs");
2
- const { join } = require("path");
3
- const { formatByte, formatTime } = require("./format");
4
- const mineTypes = require("../data/mineTypes.json");
5
-
6
- const img_folder = "data:image/png;base64," + readFileSync(join(__dirname, "../images/folder.png")).toString('base64');
7
- const img_file = "data:image/png;base64," + readFileSync(join(__dirname, "../images/file.png")).toString('base64');
8
-
9
- const template_404 = readFileSync(join(__dirname, "../template/404.html"), {
10
- encoding: "utf8"
11
- })
12
- .replace("${img_folder}", img_folder)
13
- .replace("${img_file}", img_file);
14
-
15
- module.exports = function (filePath, url) {
16
-
17
- let subItems = [];
18
-
19
- try {
20
- subItems = readdirSync(filePath);
21
- console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read Folder: " + url + '\x1b[0m ' + new Date().toLocaleString());
22
- } catch (e) {
23
- console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read " + (/\/$/.test(url) ? "Folder" : "File") + ": \x1b[35m" + url + ' 404 Not Found\x1b[0m ' + new Date().toLocaleString());
24
- try {
25
- if (!/\/$/.test(url) || url === "/") {
26
- filePath = join(filePath, "../");
27
- subItems = readdirSync(filePath);
28
- }
29
- } catch (e) { }
30
- }
31
-
32
- let template = "";
33
- for (let i in subItems) {
34
- let isDirectory = lstatSync(join(filePath, subItems[i])).isDirectory();
35
- let statObj = statSync(join(filePath, subItems[i]));
36
-
37
- // 文件夹
38
- if (isDirectory) {
39
- template += `<tr class="folder">
40
- <th class="name">
41
- <a href='./${subItems[i]}/'>${subItems[i]}</a>
42
- </th>
43
- <th>
44
- ${formatTime(statObj.mtime)}
45
- </th>
46
- <th>
47
- 文件夹
48
- </th>
49
- <th>
50
- -
51
- </th>
52
- <th>
53
- <a href='./${subItems[i]}/' class="btn">打开</a>
54
- </th>
55
- </tr>`;
56
- }
57
-
58
- // 文件
59
- else {
60
- let dotName = /\./.test(subItems[i]) ? subItems[i].match(/\.([^.]+)$/)[1] : "";
61
-
62
- template += `<tr class="file">
63
- <th class="name">
64
- <a href='./${subItems[i]}'>${subItems[i]}</a>
65
- </th>
66
- <th>
67
- ${formatTime(statObj.mtime)}
68
- </th>
69
- <th>
70
- ${mineTypes[dotName] || "text/plain"}
71
- </th>
72
- <th>
73
- ${formatByte(statObj.size)}
74
- </th>
75
- <th>
76
- <a href='./${subItems[i]}' class="btn">访问</a>
77
- <a href='./${subItems[i]}?download' class="btn" download='${subItems[i]}'>下载</a>
78
- </th>
79
- </tr>`;
80
- }
81
- }
82
-
83
- return template_404.replace("${current}", filePath).replace("${template}", template);
1
+ const { readdirSync, lstatSync, readFileSync, statSync } = require("fs");
2
+ const { join } = require("path");
3
+ const { formatByte, formatTime } = require("./format");
4
+ const mineTypes = require("../data/mineTypes.json");
5
+
6
+ const img_folder = "data:image/png;base64," + readFileSync(join(__dirname, "../images/folder.png")).toString('base64');
7
+ const img_file = "data:image/png;base64," + readFileSync(join(__dirname, "../images/file.png")).toString('base64');
8
+
9
+ const template_404 = readFileSync(join(__dirname, "../template/404.html"), {
10
+ encoding: "utf8"
11
+ })
12
+ .replace("${img_folder}", img_folder)
13
+ .replace("${img_file}", img_file);
14
+
15
+ module.exports = function (filePath, url) {
16
+
17
+ let subItems = [];
18
+
19
+ try {
20
+ subItems = readdirSync(filePath);
21
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read Folder: " + url + '\x1b[0m ' + new Date().toLocaleString());
22
+ } catch (e) {
23
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read " + (/\/$/.test(url) ? "Folder" : "File") + ": \x1b[35m" + url + ' 404 Not Found\x1b[0m ' + new Date().toLocaleString());
24
+ try {
25
+ if (!/\/$/.test(url) || url === "/") {
26
+ filePath = join(filePath, "../");
27
+ subItems = readdirSync(filePath);
28
+ }
29
+ } catch (e) { }
30
+ }
31
+
32
+ let template = "";
33
+ for (let i in subItems) {
34
+ let isDirectory = lstatSync(join(filePath, subItems[i])).isDirectory();
35
+ let statObj = statSync(join(filePath, subItems[i]));
36
+
37
+ // 文件夹
38
+ if (isDirectory) {
39
+ template += `<tr class="folder">
40
+ <th class="name">
41
+ <a href='./${subItems[i]}/'>${subItems[i]}</a>
42
+ </th>
43
+ <th>
44
+ ${formatTime(statObj.mtime)}
45
+ </th>
46
+ <th>
47
+ 文件夹
48
+ </th>
49
+ <th>
50
+ -
51
+ </th>
52
+ <th>
53
+ <a href='./${subItems[i]}/' class="btn">打开</a>
54
+ </th>
55
+ </tr>`;
56
+ }
57
+
58
+ // 文件
59
+ else {
60
+ let dotName = /\./.test(subItems[i]) ? subItems[i].match(/\.([^.]+)$/)[1] : "";
61
+
62
+ template += `<tr class="file">
63
+ <th class="name">
64
+ <a href='./${subItems[i]}'>${subItems[i]}</a>
65
+ </th>
66
+ <th>
67
+ ${formatTime(statObj.mtime)}
68
+ </th>
69
+ <th>
70
+ ${mineTypes[dotName] || "text/plain"}
71
+ </th>
72
+ <th>
73
+ ${formatByte(statObj.size)}
74
+ </th>
75
+ <th>
76
+ <a href='./${subItems[i]}' class="btn">访问</a>
77
+ <a href='./${subItems[i]}?download' class="btn" download='${subItems[i]}'>下载</a>
78
+ </th>
79
+ </tr>`;
80
+ }
81
+ }
82
+
83
+ return template_404.replace("${current}", filePath).replace("${template}", template);
84
84
  };
@@ -1,89 +1,89 @@
1
- const { readFileSync, existsSync, lstatSync } = require("fs");
2
- const { join } = require("path");
3
- const { testIntercept } = require("../intercept.js");
4
-
5
- module.exports = function (basePath, filePath, entry, intercept, isDownload, isWebsite) {
6
- basePath = join(basePath, "./");
7
-
8
- let source = readFileSync(filePath);
9
- let resolveImport = content => content;
10
-
11
- let __resolveImport = function (content) {
12
- return content.replace(/import [^'"]* from (['"])([^'"]*)['"]/sg, function (_importCode, _, _importUrl) {
13
- if (/^[./]/.test(_importUrl)) {
14
- return _importCode;
15
- } else {
16
- return _importCode.replace(_importUrl, _importUrl.replace(/([^/])+/s, function (npmName) {
17
-
18
- if (testIntercept(npmName, intercept)) {
19
- return (isWebsite ? "/_oipage_website_/@modules/" : "/@modules/") + npmName;
20
- } else {
21
-
22
- let node_modulesRootPath = join(filePath, "../");
23
- let prePath = "";
24
- while (true) {
25
- let npmBundlePath = join(node_modulesRootPath, "./node_modules/", npmName);
26
-
27
- // 如果存在
28
- if (existsSync(npmBundlePath) && lstatSync(npmBundlePath).isDirectory()) {
29
- let npmNameValue = npmName;
30
-
31
- // 对于类似 import VISLite from "vislite"
32
- // 需要把包名解析成具体的文件
33
- if (!/\//.test(_importUrl)) {
34
- let bundlePackage = require(join(npmBundlePath, "./package.json"));
35
- npmNameValue = npmName + "/" + bundlePackage.main;
36
- }
37
-
38
- return (prePath ? prePath : "./") + "node_modules/" + npmNameValue;
39
- }
40
-
41
- if (node_modulesRootPath === basePath) {
42
-
43
- // 如果命令行根目录是一个项目
44
- let packagePath = join(basePath, "./package.json");
45
- if (existsSync(packagePath) && !lstatSync(packagePath).isDirectory()) {
46
- let bundlePackage = require(packagePath);
47
- if (!/\//.test(_importUrl)) {
48
- return "/" + bundlePackage.main;
49
- } else {
50
- return "/"
51
- }
52
- }
53
-
54
- return npmName;
55
- } else {
56
- node_modulesRootPath = join(node_modulesRootPath, "../");
57
- prePath = "../" + prePath;
58
- }
59
- }
60
-
61
- }
62
- }));
63
- }
64
- });
65
- };
66
-
67
- // 如果是下载
68
- if (isDownload) {
69
- // todo
70
- }
71
-
72
- // 如果不是直接访问的
73
- else if (!entry) {
74
- source += "";
75
- resolveImport = (content, notResolve) => notResolve ? content : __resolveImport(content);
76
- }
77
-
78
- // 如果是.html或.htm结尾
79
- else if (/\.html{0,1}$/.test(filePath)) {
80
- source = (source + "").replace(/<script type="module">(.*)<\/script>/sg, function (_, _matchCode) {
81
- return `<script type="module">${__resolveImport(_matchCode)}</script>`;
82
- });
83
- }
84
-
85
- return {
86
- source,
87
- resolveImport
88
- };
1
+ const { readFileSync, existsSync, lstatSync } = require("fs");
2
+ const { join } = require("path");
3
+ const { testIntercept } = require("../intercept.js");
4
+
5
+ module.exports = function (basePath, filePath, entry, intercept, isDownload, isWebsite) {
6
+ basePath = join(basePath, "./");
7
+
8
+ let source = readFileSync(filePath);
9
+ let resolveImport = content => content;
10
+
11
+ let __resolveImport = function (content) {
12
+ return content.replace(/import [^'"]* from (['"])([^'"]*)['"]/sg, function (_importCode, _, _importUrl) {
13
+ if (/^[./]/.test(_importUrl)) {
14
+ return _importCode;
15
+ } else {
16
+ return _importCode.replace(_importUrl, _importUrl.replace(/([^/])+/s, function (npmName) {
17
+
18
+ if (testIntercept(npmName, intercept)) {
19
+ return (isWebsite ? "/_oipage_website_/@modules/" : "/@modules/") + npmName;
20
+ } else {
21
+
22
+ let node_modulesRootPath = join(filePath, "../");
23
+ let prePath = "";
24
+ while (true) {
25
+ let npmBundlePath = join(node_modulesRootPath, "./node_modules/", npmName);
26
+
27
+ // 如果存在
28
+ if (existsSync(npmBundlePath) && lstatSync(npmBundlePath).isDirectory()) {
29
+ let npmNameValue = npmName;
30
+
31
+ // 对于类似 import VISLite from "vislite"
32
+ // 需要把包名解析成具体的文件
33
+ if (!/\//.test(_importUrl)) {
34
+ let bundlePackage = require(join(npmBundlePath, "./package.json"));
35
+ npmNameValue = npmName + "/" + bundlePackage.main;
36
+ }
37
+
38
+ return (prePath ? prePath : "./") + "node_modules/" + npmNameValue;
39
+ }
40
+
41
+ if (node_modulesRootPath === basePath) {
42
+
43
+ // 如果命令行根目录是一个项目
44
+ let packagePath = join(basePath, "./package.json");
45
+ if (existsSync(packagePath) && !lstatSync(packagePath).isDirectory()) {
46
+ let bundlePackage = require(packagePath);
47
+ if (!/\//.test(_importUrl)) {
48
+ return "/" + bundlePackage.main;
49
+ } else {
50
+ return "/"
51
+ }
52
+ }
53
+
54
+ return npmName;
55
+ } else {
56
+ node_modulesRootPath = join(node_modulesRootPath, "../");
57
+ prePath = "../" + prePath;
58
+ }
59
+ }
60
+
61
+ }
62
+ }));
63
+ }
64
+ });
65
+ };
66
+
67
+ // 如果是下载
68
+ if (isDownload) {
69
+ // todo
70
+ }
71
+
72
+ // 如果不是直接访问的
73
+ else if (!entry) {
74
+ source += "";
75
+ resolveImport = (content, notResolve) => notResolve ? content : __resolveImport(content);
76
+ }
77
+
78
+ // 如果是.html或.htm结尾
79
+ else if (/\.html{0,1}$/.test(filePath)) {
80
+ source = (source + "").replace(/<script type="module">(.*)<\/script>/sg, function (_, _matchCode) {
81
+ return `<script type="module">${__resolveImport(_matchCode)}</script>`;
82
+ });
83
+ }
84
+
85
+ return {
86
+ source,
87
+ resolveImport
88
+ };
89
89
  };
@@ -1,8 +1,8 @@
1
- <div class="ui-select-file-view">
2
- <h2 class="title" z-bind="_props.title"></h2>
3
- <div class="tips" z-bind="_props.tips"></div>
4
- <div class="file">
5
- <input type="file" multiple id="input" z-on:change.stop="doChange" z-bind:accept="accept" />
6
- <label for="input" z-bind="'选择'+_props.type+'文件'"></label>
7
- </div>
1
+ <div class="ui-select-file-view">
2
+ <h2 class="title" z-bind="_props.title"></h2>
3
+ <div class="tips" z-bind="_props.tips"></div>
4
+ <div class="file">
5
+ <input type="file" multiple id="input" z-on:change.stop="doChange" z-bind:accept="accept" />
6
+ <label for="input" z-bind="'选择'+_props.type+'文件'"></label>
7
+ </div>
8
8
  </div>
@@ -1,38 +1,38 @@
1
- import { defineElement } from "zipaper";
2
- import template from "./index.html";
3
- import style from "./index.scss";
4
-
5
- export default defineElement({
6
- template,
7
- emits: ["change"],
8
- props: {
9
- title: {
10
- type: String,
11
- required: true,
12
- },
13
- tips: {
14
- type: String,
15
- required: true,
16
- },
17
- type: {
18
- type: String,
19
- required: true,
20
- },
21
- },
22
- data() {
23
- return {
24
- accept: {
25
- pdf: "application/pdf",
26
- image: "image/*"
27
- }[this._props.type]
28
- };
29
- },
30
- methods: {
31
- doChange(event, target) {
32
- this.$emit("change", target.files);
33
- }
34
- },
35
- style: {
36
- content: style
37
- }
1
+ import { defineElement } from "zipaper";
2
+ import template from "./index.html";
3
+ import style from "./index.scss";
4
+
5
+ export default defineElement({
6
+ template,
7
+ emits: ["change"],
8
+ props: {
9
+ title: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ tips: {
14
+ type: String,
15
+ required: true,
16
+ },
17
+ type: {
18
+ type: String,
19
+ required: true,
20
+ },
21
+ },
22
+ data() {
23
+ return {
24
+ accept: {
25
+ pdf: "application/pdf",
26
+ image: "image/*"
27
+ }[this._props.type]
28
+ };
29
+ },
30
+ methods: {
31
+ doChange(event, target) {
32
+ this.$emit("change", target.files);
33
+ }
34
+ },
35
+ style: {
36
+ content: style
37
+ }
38
38
  });
@@ -1,45 +1,45 @@
1
- .ui-select-file-view{
2
- &>.title {
3
- text-align: center;
4
- font-weight: 700;
5
- color: rgb(26, 26, 26);
6
- font-size: 36px;
7
- line-height: 48px;
8
- padding-top: 30px;
9
- }
10
-
11
- &>.tips {
12
- text-align: center;
13
- line-height: 30px;
14
- font-size: 22px;
15
- color: rgb(26, 26, 26);
16
- font-weight: 300;
17
- }
18
-
19
- &>.file {
20
- text-align: center;
21
- margin-top: 30px;
22
-
23
- input {
24
- display: none;
25
- }
26
-
27
- label {
28
- line-height: 50px;
29
- display: inline-block;
30
- border: 1px solid gray;
31
- background-image: url("./images/addFile.svg");
32
- background-repeat: no-repeat;
33
- background-position: 5px center;
34
- background-size: auto 70%;
35
- padding-left: 40px;
36
- padding-right: 10px;
37
- border-radius: 5px;
38
-
39
- &:hover {
40
- text-decoration: underline;
41
- cursor: pointer;
42
- }
43
- }
44
- }
1
+ .ui-select-file-view{
2
+ &>.title {
3
+ text-align: center;
4
+ font-weight: 700;
5
+ color: rgb(26, 26, 26);
6
+ font-size: 36px;
7
+ line-height: 48px;
8
+ padding-top: 30px;
9
+ }
10
+
11
+ &>.tips {
12
+ text-align: center;
13
+ line-height: 30px;
14
+ font-size: 22px;
15
+ color: rgb(26, 26, 26);
16
+ font-weight: 300;
17
+ }
18
+
19
+ &>.file {
20
+ text-align: center;
21
+ margin-top: 30px;
22
+
23
+ input {
24
+ display: none;
25
+ }
26
+
27
+ label {
28
+ line-height: 50px;
29
+ display: inline-block;
30
+ border: 1px solid gray;
31
+ background-image: url("./images/addFile.svg");
32
+ background-repeat: no-repeat;
33
+ background-position: 5px center;
34
+ background-size: auto 70%;
35
+ padding-left: 40px;
36
+ padding-right: 10px;
37
+ border-radius: 5px;
38
+
39
+ &:hover {
40
+ text-decoration: underline;
41
+ cursor: pointer;
42
+ }
43
+ }
44
+ }
45
45
  }