Compare commits

...
Author SHA1 Message Date
StandardNotes CI f0c9f899e9 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].2
2022-11-16 09:49:29 +00:00
Karol Sójko ea40427e67 fix(web): remove checking for MFA permissions as all users are permitted to MFA 2022-11-16 10:26:59 +01:00
StandardNotes CI 7d8e212cfe chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-11-15 15:52:21 +00:00
Mo e962e9c745 fix(mobile): show premium modal on iOS 2022-11-15 09:29:59 -06:00
StandardNotes CI d65abb9a49 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-11-15 13:56:50 +00:00
Aman Harwara 68991abba7 feat: add smart view with custom json (#2000) 2022-11-15 18:58:13 +05:30
Mo 7732f55a28 chore: remove slack (#1999) 2022-11-14 12:01:37 -06:00
StandardNotes CI 97dedc8523 chore(release): publish
- @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-11-14 14:33:18 +00:00
Aman Harwara f656185c16 feat: GUI to create smart views (#1997) 2022-11-14 19:40:00 +05:30
Mo 1c23bc1747 fix(mobile): iOS IAP related adjustments 2022-11-14 07:50:50 -06:00
StandardNotes CI eba8dbc38c chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-11-13 21:33:32 +00:00
Mo f42657fa9e fix: show files option in linking menu even if not entitled 2022-11-13 15:10:57 -06:00
StandardNotes CI 2b76d48392 chore(release): publish
- @standardnotes/[email protected].1
 - @standardnotes/[email protected]
2022-11-13 17:44:39 +00:00
Mo 5777e511a9 fix(mobile): android build 2022-11-13 11:16:47 -06:00
StandardNotes CI a57bf11b5d chore(release): publish
- @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-11-13 15:52:08 +00:00
Mo e074805c2b chore: lint 2022-11-13 09:28:53 -06:00
Mo d519aca685 feat: iap (#1996) 2022-11-13 09:28:16 -06:00
StandardNotes CI e56a960bbf chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-11-11 18:49:20 +00:00
Mo da6f36f34c fix: super improvements (#1995)
* feat(super): autolink selection with cmd + k

* feat: super note importer

* feat: handle html import

* fix: ignore load change event emitted by on change plugin
2022-11-11 12:24:46 -06:00
StandardNotes CI 731e9df1af chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-11-11 12:54:56 +00:00
Mo e27ac3126e feat(dev): insert current date and time command in super note (#1994) 2022-11-11 06:32:31 -06:00
StandardNotes CI bdfda04d69 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2022-11-10 15:59:28 +00:00
Mo 2dbc89594e fix: super note improvements (#1991)
* fix: super note previews

* fix; checkmark size

* fix: top padding

* fix: prevent delete shortcut

* fix: spellcheck control

* fix: only embed file if uploaded to current note

* fix: ability to create new tag from editor autocomplete

* feat: protected file embed handling

* fix: event payload
2022-11-10 09:35:53 -06:00
StandardNotes CI 0cbc23f740 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-11-10 08:15:58 +00:00
Aman Harwara 93b6616b78 fix: iframe classname 2022-11-10 13:18:09 +05:30
StandardNotes CI 444aea3688 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-11-09 21:25:15 +00:00
Mo fdf9ab0fcb feat: file drop handling for super notes (#1990) 2022-11-09 14:55:44 -06:00
StandardNotes CI c961d5e17d chore(release): publish
- @standardnotes/[email protected].9
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
2022-11-09 20:52:23 +00:00
Mo 3498130bfb fix: load blocking by network await (#1989) 2022-11-09 14:25:32 -06:00
StandardNotes CI 0275afc99e chore(release): publish
- @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
2022-11-09 17:43:56 +00:00
Mo 10a9889cf4 refactor: directly include themes in web package (#1988) 2022-11-09 11:21:26 -06:00
Mo ac4882b357 fix: link color 2022-11-09 11:00:37 -06:00
Mo 3690104934 Revert "refactor: include themes in components folder"
This reverts commit 711bea0166.
2022-11-09 11:00:09 -06:00
Mo 711bea0166 refactor: include themes in components folder 2022-11-09 09:28:20 -06:00
Mo ec7f915642 refactor: super icons (#1974) 2022-11-09 09:14:49 -06:00
StandardNotes CI 772fbea381 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
2022-11-09 12:31:40 +00:00
Mo 6bcba01dab refactor: inner blocks note links (#1973) 2022-11-09 06:06:46 -06:00
StandardNotes CI 2438443e53 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-11-09 11:13:10 +00:00
Aman Harwara abaf6a95a6 Merge branch 'main' of github.com:standardnotes/app 2022-11-09 16:14:48 +05:30
Aman Harwara 73ff1c35ab fix: editor height 2022-11-09 16:14:38 +05:30
StandardNotes CI 5cf461dcfb chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-11-09 10:11:32 +00:00
Aman Harwara e9e5a20afa fix: links & new note 2022-11-09 15:17:36 +05:30
StandardNotes CI 104c7bf88c chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
2022-11-08 19:56:36 +00:00
Mo 70a9dbcea6 refactor: blocks plugins (#1956) 2022-11-08 13:31:48 -06:00
Mo bfca244061 refactor: introduce error boundary 2022-11-08 13:29:10 -06:00
434 changed files with 7202 additions and 2146 deletions
Binary file not shown.
+1 -2
View File
@@ -3,7 +3,7 @@
Standard Notes is an end-to-end encrypted note-taking app for digitalists and professionals. Capture your notes, files, and lifes work all in one secure place.
[![latest release version](https://img.shields.io/github/v/release/standardnotes/app)](https://github.com/standardnotes/app/releases)
[![Slack](https://img.shields.io/badge/slack-standardnotes-CC2B5E.svg?style=flat&logo=slack)](https://standardnotes.com/slack)
[![Discord](https://img.shields.io/badge/discord-standardnotes-CC2B5E.svg?style=flat&logo=discord)](https://standardnotes.com/discord)
[![Twitter Follow](https://img.shields.io/badge/follow-%40standardnotes-blue.svg?style=flat&logo=twitter)](https://twitter.com/standardnotes)
### Why Standard Notes?
@@ -38,7 +38,6 @@ Join us on
- [Discord](https://standardnotes.com/discord)
- [Twitter](https://twitter.com/StandardNotes)
- [Forum](https://forum.standardnotes.org)
- [Slack](https://standardnotes.com/slack)
Developers can create and publish their own extensions. Visit the [documentation hub](https://docs.standardnotes.com/) to learn more.
+20
View File
@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-14)
**Note:** Version bump only for package @standardnotes/api
# [1.20.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-13)
### Features
* iap ([#1996](https://github.com/standardnotes/app/issues/1996)) ([d519aca](https://github.com/standardnotes/app/commit/d519aca685b32f4b6f7079ba9562ecaf1a18aecb))
## [1.19.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-09)
### Bug Fixes
* load blocking by network await ([#1989](https://github.com/standardnotes/app/issues/1989)) ([3498130](https://github.com/standardnotes/app/commit/3498130bfb4e7ee9764e5c687844fd78bf909150))
## [1.19.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api
## [1.19.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-07)
**Note:** Version bump only for package @standardnotes/api
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.19.7",
"version": "1.20.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -3,4 +3,5 @@ export enum SubscriptionApiOperations {
CancelingInvite,
ListingInvites,
AcceptingInvite,
ConfirmAppleIAP,
}
@@ -11,6 +11,8 @@ import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/Su
import { SubscriptionApiServiceInterface } from './SubscriptionApiServiceInterface'
import { SubscriptionApiOperations } from './SubscriptionApiOperations'
import { Uuid } from '@standardnotes/common'
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from '../../Request'
export class SubscriptionApiService implements SubscriptionApiServiceInterface {
private operationsInProgress: Map<SubscriptionApiOperations, boolean>
@@ -31,11 +33,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
[ApiEndpointParam.ApiVersion]: ApiVersion.v0,
})
this.operationsInProgress.set(SubscriptionApiOperations.ListingInvites, false)
return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.ListingInvites, false)
}
}
@@ -52,11 +54,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
inviteUuid,
})
this.operationsInProgress.set(SubscriptionApiOperations.CancelingInvite, false)
return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.CancelingInvite, false)
}
}
@@ -73,11 +75,11 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
identifier: inviteeEmail,
})
this.operationsInProgress.set(SubscriptionApiOperations.Inviting, false)
return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.Inviting, false)
}
}
@@ -93,11 +95,27 @@ export class SubscriptionApiService implements SubscriptionApiServiceInterface {
inviteUuid,
})
this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, false)
return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericFail)
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.AcceptingInvite, false)
}
}
async confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse> {
if (this.operationsInProgress.get(SubscriptionApiOperations.ConfirmAppleIAP)) {
throw new ApiCallError(ErrorMessage.GenericInProgress)
}
this.operationsInProgress.set(SubscriptionApiOperations.ConfirmAppleIAP, true)
try {
const response = await this.subscriptionServer.confirmAppleIAP(params)
return response
} finally {
this.operationsInProgress.set(SubscriptionApiOperations.ConfirmAppleIAP, false)
}
}
}
@@ -1,5 +1,7 @@
import { Uuid } from '@standardnotes/common'
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from '../../Request'
import { SubscriptionInviteAcceptResponse } from '../../Response/Subscription/SubscriptionInviteAcceptResponse'
import { SubscriptionInviteCancelResponse } from '../../Response/Subscription/SubscriptionInviteCancelResponse'
import { SubscriptionInviteListResponse } from '../../Response/Subscription/SubscriptionInviteListResponse'
@@ -10,4 +12,5 @@ export interface SubscriptionApiServiceInterface {
listInvites(): Promise<SubscriptionInviteListResponse>
cancelInvite(inviteUuid: Uuid): Promise<SubscriptionInviteCancelResponse>
acceptInvite(inviteUuid: Uuid): Promise<SubscriptionInviteAcceptResponse>
confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse>
}
@@ -10,7 +10,11 @@ describe('HttpService', () => {
const host = 'http://bar'
let updateMetaCallback: (meta: HttpResponseMeta) => void
const createService = () => new HttpService(environment, appVersion, snjsVersion, host, updateMetaCallback)
const createService = () => {
const service = new HttpService(environment, appVersion, snjsVersion, updateMetaCallback)
service.setHost(host)
return service
}
beforeEach(() => {
updateMetaCallback = jest.fn()
+7 -2
View File
@@ -1,4 +1,4 @@
import { isString, joinPaths } from '@standardnotes/utils'
import { isString, joinPaths, sleep } from '@standardnotes/utils'
import { Environment } from '@standardnotes/models'
import { HttpRequestParams } from './HttpRequestParams'
import { HttpVerb } from './HttpVerb'
@@ -13,12 +13,13 @@ import { HttpErrorResponseBody } from './HttpErrorResponseBody'
export class HttpService implements HttpServiceInterface {
private authorizationToken?: string
private __latencySimulatorMs?: number
private host!: string
constructor(
private environment: Environment,
private appVersion: string,
private snjsVersion: string,
private host: string,
private updateMetaCallback: (meta: HttpResponseMeta) => void,
) {}
@@ -78,6 +79,10 @@ export class HttpService implements HttpServiceInterface {
private async runHttp(httpRequest: HttpRequest): Promise<HttpResponse> {
const request = this.createXmlRequest(httpRequest)
if (this.__latencySimulatorMs) {
await sleep(this.__latencySimulatorMs, true)
}
const response = await this.runRequest(request, this.createRequestBody(httpRequest))
if (response.meta) {
@@ -0,0 +1,7 @@
export type AppleIAPConfirmRequestParams = {
productId: string
transactionId: string
transactionDate: string
transactionReceipt: string
subscription_token: string
}
+1
View File
@@ -1,4 +1,5 @@
export * from './ApiEndpointParam'
export * from './Subscription/AppleIAPConfirmRequestParams'
export * from './Subscription/SubscriptionInviteAcceptRequestParams'
export * from './Subscription/SubscriptionInviteCancelRequestParams'
export * from './Subscription/SubscriptionInviteDeclineRequestParams'
@@ -0,0 +1,9 @@
import { Either } from '@standardnotes/common'
import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { AppleIAPConfirmResponseBody } from './AppleIAPConfirmResponseBody'
export interface AppleIAPConfirmResponse extends HttpResponse {
data: Either<AppleIAPConfirmResponseBody, HttpErrorResponseBody>
}
@@ -0,0 +1 @@
export type AppleIAPConfirmResponseBody = { success: true } | { success: false; message: string }
@@ -1,3 +1,5 @@
export * from './Subscription/AppleIAPConfirmResponse'
export * from './Subscription/AppleIAPConfirmResponseBody'
export * from './Subscription/SubscriptionInviteAcceptResponse'
export * from './Subscription/SubscriptionInviteAcceptResponseBody'
export * from './Subscription/SubscriptionInviteCancelResponse'
@@ -8,8 +8,13 @@ const SharingPaths = {
listInvites: '/v1/subscription-invites',
}
const ApplePaths = {
confirmAppleIAP: '/v1/subscriptions/apple_iap_confirm',
}
export const Paths = {
v1: {
...SharingPaths,
...ApplePaths,
},
}
@@ -1,4 +1,6 @@
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { HttpServiceInterface } from '../../Http/HttpServiceInterface'
import { AppleIAPConfirmRequestParams } from '../../Request'
import { SubscriptionInviteAcceptRequestParams } from '../../Request/Subscription/SubscriptionInviteAcceptRequestParams'
import { SubscriptionInviteCancelRequestParams } from '../../Request/Subscription/SubscriptionInviteCancelRequestParams'
import { SubscriptionInviteDeclineRequestParams } from '../../Request/Subscription/SubscriptionInviteDeclineRequestParams'
@@ -45,4 +47,10 @@ export class SubscriptionServer implements SubscriptionServerInterface {
return response as SubscriptionInviteResponse
}
async confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse> {
const response = await this.httpService.post(Paths.v1.confirmAppleIAP, params)
return response as AppleIAPConfirmResponse
}
}
@@ -1,3 +1,5 @@
import { AppleIAPConfirmResponse } from './../../Response/Subscription/AppleIAPConfirmResponse'
import { AppleIAPConfirmRequestParams } from './../../Request/Subscription/AppleIAPConfirmRequestParams'
import { SubscriptionInviteAcceptRequestParams } from '../../Request/Subscription/SubscriptionInviteAcceptRequestParams'
import { SubscriptionInviteCancelRequestParams } from '../../Request/Subscription/SubscriptionInviteCancelRequestParams'
import { SubscriptionInviteDeclineRequestParams } from '../../Request/Subscription/SubscriptionInviteDeclineRequestParams'
@@ -15,4 +17,5 @@ export interface SubscriptionServerInterface {
declineInvite(params: SubscriptionInviteDeclineRequestParams): Promise<SubscriptionInviteDeclineResponse>
cancelInvite(params: SubscriptionInviteCancelRequestParams): Promise<SubscriptionInviteCancelResponse>
listInvites(params: SubscriptionInviteListRequestParams): Promise<SubscriptionInviteListResponse>
confirmAppleIAP(params: AppleIAPConfirmRequestParams): Promise<AppleIAPConfirmResponse>
}
+36
View File
@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-11)
### Bug Fixes
* super improvements ([#1995](https://github.com/standardnotes/app/issues/1995)) ([da6f36f](https://github.com/standardnotes/app/commit/da6f36f34cdee324339d2c923d61191b373513f3))
# [1.4.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-11)
### Features
* **dev:** insert current date and time command in super note ([#1994](https://github.com/standardnotes/app/issues/1994)) ([e27ac31](https://github.com/standardnotes/app/commit/e27ac3126ee4fec9e81df8722b6326ba6f38fe5e))
## [1.3.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-10)
### Bug Fixes
* super note improvements ([#1991](https://github.com/standardnotes/app/issues/1991)) ([2dbc895](https://github.com/standardnotes/app/commit/2dbc89594ea2759c49bc318d5efd2b3a5ef3b22d))
## [1.3.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-09)
### Bug Fixes
* link color ([ac4882b](https://github.com/standardnotes/app/commit/ac4882b357162f8737ac32ea9f55884276cc3011))
### Reverts
* Revert "refactor: include themes in components folder" ([3690104](https://github.com/standardnotes/app/commit/3690104934b444ca99eed86c1a41b22a3582811a))
## [1.3.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-09)
**Note:** Version bump only for package @standardnotes/blocks-editor
## [1.3.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-11-08)
**Note:** Version bump only for package @standardnotes/blocks-editor
## 1.3.7 (2022-11-07)
**Note:** Version bump only for package @standardnotes/blocks-editor
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/blocks-editor",
"version": "1.3.7",
"version": "1.4.1",
"private": true,
"main": "./src/index.ts",
"scripts": {
@@ -9,13 +9,13 @@
"dependencies": {
"@lexical/react": "^0.6.0",
"@standardnotes/icons": "workspace:*",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"lexical": "^0.6.0",
"react": "link:../web/node_modules/react",
"react-dom": "link:../web/node_modules/react-dom"
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "link:../web/node_modules/@types/react",
"@types/react-dom": "link:../web/node_modules/@types/react-dom",
"eslint": "*",
"prettier": "*",
"typescript": "*"
@@ -1,5 +1,4 @@
import {FunctionComponent, useCallback, useState} from 'react';
import {LexicalComposer} from '@lexical/react/LexicalComposer';
import {RichTextPlugin} from '@lexical/react/LexicalRichTextPlugin';
import {ContentEditable} from '@lexical/react/LexicalContentEditable';
import {OnChangePlugin} from '@lexical/react/LexicalOnChangePlugin';
@@ -19,35 +18,60 @@ import {HashtagPlugin} from '@lexical/react/LexicalHashtagPlugin';
import {HistoryPlugin} from '@lexical/react/LexicalHistoryPlugin';
import {LinkPlugin} from '@lexical/react/LexicalLinkPlugin';
import {ListPlugin} from '@lexical/react/LexicalListPlugin';
import {EditorState, LexicalEditor} from 'lexical';
import ComponentPickerMenuPlugin from '../Lexical/Plugins/ComponentPickerPlugin';
import BlocksEditorTheme from '../Lexical/Theme/Theme';
import {$getRoot, EditorState, LexicalEditor} from 'lexical';
import HorizontalRulePlugin from '../Lexical/Plugins/HorizontalRulePlugin';
import TwitterPlugin from '../Lexical/Plugins/TwitterPlugin';
import YouTubePlugin from '../Lexical/Plugins/YouTubePlugin';
import AutoEmbedPlugin from '../Lexical/Plugins/AutoEmbedPlugin';
import CollapsiblePlugin from '../Lexical/Plugins/CollapsiblePlugin';
import {BlockEditorNodes} from '../Lexical/Nodes/AllNodes';
// import DraggableBlockPlugin from '../Lexical/Plugins/DraggableBlockPlugin';
import DraggableBlockPlugin from '../Lexical/Plugins/DraggableBlockPlugin';
import CodeHighlightPlugin from '../Lexical/Plugins/CodeHighlightPlugin';
import FloatingTextFormatToolbarPlugin from '../Lexical/Plugins/FloatingTextFormatToolbarPlugin';
import FloatingLinkEditorPlugin from '../Lexical/Plugins/FloatingLinkEditorPlugin';
import {truncateString} from './Utils';
import {SuperEditorContentId} from './Constants';
const BlockDragEnabled = false;
type BlocksEditorProps = {
initialValue: string;
onChange: (value: string) => void;
onChange: (value: string, preview: string) => void;
className?: string;
children?: React.ReactNode;
previewLength: number;
spellcheck?: boolean;
};
export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
initialValue,
onChange,
className,
children,
previewLength,
spellcheck,
}) => {
const [didIgnoreFirstChange, setDidIgnoreFirstChange] = useState(false);
const handleChange = useCallback(
(editorState: EditorState, _editor: LexicalEditor) => {
const stringifiedEditorState = JSON.stringify(editorState.toJSON());
onChange(stringifiedEditorState);
if (!didIgnoreFirstChange) {
setDidIgnoreFirstChange(true);
return;
}
editorState.read(() => {
const childrenNodes = $getRoot().getAllTextNodes().slice(0, 2);
let previewText = '';
childrenNodes.forEach((node, index) => {
previewText += node.getTextContent();
if (index !== childrenNodes.length - 1) {
previewText += '\n';
}
});
previewText = truncateString(previewText, previewLength);
const stringifiedEditorState = JSON.stringify(editorState.toJSON());
onChange(stringifiedEditorState, previewText);
});
},
[onChange],
[onChange, didIgnoreFirstChange],
);
const [floatingAnchorElem, setFloatingAnchorElem] =
@@ -60,56 +84,56 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
};
return (
<LexicalComposer
initialConfig={{
namespace: 'BlocksEditor',
theme: BlocksEditorTheme,
onError: (error: Error) => console.error(error),
editorState:
initialValue && initialValue.length > 0 ? initialValue : undefined,
nodes: BlockEditorNodes,
}}>
<>
<RichTextPlugin
contentEditable={
<div id="blocks-editor" className="editor-scroller">
<div className="editor" ref={onRef}>
<ContentEditable
className={`ContentEditable__root ${className}`}
/>
</div>
<>
{children}
<RichTextPlugin
contentEditable={
<div id="blocks-editor" className="editor-scroller">
<div className="editor" ref={onRef}>
<ContentEditable
id={SuperEditorContentId}
className={`ContentEditable__root ${className}`}
spellCheck={spellcheck}
/>
</div>
}
placeholder=""
ErrorBoundary={LexicalErrorBoundary}
/>
<ListPlugin />
<MarkdownShortcutPlugin
transformers={[
CHECK_LIST,
...ELEMENT_TRANSFORMERS,
...TEXT_FORMAT_TRANSFORMERS,
...TEXT_MATCH_TRANSFORMERS,
]}
/>
<TablePlugin />
<OnChangePlugin onChange={handleChange} />
<HistoryPlugin />
<HorizontalRulePlugin />
<AutoFocusPlugin />
<ComponentPickerMenuPlugin />
<ClearEditorPlugin />
<CheckListPlugin />
<LinkPlugin />
<HashtagPlugin />
<AutoEmbedPlugin />
<TwitterPlugin />
<YouTubePlugin />
<CollapsiblePlugin />
{floatingAnchorElem && (
<>{/* <DraggableBlockPlugin anchorElem={floatingAnchorElem} /> */}</>
)}
</>
</LexicalComposer>
</div>
}
placeholder=""
ErrorBoundary={LexicalErrorBoundary}
/>
<ListPlugin />
<MarkdownShortcutPlugin
transformers={[
CHECK_LIST,
...ELEMENT_TRANSFORMERS,
...TEXT_FORMAT_TRANSFORMERS,
...TEXT_MATCH_TRANSFORMERS,
]}
/>
<TablePlugin />
<OnChangePlugin onChange={handleChange} ignoreSelectionChange={true} />
<HistoryPlugin />
<HorizontalRulePlugin />
<AutoFocusPlugin />
<ClearEditorPlugin />
<CheckListPlugin />
<CodeHighlightPlugin />
<LinkPlugin />
<HashtagPlugin />
<AutoEmbedPlugin />
<TwitterPlugin />
<YouTubePlugin />
<CollapsiblePlugin />
{floatingAnchorElem && (
<>
<FloatingTextFormatToolbarPlugin anchorElem={floatingAnchorElem} />
<FloatingLinkEditorPlugin />
</>
)}
{floatingAnchorElem && BlockDragEnabled && (
<>{<DraggableBlockPlugin anchorElem={floatingAnchorElem} />}</>
)}
</>
);
};
@@ -0,0 +1,31 @@
import {FunctionComponent} from 'react';
import {LexicalComposer} from '@lexical/react/LexicalComposer';
import BlocksEditorTheme from '../Lexical/Theme/Theme';
import {BlockEditorNodes} from '../Lexical/Nodes/AllNodes';
import {Klass, LexicalNode} from 'lexical';
type BlocksEditorComposerProps = {
initialValue: string;
children: React.ReactNode;
nodes?: Array<Klass<LexicalNode>>;
readonly?: boolean;
};
export const BlocksEditorComposer: FunctionComponent<
BlocksEditorComposerProps
> = ({initialValue, children, readonly, nodes = []}) => {
return (
<LexicalComposer
initialConfig={{
namespace: 'BlocksEditor',
theme: BlocksEditorTheme,
editable: !readonly,
onError: (error: Error) => console.error(error),
editorState:
initialValue && initialValue.length > 0 ? initialValue : undefined,
nodes: [...nodes, ...BlockEditorNodes],
}}>
<>{children}</>
</LexicalComposer>
);
};
@@ -0,0 +1 @@
export const SuperEditorContentId = 'super-editor-content';
@@ -0,0 +1,7 @@
export function truncateString(string: string, limit: number) {
if (string.length <= limit) {
return string;
} else {
return string.substring(0, limit) + '...';
}
}
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise"><path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/><path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/></svg>

Before

Width:  |  Height:  |  Size: 325 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise"><path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/><path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/></svg>

Before

Width:  |  Height:  |  Size: 332 B

@@ -1 +0,0 @@
<svg width="16" height="16" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" fill-opacity=".01" d="M0 0h48v48H0z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M37 37a4 4 0 0 0 4-4c0-1.473-1.333-3.473-4-6-2.667 2.527-4 4.527-4 6a4 4 0 0 0 4 4Z" fill="#777"/><path d="m20.854 5.504 3.535 3.536" stroke="#777" stroke-width="4" stroke-linecap="round"/><path d="M23.682 8.333 8.125 23.889 19.44 35.203l15.556-15.557L23.682 8.333Z" stroke="#777" stroke-width="4" stroke-linejoin="round"/><path d="m12 20.073 16.961 5.577M4 43h40" stroke="#777" stroke-width="4" stroke-linecap="round"/></svg>

Before

Width:  |  Height:  |  Size: 626 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-camera"><path d="M15 12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h1.172a3 3 0 0 0 2.12-.879l.83-.828A1 1 0 0 1 6.827 3h2.344a1 1 0 0 1 .707.293l.828.828A3 3 0 0 0 12.828 5H14a1 1 0 0 1 1 1v6zM2 4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1.172a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 9.172 2H6.828a2 2 0 0 0-1.414.586l-.828.828A2 2 0 0 1 3.172 4H2z"/><path d="M8 11a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 1a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7zM3 6.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z"/></svg>

Before

Width:  |  Height:  |  Size: 613 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-card-checklist"><path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/><path d="M7 5.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm-1.496-.854a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0zM7 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm-1.496-.854a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 0 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0z"/></svg>

Before

Width:  |  Height:  |  Size: 703 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill"><path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/></svg>

Before

Width:  |  Height:  |  Size: 244 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-left-text"><path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H4.414A2 2 0 0 0 3 11.586l-2 2V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12.793a.5.5 0 0 0 .854.353l2.853-2.853A1 1 0 0 1 4.414 12H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="M3 3.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 6a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 6zm0 2.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 518 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-right-dots"><path d="M2 1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h9.586a2 2 0 0 1 1.414.586l2 2V2a1 1 0 0 0-1-1H2zm12-1a2 2 0 0 1 2 2v12.793a.5.5 0 0 1-.854.353l-2.853-2.853a1 1 0 0 0-.707-.293H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12z"/><path d="M5 6a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm4 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm4 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>

Before

Width:  |  Height:  |  Size: 440 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-right-text"><path d="M2 1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h9.586a2 2 0 0 1 1.414.586l2 2V2a1 1 0 0 0-1-1H2zm12-1a2 2 0 0 1 2 2v12.793a.5.5 0 0 1-.854.353l-2.853-2.853a1 1 0 0 0-.707-.293H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12z"/><path d="M3 3.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 6a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 6zm0 2.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 520 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-right"><path d="M2 1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h9.586a2 2 0 0 1 1.414.586l2 2V2a1 1 0 0 0-1-1H2zm12-1a2 2 0 0 1 2 2v12.793a.5.5 0 0 1-.854.353l-2.853-2.853a1 1 0 0 0-.707-.293H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12z"/></svg>

Before

Width:  |  Height:  |  Size: 324 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-square-quote"><path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-2.5a2 2 0 0 0-1.6.8L8 14.333 6.1 11.8a2 2 0 0 0-1.6-.8H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2.5a1 1 0 0 1 .8.4l1.9 2.533a1 1 0 0 0 1.6 0l1.9-2.533a1 1 0 0 1 .8-.4H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="M7.066 4.76A1.665 1.665 0 0 0 4 5.668a1.667 1.667 0 0 0 2.561 1.406c-.131.389-.375.804-.777 1.22a.417.417 0 1 0 .6.58c1.486-1.54 1.293-3.214.682-4.112zm4 0A1.665 1.665 0 0 0 8 5.668a1.667 1.667 0 0 0 2.561 1.406c-.131.389-.375.804-.777 1.22a.417.417 0 1 0 .6.58c1.486-1.54 1.293-3.214.682-4.112z"/></svg>

Before

Width:  |  Height:  |  Size: 708 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard"><path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/><path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/></svg>

Before

Width:  |  Height:  |  Size: 469 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-code"><path d="M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8l3.147-3.146zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8l-3.147-3.146z"/></svg>

Before

Width:  |  Height:  |  Size: 338 B

@@ -1 +0,0 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13 5.885v1.166a3.95 3.95 0 0 1-3.949 3.95H6.917a.748.748 0 0 0-.45.15l-1.345 1.007a.752.752 0 0 0-.032 1.181A2.933 2.933 0 0 0 6.95 14h2.716l2.534 1.901a.506.506 0 0 0 .524.047A.501.501 0 0 0 13 15.5V14h.051a2.949 2.949 0 0 0 2.95-2.949v-3.05a3.002 3.002 0 0 0-2.002-2.83.756.756 0 0 0-.999.714" fill="#050505"/><path fill-rule="evenodd" clip-rule="evenodd" d="M9.05 1H2.95A2.952 2.952 0 0 0 0 3.949v3.102A2.952 2.952 0 0 0 2.949 10H3v1.5a.502.502 0 0 0 .8.4L6.334 10H9.05A2.952 2.952 0 0 0 12 7.05V3.95A2.952 2.952 0 0 0 9.05 1" fill="#050505"/></svg>

Before

Width:  |  Height:  |  Size: 677 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-diagram-2"><path fill-rule="evenodd" d="M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 5 7h2.5V6A1.5 1.5 0 0 1 6 4.5v-1zM8.5 5a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1zM3 11.5A1.5 1.5 0 0 1 4.5 10h1A1.5 1.5 0 0 1 7 11.5v1A1.5 1.5 0 0 1 5.5 14h-1A1.5 1.5 0 0 1 3 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1zm4.5.5a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1A1.5 1.5 0 0 1 9 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1z"/></svg>

Before

Width:  |  Height:  |  Size: 782 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download"><path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/><path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/></svg>

Before

Width:  |  Height:  |  Size: 400 B

@@ -1 +0,0 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M4.648 4.475 1.824 12.25H.67l3.252-8.531h.744l-.018.756Zm2.368 7.775-2.83-7.775-.018-.756h.744l3.264 8.531h-1.16Zm-.147-3.158v.926H2.076v-.926H6.87Zm6.024 2.074V7.902c0-.25-.051-.466-.153-.65a.997.997 0 0 0-.445-.434c-.2-.101-.445-.152-.738-.152-.274 0-.514.047-.721.14a1.255 1.255 0 0 0-.48.37.809.809 0 0 0-.17.492H9.101c0-.227.058-.451.175-.674.118-.223.286-.424.504-.603.223-.184.489-.329.797-.434.313-.11.66-.164 1.043-.164.461 0 .867.078 1.219.234.355.157.633.393.832.71.203.312.305.704.305 1.177v2.953c0 .211.017.436.052.674.04.238.096.443.17.615v.094h-1.13a2.022 2.022 0 0 1-.13-.498 4.011 4.011 0 0 1-.046-.586Zm.187-2.76.012.762h-1.096c-.309 0-.584.025-.826.076a1.89 1.89 0 0 0-.61.217.979.979 0 0 0-.504.879c0 .2.046.38.135.545a.98.98 0 0 0 .405.392c.183.094.408.141.674.141.332 0 .625-.07.878-.211a1.83 1.83 0 0 0 .604-.516c.152-.203.234-.4.246-.591l.463.521a1.572 1.572 0 0 1-.223.545 2.607 2.607 0 0 1-1.2 1.025 2.328 2.328 0 0 1-.927.176c-.43 0-.806-.084-1.13-.252a1.933 1.933 0 0 1-.75-.674 1.784 1.784 0 0 1-.264-.955c0-.34.066-.638.199-.896a1.73 1.73 0 0 1 .574-.65c.25-.176.551-.31.903-.399a4.76 4.76 0 0 1 1.177-.135h1.26Z" fill="#000"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.--><path d="M14 95.792C14 42.888 56.888 0 109.793 0h164.368c52.905 0 95.793 42.888 95.793 95.792 0 33.5-17.196 62.984-43.243 80.105 26.047 17.122 43.243 46.605 43.243 80.105 0 52.905-42.888 95.793-95.793 95.793h-2.08c-24.802 0-47.403-9.426-64.415-24.891v88.263c0 53.61-44.009 96.833-97.357 96.833C57.536 512 14 469.243 14 416.207c0-33.498 17.195-62.98 43.24-80.102C31.193 318.983 14 289.5 14 256.002c0-33.5 17.196-62.983 43.242-80.105C31.197 158.776 14 129.292 14 95.792Zm162.288 95.795h-66.495c-35.576 0-64.415 28.84-64.415 64.415 0 35.438 28.617 64.192 64.003 64.414l.412-.001h66.495V191.587Zm31.378 64.415c0 35.575 28.839 64.415 64.415 64.415h2.08c35.576 0 64.415-28.84 64.415-64.415s-28.839-64.415-64.415-64.415h-2.08c-35.576 0-64.415 28.84-64.415 64.415Zm-97.873 95.793-.412-.001c-35.386.221-64.003 28.975-64.003 64.413 0 35.445 29.225 64.415 64.931 64.415 36.282 0 65.979-29.436 65.979-65.455v-63.372h-66.495Zm0-320.417c-35.576 0-64.415 28.84-64.415 64.414 0 35.576 28.84 64.415 64.415 64.415h66.495V31.377h-66.495Zm97.873 128.829h66.495c35.576 0 64.415-28.839 64.415-64.415 0-35.575-28.839-64.414-64.415-64.414h-66.495v128.829Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-image"><path d="M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/><path d="M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12V2z"/></svg>

Before

Width:  |  Height:  |  Size: 367 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-filetype-gif"><path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2H9v-1h3a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5L14 4.5ZM3.278 13.124a1.403 1.403 0 0 0-.14-.492 1.317 1.317 0 0 0-.314-.407 1.447 1.447 0 0 0-.48-.275 1.88 1.88 0 0 0-.636-.1c-.361 0-.67.076-.926.229a1.48 1.48 0 0 0-.583.632 2.136 2.136 0 0 0-.199.95v.506c0 .272.035.52.105.745.07.224.177.417.32.58.142.162.32.288.533.377.215.088.466.132.753.132.268 0 .5-.037.697-.111a1.29 1.29 0 0 0 .788-.77c.065-.174.097-.358.097-.551v-.797H1.717v.589h.823v.255c0 .132-.03.254-.09.363a.67.67 0 0 1-.273.264.967.967 0 0 1-.457.096.87.87 0 0 1-.519-.146.881.881 0 0 1-.305-.413 1.785 1.785 0 0 1-.096-.615v-.499c0-.365.078-.648.234-.85.158-.2.38-.301.665-.301a.96.96 0 0 1 .3.044c.09.03.17.071.236.126a.689.689 0 0 1 .17.19.797.797 0 0 1 .097.25h.776Zm1.353 2.801v-3.999H3.84v4h.79Zm1.493-1.59v1.59h-.791v-3.999H7.88v.653H6.124v1.117h1.605v.638H6.124Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-fonts"><path d="M12.258 3h-8.51l-.083 2.46h.479c.26-1.544.758-1.783 2.693-1.845l.424-.013v7.827c0 .663-.144.82-1.3.923v.52h4.082v-.52c-1.162-.103-1.306-.26-1.306-.923V3.602l.431.013c1.934.062 2.434.301 2.693 1.846h.479L12.258 3z"/></svg>

Before

Width:  |  Height:  |  Size: 333 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear"><path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"/><path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-break"><path d="M0 10.5a.5.5 0 0 1 .5-.5h15a.5.5 0 0 1 0 1H.5a.5.5 0 0 1-.5-.5zM12 0H4a2 2 0 0 0-2 2v7h1V2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v7h1V2a2 2 0 0 0-2-2zm2 12h-1v2a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-2H2v2a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-2z"/></svg>

Before

Width:  |  Height:  |  Size: 348 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-indent-left"><path d="M2 3.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm.646 2.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L4.293 8 2.646 6.354a.5.5 0 0 1 0-.708zM7 6.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 3a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm-5 3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 493 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-code"><path fill-rule="evenodd" d="M8.646 5.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 8 8.646 6.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 8l1.647-1.646a.5.5 0 0 0 0-.708z"/><path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/><path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/></svg>

Before

Width:  |  Height:  |  Size: 742 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-text"><path d="M5 10.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0-2a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/><path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2z"/><path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1z"/></svg>

Before

Width:  |  Height:  |  Size: 729 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-justify"><path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 390 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-link"><path d="M6.354 5.5H4a3 3 0 0 0 0 6h3a3 3 0 0 0 2.83-4H9c-.086 0-.17.01-.25.031A2 2 0 0 1 7 10.5H4a2 2 0 1 1 0-4h1.535c.218-.376.495-.714.82-1z"/><path d="M9 5.5a3 3 0 0 0-2.83 4h1.098A2 2 0 0 1 9 6.5h3a2 2 0 1 1 0 4h-1.535a4.02 4.02 0 0 1-.82 1H12a3 3 0 1 0 0-6H9z"/></svg>

Before

Width:  |  Height:  |  Size: 376 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list-ol"><path fill-rule="evenodd" d="M5 11.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5z"/><path d="M1.713 11.865v-.474H2c.217 0 .363-.137.363-.317 0-.185-.158-.31-.361-.31-.223 0-.367.152-.373.31h-.59c.016-.467.373-.787.986-.787.588-.002.954.291.957.703a.595.595 0 0 1-.492.594v.033a.615.615 0 0 1 .569.631c.003.533-.502.8-1.051.8-.656 0-1-.37-1.008-.794h.582c.008.178.186.306.422.309.254 0 .424-.145.422-.35-.002-.195-.155-.348-.414-.348h-.3zm-.004-4.699h-.604v-.035c0-.408.295-.844.958-.844.583 0 .96.326.96.756 0 .389-.257.617-.476.848l-.537.572v.03h1.054V9H1.143v-.395l.957-.99c.138-.142.293-.304.293-.508 0-.18-.147-.32-.342-.32a.33.33 0 0 0-.342.338v.041zM2.564 5h-.635V2.924h-.031l-.598.42v-.567l.629-.443h.635V5z"/></svg>

Before

Width:  |  Height:  |  Size: 956 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list-ul"><path fill-rule="evenodd" d="M5 11.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm-3 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>

Before

Width:  |  Height:  |  Size: 423 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-lock-fill"><path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/></svg>

Before

Width:  |  Height:  |  Size: 249 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-lock"><path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2zM5 8h6a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1z"/></svg>

Before

Width:  |  Height:  |  Size: 313 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-markdown"><path d="M14 3a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h12zM2 2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H2z"/><path fill-rule="evenodd" d="M9.146 8.146a.5.5 0 0 1 .708 0L11.5 9.793l1.646-1.647a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 0-.708z"/><path fill-rule="evenodd" d="M11.5 5a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0v-4a.5.5 0 0 1 .5-.5z"/><path d="M3.56 11V7.01h.056l1.428 3.239h.774l1.42-3.24h.056V11h1.073V5.001h-1.2l-1.71 3.894h-.039l-1.71-3.894H2.5V11h1.06z"/></svg>

Before

Width:  |  Height:  |  Size: 635 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-mic"><path d="M3.5 6.5A.5.5 0 0 1 4 7v1a4 4 0 0 0 8 0V7a.5.5 0 0 1 1 0v1a5 5 0 0 1-4.5 4.975V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 .5-.5z"/><path d="M10 8a2 2 0 1 1-4 0V3a2 2 0 1 1 4 0v5zM8 0a3 3 0 0 0-3 3v5a3 3 0 0 0 6 0V3a3 3 0 0 0-3-3z"/></svg>

Before

Width:  |  Height:  |  Size: 379 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-indent-right"><path d="M2 3.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm10.646 2.146a.5.5 0 0 1 .708.708L11.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708l2-2zM2 6.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 3a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 479 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-paint-bucket"><path d="M6.192 2.78c-.458-.677-.927-1.248-1.35-1.643a2.972 2.972 0 0 0-.71-.515c-.217-.104-.56-.205-.882-.02-.367.213-.427.63-.43.896-.003.304.064.664.173 1.044.196.687.556 1.528 1.035 2.402L.752 8.22c-.277.277-.269.656-.218.918.055.283.187.593.36.903.348.627.92 1.361 1.626 2.068.707.707 1.441 1.278 2.068 1.626.31.173.62.305.903.36.262.05.64.059.918-.218l5.615-5.615c.118.257.092.512.05.939-.03.292-.068.665-.073 1.176v.123h.003a1 1 0 0 0 1.993 0H14v-.057a1.01 1.01 0 0 0-.004-.117c-.055-1.25-.7-2.738-1.86-3.494a4.322 4.322 0 0 0-.211-.434c-.349-.626-.92-1.36-1.627-2.067-.707-.707-1.441-1.279-2.068-1.627-.31-.172-.62-.304-.903-.36-.262-.05-.64-.058-.918.219l-.217.216zM4.16 1.867c.381.356.844.922 1.311 1.632l-.704.705c-.382-.727-.66-1.402-.813-1.938a3.283 3.283 0 0 1-.131-.673c.091.061.204.15.337.274zm.394 3.965c.54.852 1.107 1.567 1.607 2.033a.5.5 0 1 0 .682-.732c-.453-.422-1.017-1.136-1.564-2.027l1.088-1.088c.054.12.115.243.183.365.349.627.92 1.361 1.627 2.068.706.707 1.44 1.278 2.068 1.626.122.068.244.13.365.183l-4.861 4.862a.571.571 0 0 1-.068-.01c-.137-.027-.342-.104-.608-.252-.524-.292-1.186-.8-1.846-1.46-.66-.66-1.168-1.32-1.46-1.846-.147-.265-.225-.47-.251-.607a.573.573 0 0 1-.01-.068l3.048-3.047zm2.87-1.935a2.44 2.44 0 0 1-.241-.561c.135.033.324.11.562.241.524.292 1.186.8 1.846 1.46.45.45.83.901 1.118 1.31a3.497 3.497 0 0 0-1.066.091 11.27 11.27 0 0 1-.76-.694c-.66-.66-1.167-1.322-1.458-1.847z"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-palette"><path d="M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/><path d="M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8zm-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7z"/></svg>

Before

Width:  |  Height:  |  Size: 768 B

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil-fill"><path d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" class="bi bi-pencil-fill"><path d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/></svg>

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 554 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plug-fill"><path d="M6 0a.5.5 0 0 1 .5.5V3h3V.5a.5.5 0 0 1 1 0V3h1a.5.5 0 0 1 .5.5v3A3.5 3.5 0 0 1 8.5 10c-.002.434-.01.845-.04 1.22-.041.514-.126 1.003-.317 1.424a2.083 2.083 0 0 1-.97 1.028C6.725 13.9 6.169 14 5.5 14c-.998 0-1.61.33-1.974.718A1.922 1.922 0 0 0 3 16H2c0-.616.232-1.367.797-1.968C3.374 13.42 4.261 13 5.5 13c.581 0 .962-.088 1.218-.219.241-.123.4-.3.514-.55.121-.266.193-.621.23-1.09.027-.34.035-.718.037-1.141A3.5 3.5 0 0 1 4 6.5v-3a.5.5 0 0 1 .5-.5h1V.5A.5.5 0 0 1 6 0z"/></svg>

Before

Width:  |  Height:  |  Size: 593 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plug"><path d="M6 0a.5.5 0 0 1 .5.5V3h3V.5a.5.5 0 0 1 1 0V3h1a.5.5 0 0 1 .5.5v3A3.5 3.5 0 0 1 8.5 10c-.002.434-.01.845-.04 1.22-.041.514-.126 1.003-.317 1.424a2.083 2.083 0 0 1-.97 1.028C6.725 13.9 6.169 14 5.5 14c-.998 0-1.61.33-1.974.718A1.922 1.922 0 0 0 3 16H2c0-.616.232-1.367.797-1.968C3.374 13.42 4.261 13 5.5 13c.581 0 .962-.088 1.218-.219.241-.123.4-.3.514-.55.121-.266.193-.621.23-1.09.027-.34.035-.718.037-1.141A3.5 3.5 0 0 1 4 6.5v-3a.5.5 0 0 1 .5-.5h1V.5A.5.5 0 0 1 6 0zM5 4v2.5A2.5 2.5 0 0 0 7.5 9h1A2.5 2.5 0 0 0 11 6.5V4H5z"/></svg>

Before

Width:  |  Height:  |  Size: 644 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-slash-minus"><path d="m1.854 14.854 13-13a.5.5 0 0 0-.708-.708l-13 13a.5.5 0 0 0 .708.708ZM4 1a.5.5 0 0 1 .5.5v2h2a.5.5 0 0 1 0 1h-2v2a.5.5 0 0 1-1 0v-2h-2a.5.5 0 0 1 0-1h2v-2A.5.5 0 0 1 4 1Zm5 11a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5A.5.5 0 0 1 9 12Z"/></svg>

Before

Width:  |  Height:  |  Size: 360 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-send"><path d="M15.854.146a.5.5 0 0 1 .11.54l-5.819 14.547a.75.75 0 0 1-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 0 1 .124-1.33L15.314.037a.5.5 0 0 1 .54.11ZM6.636 10.07l2.761 4.338L14.13 2.576 6.636 10.07Zm6.787-8.201L1.591 6.602l4.339 2.76 7.494-7.493Z"/></svg>

Before

Width:  |  Height:  |  Size: 360 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-square"><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="M10.97 4.97a.75.75 0 0 1 1.071 1.05l-3.992 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.235.235 0 0 1 .02-.022z"/></svg>

Before

Width:  |  Height:  |  Size: 435 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-sticky"><path d="M2.5 1A1.5 1.5 0 0 0 1 2.5v11A1.5 1.5 0 0 0 2.5 15h6.086a1.5 1.5 0 0 0 1.06-.44l4.915-4.914A1.5 1.5 0 0 0 15 8.586V2.5A1.5 1.5 0 0 0 13.5 1h-11zM2 2.5a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 .5.5V8H9.5A1.5 1.5 0 0 0 8 9.5V14H2.5a.5.5 0 0 1-.5-.5v-11zm7 11.293V9.5a.5.5 0 0 1 .5-.5h4.293L9 13.793z"/></svg>

Before

Width:  |  Height:  |  Size: 409 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-table"><path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm15 2h-4v3h4V4zm0 4h-4v3h4V8zm0 4h-4v3h3a1 1 0 0 0 1-1v-2zm-5 3v-3H6v3h4zm-5 0v-3H1v2a1 1 0 0 0 1 1h3zm-4-4h4V8H1v3zm0-4h4V4H1v3zm5-3v3h4V4H6zm4 4H6v3h4V8z"/></svg>

Before

Width:  |  Height:  |  Size: 347 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-center"><path fill-rule="evenodd" d="M4 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 392 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-left"><path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 388 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-paragraph"><path fill-rule="evenodd" d="M2 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm0-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm4-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 393 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-text-right"><path fill-rule="evenodd" d="M6 12.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-4-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5zm4-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-4-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>

Before

Width:  |  Height:  |  Size: 391 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/><path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/></svg>

Before

Width:  |  Height:  |  Size: 546 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3"><path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.506a.58.58 0 0 0-.01 0H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1h-.995a.59.59 0 0 0-.01 0H11Zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5h9.916Zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47ZM8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5Z"/></svg>

Before

Width:  |  Height:  |  Size: 694 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter"><path d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"/></svg>

Before

Width:  |  Height:  |  Size: 616 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-bold"><path d="M8.21 13c2.106 0 3.412-1.087 3.412-2.823 0-1.306-.984-2.283-2.324-2.386v-.055a2.176 2.176 0 0 0 1.852-2.14c0-1.51-1.162-2.46-3.014-2.46H3.843V13H8.21zM5.908 4.674h1.696c.963 0 1.517.451 1.517 1.244 0 .834-.629 1.32-1.73 1.32H5.908V4.673zm0 6.788V8.598h1.73c1.217 0 1.88.492 1.88 1.415 0 .943-.643 1.449-1.832 1.449H5.907z"/></svg>

Before

Width:  |  Height:  |  Size: 446 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h1"><path d="M8.637 13V3.669H7.379V7.62H2.758V3.67H1.5V13h1.258V8.728h4.62V13h1.259zm5.329 0V3.669h-1.244L10.5 5.316v1.265l2.16-1.565h.062V13h1.244z"/></svg>

Before

Width:  |  Height:  |  Size: 258 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h2"><path d="M7.638 13V3.669H6.38V7.62H1.759V3.67H.5V13h1.258V8.728h4.62V13h1.259zm3.022-6.733v-.048c0-.889.63-1.668 1.716-1.668.957 0 1.675.608 1.675 1.572 0 .855-.554 1.504-1.067 2.085l-3.513 3.999V13H15.5v-1.094h-4.245v-.075l2.481-2.844c.875-.998 1.586-1.784 1.586-2.953 0-1.463-1.155-2.556-2.919-2.556-1.941 0-2.966 1.326-2.966 2.74v.049h1.223z"/></svg>

Before

Width:  |  Height:  |  Size: 458 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h3"><path d="M7.637 13V3.669H6.379V7.62H1.758V3.67H.5V13h1.258V8.728h4.62V13h1.259zm3.625-4.272h1.018c1.142 0 1.935.67 1.949 1.674.013 1.005-.78 1.737-2.01 1.73-1.08-.007-1.853-.588-1.935-1.32H9.108c.069 1.327 1.224 2.386 3.083 2.386 1.935 0 3.343-1.155 3.309-2.789-.027-1.51-1.251-2.16-2.037-2.249v-.068c.704-.123 1.764-.91 1.723-2.229-.035-1.353-1.176-2.4-2.954-2.385-1.873.006-2.857 1.162-2.898 2.358h1.196c.062-.69.711-1.299 1.696-1.299.998 0 1.695.622 1.695 1.525.007.922-.718 1.592-1.695 1.592h-.964v1.074z"/></svg>

Before

Width:  |  Height:  |  Size: 622 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h1"><path d="M7.637 13V3.669H6.379V7.62H1.758V3.67H.5V13h1.258V8.728h4.62V13Zm5.337.2v-2.328H9.108V9.828l3.441-6.35h1.632v6.141H15.5v1.253h-1.319V13.2Zm-2.615-3.581h2.615V6.7L13 4.689l-.872 1.7z"/></svg>

Before

Width:  |  Height:  |  Size: 304 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h1"><path d="M7.637 13V3.669H6.379V7.62H1.758V3.67H.5V13h1.258V8.728h4.62V13Zm2.755-5.791a3.763 3.763 0 0 1 2.113-.517 2.973 2.973 0 0 1 2.995 3.1 3.45 3.45 0 0 1-.9 2.442 3.111 3.111 0 0 1-2.393.968 3.327 3.327 0 0 1-2.094-.671 2.758 2.758 0 0 1-1.007-2h1.284a1.387 1.387 0 0 0 .511 1.1 2.384 2.384 0 0 0 1.4.421 1.819 1.819 0 0 0 1.479-.638 2.042 2.042 0 0 0 .437-1.514 2.17 2.17 0 0 0-.567-1.584 1.958 1.958 0 0 0-1.468-.58 2.358 2.358 0 0 0-1.79.789H9.108V3.478h5.931v1.134h-4.647Z"/></svg>

Before

Width:  |  Height:  |  Size: 595 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-h1"><path d="M7.637 13V3.669H6.379V7.62H1.758V3.67H.5V13h1.258V8.728h4.62V13Zm5.039-6.13a2.823 2.823 0 0 1 1.419.364 2.69 2.69 0 0 1 1.022 1.05 3.327 3.327 0 0 1 .383 1.642 3.594 3.594 0 0 1-.39 1.7 2.878 2.878 0 0 1-1.1 1.158 3.165 3.165 0 0 1-1.635.416 2.812 2.812 0 0 1-1.734-.545A3.49 3.49 0 0 1 9.51 11.1a6.515 6.515 0 0 1-.4-2.411A7.726 7.726 0 0 1 9.542 6a4.289 4.289 0 0 1 1.233-1.851 2.831 2.831 0 0 1 1.889-.673A2.7 2.7 0 0 1 13.8 3.7a2.463 2.463 0 0 1 .812.586 2.886 2.886 0 0 1 .514.8 2.768 2.768 0 0 1 .223.861H14a1.488 1.488 0 0 0-.453-.923 1.346 1.346 0 0 0-.935-.329 1.509 1.509 0 0 0-1.072.425 2.839 2.839 0 0 0-.71 1.18 6.808 6.808 0 0 0-.323 1.771 2.639 2.639 0 0 1 .918-.889 2.48 2.48 0 0 1 1.251-.312Zm-.285 5.117a1.617 1.617 0 0 0 .91-.256 1.752 1.752 0 0 0 .614-.713 2.336 2.336 0 0 0 .223-1.037 2.211 2.211 0 0 0-.217-1.01 1.6 1.6 0 0 0-.6-.666 1.671 1.671 0 0 0-.892-.236 1.833 1.833 0 0 0-1.164.377 2.4 2.4 0 0 0-.743 1.009 3.749 3.749 0 0 0 .6 1.845 1.5 1.5 0 0 0 1.269.687Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-italic"><path d="M7.991 11.674 9.53 4.455c.123-.595.246-.71 1.347-.807l.11-.52H7.211l-.11.52c1.06.096 1.128.212 1.005.807L6.57 11.674c-.123.595-.246.71-1.346.806l-.11.52h3.774l.11-.52c-1.06-.095-1.129-.211-1.006-.806z"/></svg>

Before

Width:  |  Height:  |  Size: 327 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-strikethrough"><path d="M6.333 5.686c0 .31.083.581.27.814H5.166a2.776 2.776 0 0 1-.099-.76c0-1.627 1.436-2.768 3.48-2.768 1.969 0 3.39 1.175 3.445 2.85h-1.23c-.11-1.08-.964-1.743-2.25-1.743-1.23 0-2.18.602-2.18 1.607zm2.194 7.478c-2.153 0-3.589-1.107-3.705-2.81h1.23c.144 1.06 1.129 1.703 2.544 1.703 1.34 0 2.31-.705 2.31-1.675 0-.827-.547-1.374-1.914-1.675L8.046 8.5H1v-1h14v1h-3.504c.468.437.675.994.675 1.697 0 1.826-1.436 2.967-3.644 2.967z"/></svg>

Before

Width:  |  Height:  |  Size: 555 B

@@ -1 +0,0 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.354 14.5v-.665l1.553-1.438c.132-.128.243-.243.332-.345.091-.102.16-.203.207-.3.047-.1.07-.207.07-.322a.574.574 0 0 0-.326-.546.748.748 0 0 0-.343-.077.721.721 0 0 0-.35.082.557.557 0 0 0-.23.232.753.753 0 0 0-.08.36h-.876c0-.286.065-.534.194-.744.13-.21.31-.373.543-.488.233-.115.502-.172.806-.172.312 0 .584.055.816.166.233.11.414.261.543.456.13.194.194.418.194.669 0 .165-.033.327-.098.488-.064.16-.178.339-.343.535a7.918 7.918 0 0 1-.697.7l-.637.625v.03h1.832v.754h-3.11ZM5.04 4.273 6.96 7.469h.068l1.93-3.196h1.803L8.073 8.636 10.805 13H8.972L7.03 9.825h-.068L5.018 13H3.194l2.757-4.364-2.723-4.363H5.04Z" fill="currentColor"/></svg>

Before

Width:  |  Height:  |  Size: 725 B

@@ -1 +0,0 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.354 6v-.665l1.553-1.438c.132-.128.243-.243.332-.345a1.31 1.31 0 0 0 .207-.3c.047-.1.07-.207.07-.322a.574.574 0 0 0-.326-.545.748.748 0 0 0-.343-.077.721.721 0 0 0-.35.08.557.557 0 0 0-.23.233.753.753 0 0 0-.08.36h-.876c0-.286.065-.534.194-.744.13-.21.31-.373.543-.488.233-.115.502-.172.806-.172.312 0 .584.055.816.166.233.11.414.261.543.456.13.194.194.417.194.669 0 .165-.033.327-.098.488-.064.16-.178.339-.343.535a7.92 7.92 0 0 1-.697.7l-.637.625v.03h1.832V6h-3.11ZM5.04 4.273 6.96 7.469h.068l1.93-3.196h1.803L8.073 8.636 10.805 13H8.972L7.03 9.825h-.068L5.018 13H3.194l2.757-4.364-2.723-4.363H5.04Z" fill="currentColor"/></svg>

Before

Width:  |  Height:  |  Size: 717 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type-underline"><path d="M5.313 3.136h-1.23V9.54c0 2.105 1.47 3.623 3.917 3.623s3.917-1.518 3.917-3.623V3.136h-1.23v6.323c0 1.49-.978 2.57-2.687 2.57-1.709 0-2.687-1.08-2.687-2.57V3.136zM12.5 15h-9v-1h9v1z"/></svg>

Before

Width:  |  Height:  |  Size: 310 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-upload"><path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/><path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z"/></svg>

Before

Width:  |  Height:  |  Size: 397 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc.--><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256 256-114.6 256-256S397.4 0 256 0zm0 128c39.77 0 72 32.24 72 72s-32.2 72-72 72c-39.76 0-72-32.24-72-72s32.2-72 72-72zm0 320c-52.93 0-100.9-21.53-135.7-56.29C136.5 349.9 176.5 320 224 320h64c47.54 0 87.54 29.88 103.7 71.71C356.9 426.5 308.9 448 256 448z"/></svg>

Before

Width:  |  Height:  |  Size: 544 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube"><path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/></svg>

Before

Width:  |  Height:  |  Size: 900 B

@@ -31,6 +31,7 @@ interface PlaygroundEmbedConfig extends EmbedConfig {
// Icon for display.
icon?: JSX.Element;
iconName: string;
// An example of a matching url https://twitter.com/jack/status/20
exampleUrl: string;
@@ -49,6 +50,7 @@ export const YoutubeEmbedConfig: PlaygroundEmbedConfig = {
// Icon for display.
icon: <i className="icon youtube" />,
iconName: 'youtube',
insertNode: (editor: LexicalEditor, result: EmbedMatchResult) => {
editor.dispatchCommand(INSERT_YOUTUBE_COMMAND, result.id);
@@ -84,6 +86,7 @@ export const TwitterEmbedConfig: PlaygroundEmbedConfig = {
// Icon for display.
icon: <i className="icon tweet" />,
iconName: 'tweet',
// Create the Lexical embed node from the url data.
insertNode: (editor: LexicalEditor, result: EmbedMatchResult) => {
@@ -0,0 +1,21 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import {registerCodeHighlighting} from '@lexical/code';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {useEffect} from 'react';
export default function CodeHighlightPlugin(): JSX.Element | null {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return registerCodeHighlighting(editor);
}, [editor]);
return null;
}
@@ -8,8 +8,8 @@
*/
.Collapsible__container {
background: #fcfcfc;
border: 1px solid #eee;
background: var(--sn-stylekit-contrast-background-color);
border: 1px solid var(--sn-stylekit-contrast-border-color);
border-radius: 10px;
margin-bottom: 8px;
}
@@ -44,7 +44,7 @@
.Collapsible__container[open] .Collapsible__title:before {
border-color: transparent;
border-width: 6px 4px 0 4px;
border-top-color: #000;
border-top-color: var(--sn-stylekit-contrast-color);
}
.Collapsible__content {
@@ -1,357 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import {$createCodeNode} from '@lexical/code';
import {
INSERT_CHECK_LIST_COMMAND,
INSERT_ORDERED_LIST_COMMAND,
INSERT_UNORDERED_LIST_COMMAND,
} from '@lexical/list';
import {INSERT_EMBED_COMMAND} from '@lexical/react/LexicalAutoEmbedPlugin';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {INSERT_HORIZONTAL_RULE_COMMAND} from '@lexical/react/LexicalHorizontalRuleNode';
import {
LexicalTypeaheadMenuPlugin,
TypeaheadOption,
useBasicTypeaheadTriggerMatch,
} from '@lexical/react/LexicalTypeaheadMenuPlugin';
import {$createHeadingNode, $createQuoteNode} from '@lexical/rich-text';
import {$wrapNodes} from '@lexical/selection';
import {INSERT_TABLE_COMMAND} from '@lexical/table';
import {
$createParagraphNode,
$getSelection,
$isRangeSelection,
FORMAT_ELEMENT_COMMAND,
TextNode,
} from 'lexical';
import {useCallback, useMemo, useState} from 'react';
import * as ReactDOM from 'react-dom';
import useModal from '../../Hooks/useModal';
import {EmbedConfigs} from '../AutoEmbedPlugin';
import {INSERT_COLLAPSIBLE_COMMAND} from '../CollapsiblePlugin';
import {InsertTableDialog} from '../TablePlugin';
class ComponentPickerOption extends TypeaheadOption {
// What shows up in the editor
title: string;
// Icon for display
icon?: JSX.Element;
// For extra searching.
keywords: Array<string>;
// TBD
keyboardShortcut?: string;
// What happens when you select this option?
onSelect: (queryString: string) => void;
constructor(
title: string,
options: {
icon?: JSX.Element;
keywords?: Array<string>;
keyboardShortcut?: string;
onSelect: (queryString: string) => void;
},
) {
super(title);
this.title = title;
this.keywords = options.keywords || [];
this.icon = options.icon;
this.keyboardShortcut = options.keyboardShortcut;
this.onSelect = options.onSelect.bind(this);
}
}
function ComponentPickerMenuItem({
index,
isSelected,
onClick,
onMouseEnter,
option,
}: {
index: number;
isSelected: boolean;
onClick: () => void;
onMouseEnter: () => void;
option: ComponentPickerOption;
}) {
let className = 'item';
if (isSelected) {
className += ' selected';
}
return (
<li
key={option.key}
tabIndex={-1}
className={className}
ref={option.setRefElement}
role="option"
aria-selected={isSelected}
id={'typeahead-item-' + index}
onMouseEnter={onMouseEnter}
onClick={onClick}>
{option.icon}
<span className="text">{option.title}</span>
</li>
);
}
export default function ComponentPickerMenuPlugin(): JSX.Element {
const [editor] = useLexicalComposerContext();
const [modal, showModal] = useModal();
const [queryString, setQueryString] = useState<string | null>(null);
const checkForTriggerMatch = useBasicTypeaheadTriggerMatch('/', {
minLength: 0,
});
const getDynamicOptions = useCallback(() => {
const options: Array<ComponentPickerOption> = [];
if (queryString == null) {
return options;
}
const fullTableRegex = new RegExp(/^([1-9]|10)x([1-9]|10)$/);
const partialTableRegex = new RegExp(/^([1-9]|10)x?$/);
const fullTableMatch = fullTableRegex.exec(queryString);
const partialTableMatch = partialTableRegex.exec(queryString);
if (fullTableMatch) {
const [rows, columns] = fullTableMatch[0]
.split('x')
.map((n: string) => parseInt(n, 10));
options.push(
new ComponentPickerOption(`${rows}x${columns} Table`, {
icon: <i className="icon table" />,
keywords: ['table'],
onSelect: () =>
// @ts-ignore Correct types, but since they're dynamic TS doesn't like it.
editor.dispatchCommand(INSERT_TABLE_COMMAND, {columns, rows}),
}),
);
} else if (partialTableMatch) {
const rows = parseInt(partialTableMatch[0], 10);
options.push(
...Array.from({length: 5}, (_, i) => i + 1).map(
(columns) =>
new ComponentPickerOption(`${rows}x${columns} Table`, {
icon: <i className="icon table" />,
keywords: ['table'],
onSelect: () =>
// @ts-ignore Correct types, but since they're dynamic TS doesn't like it.
editor.dispatchCommand(INSERT_TABLE_COMMAND, {columns, rows}),
}),
),
);
}
return options;
}, [editor, queryString]);
const options = useMemo(() => {
const baseOptions = [
new ComponentPickerOption('Paragraph', {
icon: <i className="icon paragraph" />,
keywords: ['normal', 'paragraph', 'p', 'text'],
onSelect: () =>
editor.update(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
$wrapNodes(selection, () => $createParagraphNode());
}
}),
}),
...Array.from({length: 3}, (_, i) => i + 1).map(
(n) =>
new ComponentPickerOption(`Heading ${n}`, {
icon: <i className={`icon h${n}`} />,
keywords: ['heading', 'header', `h${n}`],
onSelect: () =>
editor.update(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
$wrapNodes(selection, () =>
// @ts-ignore Correct types, but since they're dynamic TS doesn't like it.
$createHeadingNode(`h${n}`),
);
}
}),
}),
),
new ComponentPickerOption('Table', {
icon: <i className="icon table" />,
keywords: ['table', 'grid', 'spreadsheet', 'rows', 'columns'],
onSelect: () =>
showModal('Insert Table', (onClose) => (
<InsertTableDialog activeEditor={editor} onClose={onClose} />
)),
}),
new ComponentPickerOption('Numbered List', {
icon: <i className="icon number" />,
keywords: ['numbered list', 'ordered list', 'ol'],
onSelect: () =>
editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined),
}),
new ComponentPickerOption('Bulleted List', {
icon: <i className="icon bullet" />,
keywords: ['bulleted list', 'unordered list', 'ul'],
onSelect: () =>
editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined),
}),
new ComponentPickerOption('Check List', {
icon: <i className="icon check" />,
keywords: ['check list', 'todo list'],
onSelect: () =>
editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND, undefined),
}),
new ComponentPickerOption('Quote', {
icon: <i className="icon quote" />,
keywords: ['block quote'],
onSelect: () =>
editor.update(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
$wrapNodes(selection, () => $createQuoteNode());
}
}),
}),
new ComponentPickerOption('Code', {
icon: <i className="icon code" />,
keywords: ['javascript', 'python', 'js', 'codeblock'],
onSelect: () =>
editor.update(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
if (selection.isCollapsed()) {
$wrapNodes(selection, () => $createCodeNode());
} else {
// Will this ever happen?
const textContent = selection.getTextContent();
const codeNode = $createCodeNode();
selection.insertNodes([codeNode]);
selection.insertRawText(textContent);
}
}
}),
}),
new ComponentPickerOption('Divider', {
icon: <i className="icon horizontal-rule" />,
keywords: ['horizontal rule', 'divider', 'hr'],
onSelect: () =>
editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined),
}),
...EmbedConfigs.map(
(embedConfig) =>
new ComponentPickerOption(`Embed ${embedConfig.contentName}`, {
icon: embedConfig.icon,
keywords: [...embedConfig.keywords, 'embed'],
onSelect: () =>
editor.dispatchCommand(INSERT_EMBED_COMMAND, embedConfig.type),
}),
),
new ComponentPickerOption('Collapsible', {
icon: <i className="icon caret-right" />,
keywords: ['collapse', 'collapsible', 'toggle'],
onSelect: () =>
editor.dispatchCommand(INSERT_COLLAPSIBLE_COMMAND, undefined),
}),
...['left', 'center', 'right', 'justify'].map(
(alignment) =>
new ComponentPickerOption(`Align ${alignment}`, {
icon: <i className={`icon ${alignment}-align`} />,
keywords: ['align', 'justify', alignment],
onSelect: () =>
// @ts-ignore Correct types, but since they're dynamic TS doesn't like it.
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment),
}),
),
];
const dynamicOptions = getDynamicOptions();
return queryString
? [
...dynamicOptions,
...baseOptions.filter((option) => {
return new RegExp(queryString, 'gi').exec(option.title) ||
option.keywords != null
? option.keywords.some((keyword) =>
new RegExp(queryString, 'gi').exec(keyword),
)
: false;
}),
]
: baseOptions;
}, [editor, getDynamicOptions, queryString, showModal]);
const onSelectOption = useCallback(
(
selectedOption: ComponentPickerOption,
nodeToRemove: TextNode | null,
closeMenu: () => void,
matchingString: string,
) => {
editor.update(() => {
if (nodeToRemove) {
nodeToRemove.remove();
}
selectedOption.onSelect(matchingString);
closeMenu();
});
},
[editor],
);
return (
<>
{modal}
<LexicalTypeaheadMenuPlugin<ComponentPickerOption>
onQueryChange={setQueryString}
onSelectOption={onSelectOption}
triggerFn={checkForTriggerMatch}
options={options}
menuRenderFn={(
anchorElementRef,
{selectedIndex, selectOptionAndCleanUp, setHighlightedIndex},
) =>
anchorElementRef.current && options.length
? ReactDOM.createPortal(
<div className="typeahead-popover component-picker-menu">
<ul>
{options.map((option, i: number) => (
<ComponentPickerMenuItem
index={i}
isSelected={selectedIndex === i}
onClick={() => {
setHighlightedIndex(i);
selectOptionAndCleanUp(option);
}}
onMouseEnter={() => {
setHighlightedIndex(i);
}}
key={option.key}
option={option}
/>
))}
</ul>
</div>,
anchorElementRef.current,
)
: null
}
/>
</>
);
}
@@ -0,0 +1,261 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import {$isAutoLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND} from '@lexical/link';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {$findMatchingParent, mergeRegister} from '@lexical/utils';
import {
$getSelection,
$isRangeSelection,
COMMAND_PRIORITY_CRITICAL,
COMMAND_PRIORITY_LOW,
GridSelection,
LexicalEditor,
NodeSelection,
RangeSelection,
SELECTION_CHANGE_COMMAND,
} from 'lexical';
import {useCallback, useEffect, useRef, useState} from 'react';
import {createPortal} from 'react-dom';
import LinkPreview from '../../UI/LinkPreview';
import {getSelectedNode} from '../../Utils/getSelectedNode';
import {sanitizeUrl} from '../../Utils/sanitizeUrl';
import {setFloatingElemPosition} from '../../Utils/setFloatingElemPosition';
import {LexicalPencilFill} from '@standardnotes/icons';
import {IconComponent} from '../../../Lexical/Theme/IconComponent';
function FloatingLinkEditor({
editor,
anchorElem,
}: {
editor: LexicalEditor;
anchorElem: HTMLElement;
}): JSX.Element {
const editorRef = useRef<HTMLDivElement | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
const [linkUrl, setLinkUrl] = useState('');
const [isEditMode, setEditMode] = useState(false);
const [lastSelection, setLastSelection] = useState<
RangeSelection | GridSelection | NodeSelection | null
>(null);
const updateLinkEditor = useCallback(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
const node = getSelectedNode(selection);
const parent = node.getParent();
if ($isLinkNode(parent)) {
setLinkUrl(parent.getURL());
} else if ($isLinkNode(node)) {
setLinkUrl(node.getURL());
} else {
setLinkUrl('');
}
}
const editorElem = editorRef.current;
const nativeSelection = window.getSelection();
const activeElement = document.activeElement;
if (editorElem === null) {
return;
}
const rootElement = editor.getRootElement();
if (
selection !== null &&
nativeSelection !== null &&
rootElement !== null &&
rootElement.contains(nativeSelection.anchorNode)
) {
const domRange = nativeSelection.getRangeAt(0);
let rect;
if (nativeSelection.anchorNode === rootElement) {
let inner = rootElement;
while (inner.firstElementChild != null) {
inner = inner.firstElementChild as HTMLElement;
}
rect = inner.getBoundingClientRect();
} else {
rect = domRange.getBoundingClientRect();
}
setFloatingElemPosition(rect, editorElem, anchorElem);
setLastSelection(selection);
} else if (!activeElement || activeElement.className !== 'link-input') {
if (rootElement !== null) {
setFloatingElemPosition(null, editorElem, anchorElem);
}
setLastSelection(null);
setEditMode(false);
setLinkUrl('');
}
return true;
}, [anchorElem, editor]);
useEffect(() => {
const scrollerElem = anchorElem.parentElement;
const update = () => {
editor.getEditorState().read(() => {
updateLinkEditor();
});
};
window.addEventListener('resize', update);
if (scrollerElem) {
scrollerElem.addEventListener('scroll', update);
}
return () => {
window.removeEventListener('resize', update);
if (scrollerElem) {
scrollerElem.removeEventListener('scroll', update);
}
};
}, [anchorElem.parentElement, editor, updateLinkEditor]);
useEffect(() => {
return mergeRegister(
editor.registerUpdateListener(({editorState}) => {
editorState.read(() => {
updateLinkEditor();
});
}),
editor.registerCommand(
SELECTION_CHANGE_COMMAND,
() => {
updateLinkEditor();
return true;
},
COMMAND_PRIORITY_LOW,
),
);
}, [editor, updateLinkEditor]);
useEffect(() => {
editor.getEditorState().read(() => {
updateLinkEditor();
});
}, [editor, updateLinkEditor]);
useEffect(() => {
if (isEditMode && inputRef.current) {
inputRef.current.focus();
}
}, [isEditMode]);
return (
<div ref={editorRef} className="link-editor">
{isEditMode ? (
<input
ref={inputRef}
className="link-input"
value={linkUrl}
onChange={(event) => {
setLinkUrl(event.target.value);
}}
onKeyDown={(event) => {
if (event.key === 'Enter') {
event.preventDefault();
if (lastSelection !== null) {
if (linkUrl !== '') {
editor.dispatchCommand(
TOGGLE_LINK_COMMAND,
sanitizeUrl(linkUrl),
);
}
setEditMode(false);
}
} else if (event.key === 'Escape') {
event.preventDefault();
setEditMode(false);
}
}}
/>
) : (
<>
<div className="link-input">
<a href={linkUrl} target="_blank" rel="noopener noreferrer">
{linkUrl}
</a>
<div
className="link-edit"
role="button"
tabIndex={0}
onMouseDown={(event) => event.preventDefault()}
onClick={() => {
setEditMode(true);
}}>
<IconComponent size={15}>
<LexicalPencilFill />
</IconComponent>
</div>
</div>
<LinkPreview url={linkUrl} />
</>
)}
</div>
);
}
function useFloatingLinkEditorToolbar(
editor: LexicalEditor,
anchorElem: HTMLElement,
): JSX.Element | null {
const [activeEditor, setActiveEditor] = useState(editor);
const [isLink, setIsLink] = useState(false);
const updateToolbar = useCallback(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
const node = getSelectedNode(selection);
const linkParent = $findMatchingParent(node, $isLinkNode);
const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);
// We don't want this menu to open for auto links.
if (linkParent != null && autoLinkParent == null) {
setIsLink(true);
} else {
setIsLink(false);
}
}
}, []);
useEffect(() => {
return editor.registerCommand(
SELECTION_CHANGE_COMMAND,
(_payload, newEditor) => {
updateToolbar();
setActiveEditor(newEditor);
return false;
},
COMMAND_PRIORITY_CRITICAL,
);
}, [editor, updateToolbar]);
return isLink
? createPortal(
<FloatingLinkEditor editor={activeEditor} anchorElem={anchorElem} />,
anchorElem,
)
: null;
}
export default function FloatingLinkEditorPlugin({
anchorElem = document.body,
}: {
anchorElem?: HTMLElement;
}): JSX.Element | null {
const [editor] = useLexicalComposerContext();
return useFloatingLinkEditorToolbar(editor, anchorElem);
}
@@ -0,0 +1,128 @@
.floating-text-format-popup {
display: flex;
vertical-align: middle;
position: absolute;
top: 0;
left: 0;
z-index: 10;
opacity: 0;
background-color: var(--sn-stylekit-contrast-background-color);
box-shadow: 0px 5px 10px var(--sn-stylekit-shadow-color);
border-radius: 8px;
transition: opacity 0.5s;
will-change: transform;
}
.floating-text-format-popup button.popup-item {
border: 0;
display: flex;
background: none;
border-radius: 10px;
padding: 12px;
cursor: pointer;
vertical-align: middle;
}
.floating-text-format-popup button.popup-item:disabled {
cursor: not-allowed;
}
.floating-text-format-popup button.popup-item.spaced {
margin-right: 2px;
}
.floating-text-format-popup button.popup-item i.format {
background-size: contain;
display: inline-block;
height: 18px;
width: 18px;
margin-top: 2px;
vertical-align: -0.25em;
display: flex;
opacity: 0.6;
}
.floating-text-format-popup button.popup-item:disabled i.format {
opacity: 0.2;
}
.floating-text-format-popup button.popup-item.active {
background-color: rgba(223, 232, 250, 0.3);
}
.floating-text-format-popup button.popup-item.active i {
opacity: 1;
}
.floating-text-format-popup .popup-item:hover:not([disabled]) {
background-color: var(--sn-stylekit-info-color);
color: var(--sn-stylekit-info-contrast-color);
}
.floating-text-format-popup select.popup-item {
border: 0;
display: flex;
background: none;
border-radius: 10px;
padding: 8px;
vertical-align: middle;
-webkit-appearance: none;
-moz-appearance: none;
width: 70px;
font-size: 14px;
color: #777;
text-overflow: ellipsis;
}
.floating-text-format-popup select.code-language {
text-transform: capitalize;
width: 130px;
}
.floating-text-format-popup .popup-item .text {
display: flex;
line-height: 20px;
width: 200px;
vertical-align: middle;
font-size: 14px;
color: #777;
text-overflow: ellipsis;
width: 70px;
overflow: hidden;
height: 20px;
text-align: left;
}
.floating-text-format-popup .popup-item .icon {
display: flex;
width: 20px;
height: 20px;
user-select: none;
margin-right: 8px;
line-height: 16px;
background-size: contain;
}
.floating-text-format-popup i.chevron-down {
margin-top: 3px;
width: 16px;
height: 16px;
display: flex;
user-select: none;
}
.floating-text-format-popup i.chevron-down.inside {
width: 16px;
height: 16px;
display: flex;
margin-left: -25px;
margin-top: 11px;
margin-right: 10px;
pointer-events: none;
}
.floating-text-format-popup .divider {
width: 1px;
background-color: #eee;
margin: 0 4px;
}
@@ -0,0 +1,351 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import './index.css';
import {$isCodeHighlightNode} from '@lexical/code';
import {$isLinkNode, TOGGLE_LINK_COMMAND} from '@lexical/link';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {mergeRegister} from '@lexical/utils';
import {
$getSelection,
$isRangeSelection,
$isTextNode,
COMMAND_PRIORITY_LOW,
FORMAT_TEXT_COMMAND,
LexicalEditor,
SELECTION_CHANGE_COMMAND,
} from 'lexical';
import {useCallback, useEffect, useRef, useState} from 'react';
import {createPortal} from 'react-dom';
import {getDOMRangeRect} from '../../Utils/getDOMRangeRect';
import {getSelectedNode} from '../../Utils/getSelectedNode';
import {setFloatingElemPosition} from '../../Utils/setFloatingElemPosition';
import {
BoldIcon,
ItalicIcon,
UnderlineIcon,
StrikethroughIcon,
CodeIcon,
LinkIcon,
SuperscriptIcon,
SubscriptIcon,
} from '@standardnotes/icons';
import {IconComponent} from '../../Theme/IconComponent';
const IconSize = 15;
function TextFormatFloatingToolbar({
editor,
anchorElem,
isLink,
isBold,
isItalic,
isUnderline,
isCode,
isStrikethrough,
isSubscript,
isSuperscript,
}: {
editor: LexicalEditor;
anchorElem: HTMLElement;
isBold: boolean;
isCode: boolean;
isItalic: boolean;
isLink: boolean;
isStrikethrough: boolean;
isSubscript: boolean;
isSuperscript: boolean;
isUnderline: boolean;
}): JSX.Element {
const popupCharStylesEditorRef = useRef<HTMLDivElement | null>(null);
const insertLink = useCallback(() => {
if (!isLink) {
editor.dispatchCommand(TOGGLE_LINK_COMMAND, 'https://');
} else {
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
}
}, [editor, isLink]);
const updateTextFormatFloatingToolbar = useCallback(() => {
const selection = $getSelection();
const popupCharStylesEditorElem = popupCharStylesEditorRef.current;
const nativeSelection = window.getSelection();
if (popupCharStylesEditorElem === null) {
return;
}
const rootElement = editor.getRootElement();
if (
selection !== null &&
nativeSelection !== null &&
!nativeSelection.isCollapsed &&
rootElement !== null &&
rootElement.contains(nativeSelection.anchorNode)
) {
const rangeRect = getDOMRangeRect(nativeSelection, rootElement);
setFloatingElemPosition(rangeRect, popupCharStylesEditorElem, anchorElem);
}
}, [editor, anchorElem]);
useEffect(() => {
const scrollerElem = anchorElem.parentElement;
const update = () => {
editor.getEditorState().read(() => {
updateTextFormatFloatingToolbar();
});
};
window.addEventListener('resize', update);
if (scrollerElem) {
scrollerElem.addEventListener('scroll', update);
}
return () => {
window.removeEventListener('resize', update);
if (scrollerElem) {
scrollerElem.removeEventListener('scroll', update);
}
};
}, [editor, updateTextFormatFloatingToolbar, anchorElem]);
useEffect(() => {
editor.getEditorState().read(() => {
updateTextFormatFloatingToolbar();
});
return mergeRegister(
editor.registerUpdateListener(({editorState}) => {
editorState.read(() => {
updateTextFormatFloatingToolbar();
});
}),
editor.registerCommand(
SELECTION_CHANGE_COMMAND,
() => {
updateTextFormatFloatingToolbar();
return false;
},
COMMAND_PRIORITY_LOW,
),
);
}, [editor, updateTextFormatFloatingToolbar]);
return (
<div ref={popupCharStylesEditorRef} className="floating-text-format-popup">
{editor.isEditable() && (
<>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
}}
className={'popup-item spaced ' + (isBold ? 'active' : '')}
aria-label="Format text as bold">
<IconComponent size={IconSize}>
<BoldIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
}}
className={'popup-item spaced ' + (isItalic ? 'active' : '')}
aria-label="Format text as italics">
<IconComponent size={IconSize}>
<ItalicIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
}}
className={'popup-item spaced ' + (isUnderline ? 'active' : '')}
aria-label="Format text to underlined">
<IconComponent size={IconSize + 1}>
<UnderlineIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
}}
className={'popup-item spaced ' + (isStrikethrough ? 'active' : '')}
aria-label="Format text with a strikethrough">
<IconComponent size={IconSize}>
<StrikethroughIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'subscript');
}}
className={'popup-item spaced ' + (isSubscript ? 'active' : '')}
title="Subscript"
aria-label="Format Subscript">
<IconComponent paddingTop={4} size={IconSize - 2}>
<SubscriptIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'superscript');
}}
className={'popup-item spaced ' + (isSuperscript ? 'active' : '')}
title="Superscript"
aria-label="Format Superscript">
<IconComponent paddingTop={1} size={IconSize - 2}>
<SuperscriptIcon />
</IconComponent>
</button>
<button
onClick={() => {
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code');
}}
className={'popup-item spaced ' + (isCode ? 'active' : '')}
aria-label="Insert code block">
<IconComponent size={IconSize}>
<CodeIcon />
</IconComponent>
</button>
<button
onClick={insertLink}
className={'popup-item spaced ' + (isLink ? 'active' : '')}
aria-label="Insert link">
<IconComponent size={IconSize}>
<LinkIcon />
</IconComponent>
</button>
</>
)}
</div>
);
}
function useFloatingTextFormatToolbar(
editor: LexicalEditor,
anchorElem: HTMLElement,
): JSX.Element | null {
const [isText, setIsText] = useState(false);
const [isLink, setIsLink] = useState(false);
const [isBold, setIsBold] = useState(false);
const [isItalic, setIsItalic] = useState(false);
const [isUnderline, setIsUnderline] = useState(false);
const [isStrikethrough, setIsStrikethrough] = useState(false);
const [isSubscript, setIsSubscript] = useState(false);
const [isSuperscript, setIsSuperscript] = useState(false);
const [isCode, setIsCode] = useState(false);
const updatePopup = useCallback(() => {
editor.getEditorState().read(() => {
// Should not to pop up the floating toolbar when using IME input
if (editor.isComposing()) {
return;
}
const selection = $getSelection();
const nativeSelection = window.getSelection();
const rootElement = editor.getRootElement();
if (
nativeSelection !== null &&
(!$isRangeSelection(selection) ||
rootElement === null ||
!rootElement.contains(nativeSelection.anchorNode))
) {
setIsText(false);
return;
}
if (!$isRangeSelection(selection)) {
return;
}
const node = getSelectedNode(selection);
// Update text format
setIsBold(selection.hasFormat('bold'));
setIsItalic(selection.hasFormat('italic'));
setIsUnderline(selection.hasFormat('underline'));
setIsStrikethrough(selection.hasFormat('strikethrough'));
setIsSubscript(selection.hasFormat('subscript'));
setIsSuperscript(selection.hasFormat('superscript'));
setIsCode(selection.hasFormat('code'));
// Update links
const parent = node.getParent();
if ($isLinkNode(parent) || $isLinkNode(node)) {
setIsLink(true);
} else {
setIsLink(false);
}
if (
!$isCodeHighlightNode(selection.anchor.getNode()) &&
selection.getTextContent() !== ''
) {
setIsText($isTextNode(node));
} else {
setIsText(false);
}
});
}, [editor]);
useEffect(() => {
document.addEventListener('selectionchange', updatePopup);
return () => {
document.removeEventListener('selectionchange', updatePopup);
};
}, [updatePopup]);
useEffect(() => {
return mergeRegister(
editor.registerUpdateListener(() => {
updatePopup();
}),
editor.registerRootListener(() => {
if (editor.getRootElement() === null) {
setIsText(false);
}
}),
);
}, [editor, updatePopup]);
if (!isText || isLink) {
return null;
}
return createPortal(
<TextFormatFloatingToolbar
editor={editor}
anchorElem={anchorElem}
isLink={isLink}
isBold={isBold}
isItalic={isItalic}
isStrikethrough={isStrikethrough}
isSubscript={isSubscript}
isSuperscript={isSuperscript}
isUnderline={isUnderline}
isCode={isCode}
/>,
anchorElem,
);
}
export default function FloatingTextFormatToolbarPlugin({
anchorElem = document.body,
}: {
anchorElem?: HTMLElement;
}): JSX.Element | null {
const [editor] = useLexicalComposerContext();
return useFloatingTextFormatToolbar(editor, anchorElem);
}
@@ -35,7 +35,6 @@ export default function HorizontalRulePlugin(): null {
if (focusNode !== null) {
const horizontalRuleNode = $createHorizontalRuleNode();
selection.insertParagraph();
selection.focus
.getNode()
.getTopLevelElementOrThrow()
@@ -0,0 +1,15 @@
export const IconComponent = ({
children,
size = 20,
paddingTop = 0,
}: {
children: React.ReactNode;
size?: number;
paddingTop?: number;
}) => {
return (
<span className="svg-icon" style={{width: size, height: size, paddingTop}}>
{children}
</span>
);
};
@@ -6,8 +6,6 @@
*
*/
@import 'https://fonts.googleapis.com/css?family=Reenie+Beanie';
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -216,34 +214,6 @@ body {
bottom: 20px;
}
#options-button::after {
background-image: url(#{$blocks-editor-icons-path}/gear.svg);
}
#test-recorder-button::after {
background-image: url(#{$blocks-editor-icons-path}/journal-code.svg);
}
#paste-log-button::after {
background-image: url(#{$blocks-editor-icons-path}/clipboard.svg);
}
#test-recorder-button-snapshot {
margin-right: auto;
}
#test-recorder-button-snapshot::after {
background-image: url(#{$blocks-editor-icons-path}/camera.svg);
}
#test-recorder-button-copy::after {
background-image: url(#{$blocks-editor-icons-path}/clipboard.svg);
}
#test-recorder-button-download::after {
background-image: url(#{$blocks-editor-icons-path}/download.svg);
}
.mentions-menu {
width: 250px;
}
@@ -256,68 +226,6 @@ body {
width: 200px;
}
.link-editor .button.active,
.toolbar .button.active {
background-color: rgb(223, 232, 250);
}
.link-editor .link-input {
display: block;
width: calc(100% - 24px);
box-sizing: border-box;
margin: 8px 12px;
padding: 8px 12px;
border-radius: 15px;
background-color: #eee;
font-size: 15px;
color: rgb(5, 5, 5);
border: 0;
outline: 0;
position: relative;
font-family: inherit;
}
.link-editor div.link-edit {
background-image: url(#{$blocks-editor-icons-path}/pencil-fill.svg);
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
width: 35px;
vertical-align: -0.25em;
position: absolute;
right: 0;
top: 0;
bottom: 0;
cursor: pointer;
}
.link-editor .link-input a {
color: rgb(33, 111, 219);
text-decoration: none;
display: block;
white-space: nowrap;
overflow: hidden;
margin-right: 30px;
text-overflow: ellipsis;
}
.link-editor .link-input a:hover {
text-decoration: underline;
}
.link-editor .font-size-wrapper,
.link-editor .font-family-wrapper {
display: flex;
margin: 0 4px;
}
.link-editor select {
padding: 6px;
border: none;
background-color: rgba(0, 0, 0, 0.075);
border-radius: 4px;
}
.mention:focus {
box-shadow: rgb(180 213 255) 0px 0px 0px 2px;
outline: none;
@@ -365,34 +273,6 @@ body {
margin: 2px;
}
#block-controls span.block-type.paragraph {
background-image: url(#{$blocks-editor-icons-path}/text-paragraph.svg);
}
#block-controls span.block-type.h1 {
background-image: url(#{$blocks-editor-icons-path}/type-h1.svg);
}
#block-controls span.block-type.h2 {
background-image: url(#{$blocks-editor-icons-path}/type-h2.svg);
}
#block-controls span.block-type.quote {
background-image: url(#{$blocks-editor-icons-path}/chat-square-quote.svg);
}
#block-controls span.block-type.ul {
background-image: url(#{$blocks-editor-icons-path}/list-ul.svg);
}
#block-controls span.block-type.ol {
background-image: url(#{$blocks-editor-icons-path}/list-ol.svg);
}
#block-controls span.block-type.code {
background-image: url(#{$blocks-editor-icons-path}/code.svg);
}
.characters-limit {
color: #888;
font-size: 12px;
@@ -757,54 +637,6 @@ body {
vertical-align: -0.25em;
}
.actions i.indent {
background-image: url(#{$blocks-editor-icons-path}/indent.svg);
}
.actions i.outdent {
background-image: url(#{$blocks-editor-icons-path}/outdent.svg);
}
.actions i.lock {
background-image: url(#{$blocks-editor-icons-path}/lock-fill.svg);
}
.actions i.image {
background-image: url(#{$blocks-editor-icons-path}/file-image.svg);
}
.actions i.table {
background-image: url(#{$blocks-editor-icons-path}/table.svg);
}
.actions i.unlock {
background-image: url(#{$blocks-editor-icons-path}/lock.svg);
}
.actions i.left-align {
background-image: url(#{$blocks-editor-icons-path}/text-left.svg);
}
.actions i.center-align {
background-image: url(#{$blocks-editor-icons-path}/text-center.svg);
}
.actions i.right-align {
background-image: url(#{$blocks-editor-icons-path}/text-right.svg);
}
.actions i.justify-align {
background-image: url(#{$blocks-editor-icons-path}/justify.svg);
}
.actions i.disconnect {
background-image: url(#{$blocks-editor-icons-path}/plug.svg);
}
.actions i.connect {
background-image: url(#{$blocks-editor-icons-path}/plug-fill.svg);
}
.table-cell-action-button-container {
position: absolute;
top: 0;
@@ -1209,7 +1041,7 @@ body {
}
hr {
padding: 2px 2px;
padding: 2px 0px;
border: none;
margin: 1em 0;
cursor: pointer;
@@ -1219,7 +1051,7 @@ body {
content: '';
display: block;
height: 2px;
background-color: #ccc;
background-color: var(--sn-stylekit-secondary-background-color);
line-height: 2px;
}

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