@logto/core-kit 2.2.1 → 2.4.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.
- package/lib/openid.d.ts +9 -1
- package/lib/openid.js +30 -1
- package/lib/password-policy.d.ts +4 -2
- package/lib/password-policy.js +5 -2
- package/lib/regex.d.ts +2 -0
- package/lib/regex.js +2 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/integration-test.d.ts +2 -0
- package/lib/utils/integration-test.js +8 -0
- package/lib/utils/regex.d.ts +1 -0
- package/lib/utils/regex.js +8 -0
- package/lib/utils/url.d.ts +5 -0
- package/lib/utils/url.js +15 -0
- package/package.json +15 -19
- package/scss/_console-themes.scss +43 -1
- package/scss/_fonts.scss +1 -0
package/lib/openid.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare enum ReservedResource {
|
|
|
12
12
|
*/
|
|
13
13
|
Organization = "urn:logto:resource:organizations"
|
|
14
14
|
}
|
|
15
|
-
export type UserClaim = 'name' | 'picture' | '
|
|
15
|
+
export type UserClaim = 'name' | 'given_name' | 'family_name' | 'middle_name' | 'nickname' | 'preferred_username' | 'profile' | 'picture' | 'website' | 'email' | 'email_verified' | 'gender' | 'birthdate' | 'zoneinfo' | 'locale' | 'phone_number' | 'phone_number_verified' | 'address' | 'updated_at' | 'username' | 'roles' | 'organizations' | 'organization_data' | 'organization_roles' | 'custom_data' | 'identities' | 'created_at';
|
|
16
16
|
/**
|
|
17
17
|
* Scopes for ID Token and Userinfo Endpoint.
|
|
18
18
|
*/
|
|
@@ -35,6 +35,12 @@ export declare enum UserScope {
|
|
|
35
35
|
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
36
36
|
*/
|
|
37
37
|
Phone = "phone",
|
|
38
|
+
/**
|
|
39
|
+
* Scope for user address.
|
|
40
|
+
*
|
|
41
|
+
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
42
|
+
*/
|
|
43
|
+
Address = "address",
|
|
38
44
|
/**
|
|
39
45
|
* Scope for user's custom data.
|
|
40
46
|
*
|
|
@@ -68,6 +74,8 @@ export declare enum UserScope {
|
|
|
68
74
|
}
|
|
69
75
|
/**
|
|
70
76
|
* Mapped claims that ID Token includes.
|
|
77
|
+
*
|
|
78
|
+
* @see {@link https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims | OpenID Connect Core 1.0} for standard scope - claim mapping.
|
|
71
79
|
*/
|
|
72
80
|
export declare const idTokenClaims: Readonly<Record<UserScope, UserClaim[]>>;
|
|
73
81
|
/**
|
package/lib/openid.js
CHANGED
|
@@ -37,6 +37,12 @@ export var UserScope;
|
|
|
37
37
|
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
38
38
|
*/
|
|
39
39
|
UserScope["Phone"] = "phone";
|
|
40
|
+
/**
|
|
41
|
+
* Scope for user address.
|
|
42
|
+
*
|
|
43
|
+
* See {@link idTokenClaims} for mapped claims in ID Token and {@link userinfoClaims} for additional claims in Userinfo Endpoint.
|
|
44
|
+
*/
|
|
45
|
+
UserScope["Address"] = "address";
|
|
40
46
|
/**
|
|
41
47
|
* Scope for user's custom data.
|
|
42
48
|
*
|
|
@@ -70,11 +76,33 @@ export var UserScope;
|
|
|
70
76
|
})(UserScope || (UserScope = {}));
|
|
71
77
|
/**
|
|
72
78
|
* Mapped claims that ID Token includes.
|
|
79
|
+
*
|
|
80
|
+
* @see {@link https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims | OpenID Connect Core 1.0} for standard scope - claim mapping.
|
|
73
81
|
*/
|
|
74
82
|
export const idTokenClaims = Object.freeze({
|
|
75
|
-
[UserScope.Profile]: [
|
|
83
|
+
[UserScope.Profile]: [
|
|
84
|
+
// Standard claims
|
|
85
|
+
'name',
|
|
86
|
+
'family_name',
|
|
87
|
+
'given_name',
|
|
88
|
+
'middle_name',
|
|
89
|
+
'nickname',
|
|
90
|
+
'preferred_username',
|
|
91
|
+
'profile',
|
|
92
|
+
'picture',
|
|
93
|
+
'website',
|
|
94
|
+
'gender',
|
|
95
|
+
'birthdate',
|
|
96
|
+
'zoneinfo',
|
|
97
|
+
'locale',
|
|
98
|
+
'updated_at',
|
|
99
|
+
// Custom claims
|
|
100
|
+
'username',
|
|
101
|
+
'created_at',
|
|
102
|
+
],
|
|
76
103
|
[UserScope.Email]: ['email', 'email_verified'],
|
|
77
104
|
[UserScope.Phone]: ['phone_number', 'phone_number_verified'],
|
|
105
|
+
[UserScope.Address]: ['address'],
|
|
78
106
|
[UserScope.Roles]: ['roles'],
|
|
79
107
|
[UserScope.Organizations]: ['organizations'],
|
|
80
108
|
[UserScope.OrganizationRoles]: ['organization_roles'],
|
|
@@ -88,6 +116,7 @@ export const userinfoClaims = Object.freeze({
|
|
|
88
116
|
[UserScope.Profile]: [],
|
|
89
117
|
[UserScope.Email]: [],
|
|
90
118
|
[UserScope.Phone]: [],
|
|
119
|
+
[UserScope.Address]: [],
|
|
91
120
|
[UserScope.Roles]: [],
|
|
92
121
|
[UserScope.Organizations]: ['organization_data'],
|
|
93
122
|
[UserScope.OrganizationRoles]: [],
|
package/lib/password-policy.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { type webcrypto } from 'node:crypto';
|
|
1
3
|
import { type DeepPartial } from '@silverhand/essentials';
|
|
2
4
|
import { z } from 'zod';
|
|
3
5
|
/** Password policy configuration type. */
|
|
@@ -137,7 +139,7 @@ export type UserInfo = Partial<{
|
|
|
137
139
|
*/
|
|
138
140
|
export declare class PasswordPolicyChecker {
|
|
139
141
|
/** The Web Crypto API to use. By default, the global `crypto.subtle` will be used. */
|
|
140
|
-
protected readonly subtle: SubtleCrypto;
|
|
142
|
+
protected readonly subtle: webcrypto.SubtleCrypto | SubtleCrypto;
|
|
141
143
|
static symbols: "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
|
|
142
144
|
/** A set of characters that are considered as sequential. */
|
|
143
145
|
static sequence: readonly ["0123456789", "abcdefghijklmnopqrstuvwxyz", "qwertyuiop", "asdfghjkl", "zxcvbnm", "1qaz", "2wsx", "3edc", "4rfv", "5tgb", "6yhn", "7ujm", "8ik", "9ol"];
|
|
@@ -153,7 +155,7 @@ export declare class PasswordPolicyChecker {
|
|
|
153
155
|
readonly policy: PasswordPolicy;
|
|
154
156
|
constructor(policy: DeepPartial<PasswordPolicy>,
|
|
155
157
|
/** The Web Crypto API to use. By default, the global `crypto.subtle` will be used. */
|
|
156
|
-
subtle?: SubtleCrypto);
|
|
158
|
+
subtle?: webcrypto.SubtleCrypto | SubtleCrypto);
|
|
157
159
|
/**
|
|
158
160
|
* Check if a password meets all the policy requirements.
|
|
159
161
|
*
|
package/lib/password-policy.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { getPwnPasswordsForTest, isIntegrationTest } from './utils/integration-test.js';
|
|
2
3
|
/** Password policy configuration guard. */
|
|
3
4
|
export const passwordPolicyGuard = z.object({
|
|
4
5
|
length: z
|
|
@@ -43,7 +44,7 @@ export const passwordPolicyGuard = z.object({
|
|
|
43
44
|
* // ]
|
|
44
45
|
* ```
|
|
45
46
|
*/
|
|
46
|
-
class PasswordPolicyChecker {
|
|
47
|
+
export class PasswordPolicyChecker {
|
|
47
48
|
static { this.symbols = Object.freeze('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '); }
|
|
48
49
|
/** A set of characters that are considered as sequential. */
|
|
49
50
|
static { this.sequence = Object.freeze([
|
|
@@ -213,6 +214,9 @@ class PasswordPolicyChecker {
|
|
|
213
214
|
* @returns Whether the password has been pwned.
|
|
214
215
|
*/
|
|
215
216
|
async hasBeenPwned(password) {
|
|
217
|
+
if (isIntegrationTest()) {
|
|
218
|
+
return getPwnPasswordsForTest().includes(password);
|
|
219
|
+
}
|
|
216
220
|
const hash = await this.subtle.digest('SHA-1', new TextEncoder().encode(password));
|
|
217
221
|
const hashHex = Array.from(new Uint8Array(hash))
|
|
218
222
|
.map((binary) => binary.toString(16).padStart(2, '0'))
|
|
@@ -356,4 +360,3 @@ class PasswordPolicyChecker {
|
|
|
356
360
|
return false;
|
|
357
361
|
}
|
|
358
362
|
}
|
|
359
|
-
export { PasswordPolicyChecker };
|
package/lib/regex.d.ts
CHANGED
|
@@ -7,3 +7,5 @@ export declare const mobileUriSchemeProtocolRegEx: RegExp;
|
|
|
7
7
|
export declare const hexColorRegEx: RegExp;
|
|
8
8
|
export declare const dateRegex: RegExp;
|
|
9
9
|
export declare const noSpaceRegEx: RegExp;
|
|
10
|
+
/** Full domain that consists of at least 3 parts, e.g. foo.bar.com or example-foo.bar.com */
|
|
11
|
+
export declare const domainRegEx: RegExp;
|
package/lib/regex.js
CHANGED
|
@@ -7,3 +7,5 @@ export const mobileUriSchemeProtocolRegEx = /^[a-z][\d+_a-z-]*(\.[\d+_a-z-]+)+:$
|
|
|
7
7
|
export const hexColorRegEx = /^#[\da-f]{3}([\da-f]{3})?$/i;
|
|
8
8
|
export const dateRegex = /^\d{4}(-\d{2}){2}/;
|
|
9
9
|
export const noSpaceRegEx = /^\S+$/;
|
|
10
|
+
/** Full domain that consists of at least 3 parts, e.g. foo.bar.com or example-foo.bar.com */
|
|
11
|
+
export const domainRegEx = /^[\dA-Za-z](?:[\dA-Za-z-]*[\dA-Za-z])?(?:\.[\dA-Za-z](?:[\dA-Za-z-]*[\dA-Za-z])?){2,}$/;
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { yes } from '@silverhand/essentials';
|
|
2
|
+
export const isIntegrationTest = () => yes(process.env.INTEGRATION_TEST);
|
|
3
|
+
export const getPwnPasswordsForTest = () => {
|
|
4
|
+
if (!isIntegrationTest()) {
|
|
5
|
+
throw new Error('This function should only be called in integration tests');
|
|
6
|
+
}
|
|
7
|
+
return Object.freeze(['123456aA', 'test_password']);
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isValidRegEx: (regEx?: string) => boolean;
|
package/lib/utils/url.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export declare const validateRedirectUrl: (url: string, type: 'web' | 'mobile') => boolean;
|
|
2
2
|
export declare const validateUriOrigin: (url: string) => boolean;
|
|
3
|
+
export declare const isValidUrl: (url?: string) => boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Check if the given URL is localhost
|
|
6
|
+
*/
|
|
7
|
+
export declare const isLocalhost: (url: string) => boolean;
|
package/lib/utils/url.js
CHANGED
|
@@ -17,3 +17,18 @@ export const validateUriOrigin = (url) => {
|
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
+
export const isValidUrl = (url) => {
|
|
21
|
+
try {
|
|
22
|
+
return Boolean(url && new URL(url));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Check if the given URL is localhost
|
|
30
|
+
*/
|
|
31
|
+
export const isLocalhost = (url) => {
|
|
32
|
+
const parsedUrl = new URL(url);
|
|
33
|
+
return ['localhost', '127.0.0.1', '::1'].includes(parsedUrl.hostname);
|
|
34
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logto/core-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"author": "Silverhand Inc. <contact@silverhand.io>",
|
|
5
5
|
"homepage": "https://github.com/logto-io/toolkit#readme",
|
|
6
6
|
"repository": {
|
|
@@ -26,34 +26,32 @@
|
|
|
26
26
|
"scss"
|
|
27
27
|
],
|
|
28
28
|
"engines": {
|
|
29
|
-
"node": "^
|
|
29
|
+
"node": "^20.9.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@logto/language-kit": "^1.
|
|
33
|
-
"@logto/shared": "^3.
|
|
32
|
+
"@logto/language-kit": "^1.1.0",
|
|
33
|
+
"@logto/shared": "^3.1.0",
|
|
34
|
+
"@silverhand/essentials": "^2.9.0",
|
|
34
35
|
"color": "^4.2.3"
|
|
35
36
|
},
|
|
36
37
|
"optionalDependencies": {
|
|
37
38
|
"zod": "^3.22.4"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@silverhand/
|
|
42
|
-
"@silverhand/
|
|
43
|
-
"@silverhand/ts-config": "4.0.0",
|
|
44
|
-
"@silverhand/ts-config-react": "4.0.0",
|
|
41
|
+
"@silverhand/eslint-config": "5.0.0",
|
|
42
|
+
"@silverhand/ts-config": "5.0.0",
|
|
43
|
+
"@silverhand/ts-config-react": "5.0.0",
|
|
45
44
|
"@types/color": "^3.0.3",
|
|
46
|
-
"@types/
|
|
47
|
-
"@types/node": "^18.11.18",
|
|
45
|
+
"@types/node": "^20.9.5",
|
|
48
46
|
"@types/react": "^18.0.31",
|
|
47
|
+
"@vitest/coverage-v8": "^1.4.0",
|
|
49
48
|
"eslint": "^8.44.0",
|
|
50
|
-
"jest": "^29.5.0",
|
|
51
49
|
"lint-staged": "^15.0.0",
|
|
52
50
|
"postcss": "^8.4.31",
|
|
53
51
|
"prettier": "^3.0.0",
|
|
54
52
|
"stylelint": "^15.0.0",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
53
|
+
"typescript": "^5.3.3",
|
|
54
|
+
"vitest": "^1.4.0"
|
|
57
55
|
},
|
|
58
56
|
"eslintConfig": {
|
|
59
57
|
"extends": "@silverhand"
|
|
@@ -69,13 +67,11 @@
|
|
|
69
67
|
"precommit": "lint-staged",
|
|
70
68
|
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput --incremental",
|
|
71
69
|
"build": "rm -rf lib/ && tsc -p tsconfig.build.json",
|
|
72
|
-
"build:test": "pnpm build
|
|
70
|
+
"build:test": "pnpm build",
|
|
73
71
|
"lint": "eslint --ext .ts src",
|
|
74
72
|
"lint:report": "pnpm lint --format json --output-file report.json",
|
|
75
73
|
"stylelint": "stylelint \"scss/**/*.scss\"",
|
|
76
|
-
"test
|
|
77
|
-
"test": "pnpm
|
|
78
|
-
"test:ci": "pnpm test:only",
|
|
79
|
-
"test:coverage": "pnpm test:only --silent --coverage"
|
|
74
|
+
"test": "vitest src",
|
|
75
|
+
"test:ci": "pnpm run test --silent --coverage"
|
|
80
76
|
}
|
|
81
77
|
}
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
--color-alert-99: #fff5eb;
|
|
93
93
|
|
|
94
94
|
// color aliases
|
|
95
|
+
--color-static-white: #fff;
|
|
95
96
|
--color-primary: var(--color-primary-40);
|
|
96
97
|
--color-on-primary: var(--color-all-100);
|
|
97
98
|
--color-primary-container: var(--color-primary-90);
|
|
@@ -160,6 +161,18 @@
|
|
|
160
161
|
--color-env-tag-production: rgba(131, 218, 133, 35%);
|
|
161
162
|
--color-specific-icon-bg: #f3effa;
|
|
162
163
|
--color-specific-toggle-off-enable: var(--color-neutral-90);
|
|
164
|
+
--color-specific-unselected-disabled: var(--color-hover); // 8% Neutral-10
|
|
165
|
+
--color-specific-selected-disabled: var(--color-primary-80);
|
|
166
|
+
--color-specific-focused-inside: var(--color-primary-30);
|
|
167
|
+
--color-specific-focused-outside: var(--color-primary-40);
|
|
168
|
+
--color-specific-button-icon: rgba(255, 255, 255, 70%); // 70% static white
|
|
169
|
+
--color-overlay-primary-hover: rgba(93, 52, 242, 8%); // 8% Primary-40
|
|
170
|
+
--color-overlay-primary-pressed: rgba(93, 52, 242, 12%); // 12% Primary-40
|
|
171
|
+
--color-function-n-overlay-primary-focused: rgba(93, 52, 242, 16%); // 16% Primary-40
|
|
172
|
+
--color-overlay-danger-hover: rgba(186, 27, 27, 8%); // 8% Error-40
|
|
173
|
+
--color-overlay-dark-bg-hover: rgba(255, 255, 255, 12%); // 12% static white
|
|
174
|
+
--color-overlay-dark-bg-pressed: rgba(255, 255, 255, 18%); // 18% static white
|
|
175
|
+
--color-overlay-dark-bg-focused: rgba(255, 255, 255, 24%); // 24% static white
|
|
163
176
|
|
|
164
177
|
// Shadows
|
|
165
178
|
--shadow-1: 0 4px 8px rgba(0, 0, 0, 8%);
|
|
@@ -187,7 +200,7 @@
|
|
|
187
200
|
// Background
|
|
188
201
|
--color-bg-body-base: var(--color-neutral-95);
|
|
189
202
|
--color-bg-body: var(--color-neutral-100);
|
|
190
|
-
--color-bg-layer-1: var(--color-
|
|
203
|
+
--color-bg-layer-1: var(--color-all-100);
|
|
191
204
|
--color-bg-layer-2: var(--color-neutral-95);
|
|
192
205
|
--color-bg-body-overlay: var(--color-neutral-100);
|
|
193
206
|
--color-bg-float-base: var(--color-neutral-variant-90);
|
|
@@ -198,6 +211,15 @@
|
|
|
198
211
|
--color-bg-state-unselected: var(--color-neutral-90);
|
|
199
212
|
--color-bg-state-disabled: rgba(25, 28, 29, 8%); // 8% --color-neutral-10
|
|
200
213
|
--color-bg-info-tag: rgba(229, 225, 236, 80%); // 80% --color-neutral-variant-90
|
|
214
|
+
|
|
215
|
+
// code editor
|
|
216
|
+
--color-code-bg: #181133;
|
|
217
|
+
--color-code-bg-float: #30314e;
|
|
218
|
+
--color-code-white: #f7f8f8;
|
|
219
|
+
--color-code-grey: #adaab4;
|
|
220
|
+
--color-code-dark-bg-focused: rgba(255, 255, 255, 24%);
|
|
221
|
+
--color-code-dark-bg-hover: rgba(255, 255, 255, 12%);
|
|
222
|
+
--color-code-dark-bg-pressed: rgba(255, 255, 255, 18%);
|
|
201
223
|
}
|
|
202
224
|
|
|
203
225
|
@mixin dark {
|
|
@@ -294,6 +316,7 @@
|
|
|
294
316
|
--color-alert-99: #2b1700;
|
|
295
317
|
|
|
296
318
|
// color aliases
|
|
319
|
+
--color-static-white: #fff;
|
|
297
320
|
--color-primary: var(--color-primary-70);
|
|
298
321
|
--color-on-primary: var(--color-all-0);
|
|
299
322
|
--color-primary-container: var(--color-primary-30);
|
|
@@ -362,6 +385,18 @@
|
|
|
362
385
|
--color-env-tag-production: rgba(104, 190, 108, 36%);
|
|
363
386
|
--color-specific-icon-bg: rgba(247, 248, 248, 12%);
|
|
364
387
|
--color-specific-toggle-off-enable: var(--color-neutral-90);
|
|
388
|
+
--color-specific-unselected-disabled: var(--color-hover); // 8% Neutral-10
|
|
389
|
+
--color-specific-selected-disabled: var(--color-primary-80);
|
|
390
|
+
--color-specific-focused-inside: var(--color-primary-40);
|
|
391
|
+
--color-specific-focused-outside: rgba(#cabeff, 32%); // 32% Primary-40
|
|
392
|
+
--color-specific-button-icon: rgba(255, 255, 255, 60%); // 60% static white
|
|
393
|
+
--color-overlay-primary-hover: rgba(202, 190, 255, 8%); // 8% Primary-40
|
|
394
|
+
--color-overlay-primary-pressed: rgba(202, 190, 255, 12%); // 12% Primary-40
|
|
395
|
+
--color-function-n-overlay-primary-focused: rgba(202, 190, 255, 16%); // 16% Primary-40
|
|
396
|
+
--color-overlay-danger-hover: rgba(186, 27, 27, 8%); // 8% Error-40
|
|
397
|
+
--color-overlay-dark-bg-hover: rgba(255, 255, 255, 12%); // 12% static white
|
|
398
|
+
--color-overlay-dark-bg-pressed: rgba(255, 255, 255, 18%); // 18% static white
|
|
399
|
+
--color-overlay-dark-bg-focused: rgba(255, 255, 255, 24%); // 24% static white
|
|
365
400
|
|
|
366
401
|
// Shadows
|
|
367
402
|
--shadow-1: 0 4px 8px rgba(0, 0, 0, 8%);
|
|
@@ -403,4 +438,11 @@
|
|
|
403
438
|
--color-bg-state-unselected: var(--color-neutral-90);
|
|
404
439
|
--color-bg-state-disabled: rgba(247, 248, 248, 8%); // 8% --color-neutral-10
|
|
405
440
|
--color-bg-info-tag: var(--color-neutral-variant-90);
|
|
441
|
+
|
|
442
|
+
// code editor
|
|
443
|
+
--color-code-bg: #090613;
|
|
444
|
+
--color-code-bg-float: #232439;
|
|
445
|
+
--color-code-white: #f7f8f8;
|
|
446
|
+
--color-code-grey: #adaab4;
|
|
447
|
+
--color-code-dark-bg-focused: rgba(255, 255, 255, 24%);
|
|
406
448
|
}
|
package/scss/_fonts.scss
CHANGED