kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge remote-tracking branch 'origin/main' into multitenancy
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>environments/review-multitenan-9nwikp/deployments/4411
commit
1671c514b1
|
@ -111,9 +111,9 @@ pages:
|
|||
|
||||
docker:
|
||||
stage: deploy
|
||||
image: docker:24.0.7
|
||||
image: docker:24.0.9
|
||||
services:
|
||||
- docker:24.0.7-dind
|
||||
- docker:24.0.9-dind
|
||||
tags:
|
||||
- dind
|
||||
# https://medium.com/devops-with-valentine/how-to-build-a-docker-image-and-push-it-to-the-gitlab-container-registry-from-a-gitlab-ci-pipeline-acac0d1f26df
|
||||
|
|
19
package.json
19
package.json
|
@ -55,12 +55,13 @@
|
|||
"@fontsource/roboto-mono": "^5.0.0",
|
||||
"@fontsource/tajawal": "^5.0.8",
|
||||
"@gamestdio/websocket": "^0.3.2",
|
||||
"@lexical/clipboard": "^0.12.4",
|
||||
"@lexical/hashtag": "^0.12.4",
|
||||
"@lexical/link": "^0.12.4",
|
||||
"@lexical/react": "^0.12.4",
|
||||
"@lexical/selection": "^0.12.4",
|
||||
"@lexical/utils": "^0.12.4",
|
||||
"@lexical/clipboard": "^0.13.1",
|
||||
"@lexical/hashtag": "^0.13.1",
|
||||
"@lexical/link": "^0.13.1",
|
||||
"@lexical/react": "^0.13.1",
|
||||
"@lexical/selection": "^0.13.1",
|
||||
"@lexical/utils": "^0.13.1",
|
||||
"@noble/hashes": "^1.3.3",
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"@reach/combobox": "^0.18.0",
|
||||
"@reach/menu-button": "^0.18.0",
|
||||
|
@ -124,14 +125,16 @@
|
|||
"intersection-observer": "^0.12.2",
|
||||
"intl-messageformat": "10.5.8",
|
||||
"intl-pluralrules": "^2.0.0",
|
||||
"isomorphic-dompurify": "^2.3.0",
|
||||
"leaflet": "^1.8.0",
|
||||
"lexical": "^0.12.4",
|
||||
"lexical": "^0.13.1",
|
||||
"line-awesome": "^1.3.0",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.7.11",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"nostr-machina": "^0.1.0",
|
||||
"nostr-tools": "^1.14.2",
|
||||
"nspec": "^0.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"postcss": "^8.4.29",
|
||||
"process": "^0.11.10",
|
||||
|
@ -207,7 +210,7 @@
|
|||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-tailwindcss": "^3.13.0",
|
||||
"fake-indexeddb": "^5.0.0",
|
||||
"husky": "^8.0.0",
|
||||
"husky": "^9.0.0",
|
||||
"jsdom": "^23.0.0",
|
||||
"lint-staged": ">=10",
|
||||
"react-intl-translations-manager": "^5.0.3",
|
||||
|
|
|
@ -2,7 +2,7 @@ import { nip19 } from 'nostr-tools';
|
|||
|
||||
import { importEntities } from 'soapbox/entity-store/actions';
|
||||
import { Entities } from 'soapbox/entity-store/entities';
|
||||
import { getPublicKey } from 'soapbox/features/nostr/sign';
|
||||
import { signer } from 'soapbox/features/nostr/sign';
|
||||
import { selectAccount } from 'soapbox/selectors';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features';
|
||||
|
@ -134,7 +134,7 @@ const createAccount = (params: Record<string, any>) =>
|
|||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const { instance } = getState();
|
||||
const { nostrSignup } = getFeatures(instance);
|
||||
const pubkey = nostrSignup ? await getPublicKey() : undefined;
|
||||
const pubkey = (signer && nostrSignup) ? await signer.getPublicKey() : undefined;
|
||||
|
||||
dispatch({ type: ACCOUNT_CREATE_REQUEST, params });
|
||||
return api(getState, 'app').post('/api/v1/accounts', params, {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
import { getPublicKey } from 'soapbox/features/nostr/sign';
|
||||
import { signer } from 'soapbox/features/nostr/sign';
|
||||
import { type AppDispatch } from 'soapbox/store';
|
||||
|
||||
import { verifyCredentials } from './auth';
|
||||
|
@ -8,7 +8,11 @@ import { verifyCredentials } from './auth';
|
|||
/** Log in with a Nostr pubkey. */
|
||||
function nostrLogIn() {
|
||||
return async (dispatch: AppDispatch) => {
|
||||
const pubkey = await getPublicKey();
|
||||
if (!signer) {
|
||||
throw new Error('No Nostr signer available');
|
||||
}
|
||||
|
||||
const pubkey = await signer.getPublicKey();
|
||||
const npub = nip19.npubEncode(pubkey);
|
||||
|
||||
return dispatch(verifyCredentials(npub));
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { NiceRelay } from 'nostr-machina';
|
||||
import { type Event } from 'nostr-tools';
|
||||
import { type NostrEvent } from 'nspec';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
import { nip04, signEvent } from 'soapbox/features/nostr/sign';
|
||||
import { signer } from 'soapbox/features/nostr/sign';
|
||||
import { useInstance } from 'soapbox/hooks';
|
||||
import { connectRequestSchema, nwcRequestSchema } from 'soapbox/schemas/nostr';
|
||||
import { jsonSchema } from 'soapbox/schemas/utils';
|
||||
|
@ -14,14 +14,14 @@ function useSignerStream() {
|
|||
const pubkey = instance.nostr?.pubkey;
|
||||
|
||||
const relay = useMemo(() => {
|
||||
if (relayUrl) {
|
||||
if (relayUrl && signer) {
|
||||
return new NiceRelay(relayUrl);
|
||||
}
|
||||
}, [relayUrl]);
|
||||
}, [relayUrl, !!signer]);
|
||||
|
||||
async function handleConnectEvent(event: Event) {
|
||||
if (!relay || !pubkey) return;
|
||||
const decrypted = await nip04.decrypt(pubkey, event.content);
|
||||
async function handleConnectEvent(event: NostrEvent) {
|
||||
if (!relay || !pubkey || !signer) return;
|
||||
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
|
||||
|
||||
const reqMsg = jsonSchema.pipe(connectRequestSchema).safeParse(decrypted);
|
||||
if (!reqMsg.success) {
|
||||
|
@ -32,12 +32,12 @@ function useSignerStream() {
|
|||
|
||||
const respMsg = {
|
||||
id: reqMsg.data.id,
|
||||
result: await signEvent(reqMsg.data.params[0], reqMsg.data.params[1]),
|
||||
result: await signer.signEvent(reqMsg.data.params[0]),
|
||||
};
|
||||
|
||||
const respEvent = await signEvent({
|
||||
const respEvent = await signer.signEvent({
|
||||
kind: 24133,
|
||||
content: await nip04.encrypt(pubkey, JSON.stringify(respMsg)),
|
||||
content: await signer.nip04!.encrypt(pubkey, JSON.stringify(respMsg)),
|
||||
tags: [['p', pubkey]],
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
});
|
||||
|
@ -45,10 +45,10 @@ function useSignerStream() {
|
|||
relay.send(['EVENT', respEvent]);
|
||||
}
|
||||
|
||||
async function handleWalletEvent(event: Event) {
|
||||
if (!relay || !pubkey) return;
|
||||
async function handleWalletEvent(event: NostrEvent) {
|
||||
if (!relay || !pubkey || !signer) return;
|
||||
|
||||
const decrypted = await nip04.decrypt(pubkey, event.content);
|
||||
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
|
||||
|
||||
const reqMsg = jsonSchema.pipe(nwcRequestSchema).safeParse(decrypted);
|
||||
if (!reqMsg.success) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom';
|
|||
import { closeDropdownMenu as closeDropdownMenuRedux, openDropdownMenu } from 'soapbox/actions/dropdown-menu';
|
||||
import { closeModal, openModal } from 'soapbox/actions/modals';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import { isUserTouching } from 'soapbox/is-mobile';
|
||||
import { userTouching } from 'soapbox/is-mobile';
|
||||
|
||||
import { IconButton, Portal } from '../ui';
|
||||
|
||||
|
@ -53,8 +53,6 @@ const DropdownMenu = (props: IDropdownMenu) => {
|
|||
|
||||
const arrowRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const isOnMobile = isUserTouching();
|
||||
|
||||
const { x, y, strategy, refs, middlewareData, placement } = useFloating<HTMLButtonElement>({
|
||||
placement: initialPlacement,
|
||||
middleware: [
|
||||
|
@ -92,7 +90,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
|
|||
* On mobile screens, let's replace the Popper dropdown with a Modal.
|
||||
*/
|
||||
const handleOpen = () => {
|
||||
if (isOnMobile) {
|
||||
if (userTouching.matches) {
|
||||
dispatch(
|
||||
openModal('ACTIONS', {
|
||||
status: filteredProps.status,
|
||||
|
@ -113,7 +111,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
|
|||
const handleClose = () => {
|
||||
(refs.reference.current as HTMLButtonElement)?.focus();
|
||||
|
||||
if (isOnMobile) {
|
||||
if (userTouching.matches) {
|
||||
dispatch(closeModal('ACTIONS'));
|
||||
} else {
|
||||
closeDropdownMenu();
|
||||
|
|
|
@ -4,7 +4,7 @@ import { simpleEmojiReact } from 'soapbox/actions/emoji-reacts';
|
|||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { EmojiSelector, Portal } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig } from 'soapbox/hooks';
|
||||
import { isUserTouching } from 'soapbox/is-mobile';
|
||||
import { userTouching } from 'soapbox/is-mobile';
|
||||
import { getReactForStatus } from 'soapbox/utils/emoji-reacts';
|
||||
|
||||
interface IStatusReactionWrapper {
|
||||
|
@ -39,7 +39,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
|
|||
clearTimeout(timeout.current);
|
||||
}
|
||||
|
||||
if (!isUserTouching()) {
|
||||
if (!userTouching.matches) {
|
||||
setVisible(true);
|
||||
}
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
|
|||
|
||||
// Unless the user is touching, delay closing the emoji selector briefly
|
||||
// so the user can move the mouse diagonally to make a selection.
|
||||
if (isUserTouching()) {
|
||||
if (userTouching.matches) {
|
||||
setVisible(false);
|
||||
} else {
|
||||
timeout.current = setTimeout(() => {
|
||||
|
@ -73,7 +73,7 @@ const StatusReactionWrapper: React.FC<IStatusReactionWrapper> = ({ statusId, chi
|
|||
const handleClick: React.EventHandler<React.MouseEvent> = e => {
|
||||
const meEmojiReact = getReactForStatus(status, soapboxConfig.allowedEmoji)?.name || '👍';
|
||||
|
||||
if (isUserTouching()) {
|
||||
if (userTouching.matches) {
|
||||
if (ownAccount) {
|
||||
if (visible) {
|
||||
handleReact(meEmojiReact);
|
||||
|
|
|
@ -258,8 +258,8 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
{domains && (
|
||||
{domains && (
|
||||
<FormGroup>
|
||||
<Select
|
||||
onChange={onDomainChange}
|
||||
value={params.get('domain')}
|
||||
|
@ -268,8 +268,8 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
|
|||
<option key={id} value={id}>{domain}</option>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
</FormGroup>
|
||||
</FormGroup>
|
||||
)}
|
||||
|
||||
|
||||
{!features.nostrSignup && (
|
||||
|
|
|
@ -11,7 +11,7 @@ import { closeModal, openModal } from 'soapbox/actions/modals';
|
|||
import Icon from 'soapbox/components/icon';
|
||||
import { IconButton } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useCompose } from 'soapbox/hooks';
|
||||
import { isUserTouching } from 'soapbox/is-mobile';
|
||||
import { userTouching } from 'soapbox/is-mobile';
|
||||
|
||||
import Motion from '../../ui/util/optional-motion';
|
||||
|
||||
|
@ -173,7 +173,7 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
|
|||
const onModalClose = () => dispatch(closeModal('ACTIONS'));
|
||||
|
||||
const handleToggle: React.MouseEventHandler<HTMLButtonElement> = (e) => {
|
||||
if (isUserTouching()) {
|
||||
if (userTouching.matches) {
|
||||
if (open) {
|
||||
onModalClose();
|
||||
} else {
|
||||
|
|
|
@ -324,7 +324,7 @@ const AutosuggestPlugin = ({
|
|||
dispatch(chooseEmoji(suggestion));
|
||||
replaceMatch($createEmojiNode(suggestion));
|
||||
} else if (suggestion[0] === '#') {
|
||||
node.setTextContent(`${suggestion} `);
|
||||
(node as TextNode).setTextContent(`${suggestion} `);
|
||||
node.select();
|
||||
} else {
|
||||
const account = selectAccount(getState(), suggestion)!;
|
||||
|
|
|
@ -7,7 +7,16 @@
|
|||
import { LinkPlugin as LexicalLinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
||||
import * as React from 'react';
|
||||
|
||||
import { validateUrl } from '../utils/url';
|
||||
// Source: https://stackoverflow.com/a/8234912/2013580
|
||||
const urlRegExp = new RegExp(
|
||||
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,
|
||||
);
|
||||
|
||||
export const validateUrl = (url: string): boolean => {
|
||||
// TODO Fix UI for link insertion; it should never default to an invalid URL such as https://.
|
||||
// Maybe show a dialog where they user can type the URL before inserting it.
|
||||
return url === 'https://' || urlRegExp.test(url);
|
||||
};
|
||||
|
||||
const LinkPlugin = (): JSX.Element => {
|
||||
return <LexicalLinkPlugin validateUrl={validateUrl} />;
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
/* eslint-disable eqeqeq */
|
||||
|
||||
export const getDOMRangeRect = (
|
||||
nativeSelection: Selection,
|
||||
rootElement: HTMLElement,
|
||||
): DOMRect => {
|
||||
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();
|
||||
}
|
||||
|
||||
return rect;
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
import { $isAtNodeEnd } from '@lexical/selection';
|
||||
import { ElementNode, RangeSelection, TextNode } from 'lexical';
|
||||
|
||||
export const getSelectedNode = (
|
||||
selection: RangeSelection,
|
||||
): TextNode | ElementNode => {
|
||||
const anchor = selection.anchor;
|
||||
const focus = selection.focus;
|
||||
const anchorNode = selection.anchor.getNode();
|
||||
const focusNode = selection.focus.getNode();
|
||||
if (anchorNode === focusNode) {
|
||||
return anchorNode;
|
||||
}
|
||||
const isBackward = selection.isBackward();
|
||||
if (isBackward) {
|
||||
return $isAtNodeEnd(focus) ? anchorNode : focusNode;
|
||||
} else {
|
||||
return $isAtNodeEnd(anchor) ? focusNode : anchorNode;
|
||||
}
|
||||
};
|
|
@ -1,4 +0,0 @@
|
|||
const isHTMLElement = (x: unknown): x is HTMLElement => x instanceof HTMLElement;
|
||||
|
||||
export default isHTMLElement;
|
||||
export { isHTMLElement };
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
class Point {
|
||||
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
public equals({ x, y }: Point): boolean {
|
||||
return this.x === x && this.y === y;
|
||||
}
|
||||
|
||||
public calcDeltaXTo({ x }: Point): number {
|
||||
return this.x - x;
|
||||
}
|
||||
|
||||
public calcDeltaYTo({ y }: Point): number {
|
||||
return this.y - y;
|
||||
}
|
||||
|
||||
public calcHorizontalDistanceTo(point: Point): number {
|
||||
return Math.abs(this.calcDeltaXTo(point));
|
||||
}
|
||||
|
||||
public calcVerticalDistance(point: Point): number {
|
||||
return Math.abs(this.calcDeltaYTo(point));
|
||||
}
|
||||
|
||||
public calcDistanceTo(point: Point): number {
|
||||
return Math.sqrt(
|
||||
Math.pow(this.calcDeltaXTo(point), 2) +
|
||||
Math.pow(this.calcDeltaYTo(point), 2),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const isPoint = (x: unknown): x is Point => x instanceof Point;
|
||||
|
||||
export default Point;
|
||||
export { Point, isPoint };
|
|
@ -1,163 +0,0 @@
|
|||
/* eslint-disable no-dupe-class-members */
|
||||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
import { isPoint, Point } from './point';
|
||||
|
||||
type ContainsPointReturn = {
|
||||
result: boolean;
|
||||
reason: {
|
||||
isOnTopSide: boolean;
|
||||
isOnBottomSide: boolean;
|
||||
isOnLeftSide: boolean;
|
||||
isOnRightSide: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
class Rect {
|
||||
|
||||
private readonly _left: number;
|
||||
private readonly _top: number;
|
||||
private readonly _right: number;
|
||||
private readonly _bottom: number;
|
||||
|
||||
constructor(left: number, top: number, right: number, bottom: number) {
|
||||
const [physicTop, physicBottom] =
|
||||
top <= bottom ? [top, bottom] : [bottom, top];
|
||||
|
||||
const [physicLeft, physicRight] =
|
||||
left <= right ? [left, right] : [right, left];
|
||||
|
||||
this._top = physicTop;
|
||||
this._right = physicRight;
|
||||
this._left = physicLeft;
|
||||
this._bottom = physicBottom;
|
||||
}
|
||||
|
||||
get top(): number {
|
||||
return this._top;
|
||||
}
|
||||
|
||||
get right(): number {
|
||||
return this._right;
|
||||
}
|
||||
|
||||
get bottom(): number {
|
||||
return this._bottom;
|
||||
}
|
||||
|
||||
get left(): number {
|
||||
return this._left;
|
||||
}
|
||||
|
||||
get width(): number {
|
||||
return Math.abs(this._left - this._right);
|
||||
}
|
||||
|
||||
get height(): number {
|
||||
return Math.abs(this._bottom - this._top);
|
||||
}
|
||||
|
||||
public equals({ top, left, bottom, right }: Rect): boolean {
|
||||
return (
|
||||
top === this._top &&
|
||||
bottom === this._bottom &&
|
||||
left === this._left &&
|
||||
right === this._right
|
||||
);
|
||||
}
|
||||
|
||||
public contains({ x, y }: Point): ContainsPointReturn;
|
||||
public contains({ top, left, bottom, right }: Rect): boolean;
|
||||
public contains(target: Point | Rect): boolean | ContainsPointReturn {
|
||||
if (isPoint(target)) {
|
||||
const { x, y } = target;
|
||||
|
||||
const isOnTopSide = y < this._top;
|
||||
const isOnBottomSide = y > this._bottom;
|
||||
const isOnLeftSide = x < this._left;
|
||||
const isOnRightSide = x > this._right;
|
||||
|
||||
const result =
|
||||
!isOnTopSide && !isOnBottomSide && !isOnLeftSide && !isOnRightSide;
|
||||
|
||||
return {
|
||||
reason: {
|
||||
isOnBottomSide,
|
||||
isOnLeftSide,
|
||||
isOnRightSide,
|
||||
isOnTopSide,
|
||||
},
|
||||
result,
|
||||
};
|
||||
} else {
|
||||
const { top, left, bottom, right } = target;
|
||||
|
||||
return (
|
||||
top >= this._top &&
|
||||
top <= this._bottom &&
|
||||
bottom >= this._top &&
|
||||
bottom <= this._bottom &&
|
||||
left >= this._left &&
|
||||
left <= this._right &&
|
||||
right >= this._left &&
|
||||
right <= this._right
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public intersectsWith(rect: Rect): boolean {
|
||||
const { left: x1, top: y1, width: w1, height: h1 } = rect;
|
||||
const { left: x2, top: y2, width: w2, height: h2 } = this;
|
||||
const maxX = x1 + w1 >= x2 + w2 ? x1 + w1 : x2 + w2;
|
||||
const maxY = y1 + h1 >= y2 + h2 ? y1 + h1 : y2 + h2;
|
||||
const minX = x1 <= x2 ? x1 : x2;
|
||||
const minY = y1 <= y2 ? y1 : y2;
|
||||
return maxX - minX <= w1 + w2 && maxY - minY <= h1 + h2;
|
||||
}
|
||||
|
||||
public generateNewRect({
|
||||
left = this.left,
|
||||
top = this.top,
|
||||
right = this.right,
|
||||
bottom = this.bottom,
|
||||
}): Rect {
|
||||
return new Rect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
static fromLTRB(
|
||||
left: number,
|
||||
top: number,
|
||||
right: number,
|
||||
bottom: number,
|
||||
): Rect {
|
||||
return new Rect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
static fromLWTH(
|
||||
left: number,
|
||||
width: number,
|
||||
top: number,
|
||||
height: number,
|
||||
): Rect {
|
||||
return new Rect(left, top, left + width, top + height);
|
||||
}
|
||||
|
||||
static fromPoints(startPoint: Point, endPoint: Point): Rect {
|
||||
const { y: top, x: left } = startPoint;
|
||||
const { y: bottom, x: right } = endPoint;
|
||||
return Rect.fromLTRB(left, top, right, bottom);
|
||||
}
|
||||
|
||||
static fromDOM(dom: HTMLElement): Rect {
|
||||
const { top, width, left, height } = dom.getBoundingClientRect();
|
||||
return Rect.fromLWTH(left, width, top, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Rect;
|
||||
export { Rect };
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
const VERTICAL_GAP = 10;
|
||||
const HORIZONTAL_OFFSET = 5;
|
||||
|
||||
export const setFloatingElemPosition = (
|
||||
targetRect: ClientRect | null,
|
||||
floatingElem: HTMLElement,
|
||||
anchorElem: HTMLElement,
|
||||
verticalGap: number = VERTICAL_GAP,
|
||||
horizontalOffset: number = HORIZONTAL_OFFSET,
|
||||
): void => {
|
||||
const scrollerElem = anchorElem.parentElement;
|
||||
|
||||
if (targetRect === null || !scrollerElem) {
|
||||
floatingElem.style.opacity = '0';
|
||||
floatingElem.style.transform = 'translate(-10000px, -10000px)';
|
||||
return;
|
||||
}
|
||||
|
||||
const floatingElemRect = floatingElem.getBoundingClientRect();
|
||||
const anchorElementRect = anchorElem.getBoundingClientRect();
|
||||
const editorScrollerRect = scrollerElem.getBoundingClientRect();
|
||||
|
||||
let top = targetRect.top - floatingElemRect.height - verticalGap;
|
||||
let left = targetRect.left - horizontalOffset;
|
||||
|
||||
if (top < editorScrollerRect.top) {
|
||||
top += floatingElemRect.height + targetRect.height + verticalGap * 2;
|
||||
}
|
||||
|
||||
if (left + floatingElemRect.width > editorScrollerRect.right) {
|
||||
left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;
|
||||
}
|
||||
|
||||
top -= anchorElementRect.top;
|
||||
left -= anchorElementRect.left;
|
||||
|
||||
floatingElem.style.opacity = '1';
|
||||
floatingElem.style.transform = `translate(${left}px, ${top}px)`;
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* This source code is derived from code from Meta Platforms, Inc.
|
||||
* and affiliates, licensed under the MIT license located in the
|
||||
* LICENSE file in the /src/features/compose/editor directory.
|
||||
*/
|
||||
|
||||
export const sanitizeUrl = (url: string): string => {
|
||||
/** A pattern that matches safe URLs. */
|
||||
const SAFE_URL_PATTERN =
|
||||
/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
|
||||
|
||||
/** A pattern that matches safe data URLs. */
|
||||
const DATA_URL_PATTERN =
|
||||
/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;
|
||||
|
||||
url = String(url).trim();
|
||||
|
||||
if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN)) return url;
|
||||
|
||||
return 'https://';
|
||||
};
|
||||
|
||||
// Source: https://stackoverflow.com/a/8234912/2013580
|
||||
const urlRegExp = new RegExp(
|
||||
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,
|
||||
);
|
||||
|
||||
export const validateUrl = (url: string): boolean => {
|
||||
// TODO Fix UI for link insertion; it should never default to an invalid URL such as https://.
|
||||
// Maybe show a dialog where they user can type the URL before inserting it.
|
||||
return url === 'https://' || urlRegExp.test(url);
|
||||
};
|
|
@ -1,3 +1,4 @@
|
|||
import DOMPurify from 'isomorphic-dompurify';
|
||||
import React from 'react';
|
||||
|
||||
import Markup from 'soapbox/components/markup';
|
||||
|
@ -9,7 +10,7 @@ import { LogoText } from './logo-text';
|
|||
|
||||
const SiteBanner: React.FC = () => {
|
||||
const instance = useInstance();
|
||||
const description = instance.description;
|
||||
const description = DOMPurify.sanitize(instance.description);
|
||||
|
||||
return (
|
||||
<Stack space={3}>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { hexToBytes } from '@noble/hashes/utils';
|
||||
import { type NostrSigner, type NostrEvent, NSecSigner } from 'nspec';
|
||||
|
||||
/** Use key from `localStorage` if available, falling back to NIP-07. */
|
||||
export class SoapboxSigner implements NostrSigner {
|
||||
|
||||
#signer: NostrSigner;
|
||||
|
||||
constructor() {
|
||||
const privateKey = localStorage.getItem('soapbox:nostr:privateKey');
|
||||
const signer = privateKey ? new NSecSigner(hexToBytes(privateKey)) : window.nostr;
|
||||
|
||||
if (!signer) {
|
||||
throw new Error('No Nostr signer available');
|
||||
}
|
||||
|
||||
this.#signer = signer;
|
||||
}
|
||||
|
||||
async getPublicKey(): Promise<string> {
|
||||
return this.#signer.getPublicKey();
|
||||
}
|
||||
|
||||
async signEvent(event: Omit<NostrEvent, 'id' | 'pubkey' | 'sig'>): Promise<NostrEvent> {
|
||||
return this.#signer.signEvent(event);
|
||||
}
|
||||
|
||||
nip04 = {
|
||||
encrypt: (pubkey: string, plaintext: string): Promise<string> => {
|
||||
if (!this.#signer.nip04) {
|
||||
throw new Error('NIP-04 not supported by signer');
|
||||
}
|
||||
return this.#signer.nip04.encrypt(pubkey, plaintext);
|
||||
},
|
||||
|
||||
decrypt: (pubkey: string, ciphertext: string): Promise<string> => {
|
||||
if (!this.#signer.nip04) {
|
||||
throw new Error('NIP-04 not supported by signer');
|
||||
}
|
||||
return this.#signer.nip04.decrypt(pubkey, ciphertext);
|
||||
},
|
||||
};
|
||||
|
||||
}
|
|
@ -1,63 +1,13 @@
|
|||
import {
|
||||
type Event,
|
||||
type EventTemplate,
|
||||
generatePrivateKey,
|
||||
getPublicKey as _getPublicKey,
|
||||
finishEvent,
|
||||
nip04 as _nip04,
|
||||
} from 'nostr-tools';
|
||||
import { type NostrSigner } from 'nspec';
|
||||
|
||||
import { powWorker } from 'soapbox/workers';
|
||||
import { SoapboxSigner } from './SoapboxSigner';
|
||||
|
||||
/** localStorage key for the Nostr private key (if not using NIP-07). */
|
||||
const LOCAL_KEY = 'soapbox:nostr:privateKey';
|
||||
let signer: NostrSigner | undefined;
|
||||
|
||||
/** Get the private key from the browser, or generate one. */
|
||||
const getPrivateKey = (): string => {
|
||||
const local = localStorage.getItem(LOCAL_KEY);
|
||||
|
||||
if (!local) {
|
||||
const key = generatePrivateKey();
|
||||
localStorage.setItem(LOCAL_KEY, key);
|
||||
return key;
|
||||
}
|
||||
|
||||
return local;
|
||||
};
|
||||
|
||||
/** Get the user's public key from NIP-07, or generate one. */
|
||||
async function getPublicKey(): Promise<string> {
|
||||
return window.nostr ? window.nostr.getPublicKey() : _getPublicKey(getPrivateKey());
|
||||
try {
|
||||
signer = new SoapboxSigner();
|
||||
} catch (_) {
|
||||
// No signer available
|
||||
}
|
||||
|
||||
interface SignEventOpts {
|
||||
pow?: number;
|
||||
}
|
||||
|
||||
/** Sign an event with NIP-07, or the locally generated key. */
|
||||
async function signEvent<K extends number>(template: EventTemplate<K>, opts: SignEventOpts = {}): Promise<Event<K>> {
|
||||
if (opts.pow) {
|
||||
const event = await powWorker.mine({ ...template, pubkey: await getPublicKey() }, opts.pow) as Omit<Event<K>, 'sig'>;
|
||||
return window.nostr ? window.nostr.signEvent(event) as Promise<Event<K>> : finishEvent(event, getPrivateKey()) ;
|
||||
} else {
|
||||
return window.nostr ? window.nostr.signEvent(template) as Promise<Event<K>> : finishEvent(template, getPrivateKey()) ;
|
||||
}
|
||||
}
|
||||
|
||||
/** Crypto function with NIP-07, or the local key. */
|
||||
const nip04 = {
|
||||
/** Encrypt with NIP-07, or the local key. */
|
||||
encrypt: async (pubkey: string, content: string) => {
|
||||
return window.nostr?.nip04
|
||||
? window.nostr.nip04.encrypt(pubkey, content)
|
||||
: _nip04.encrypt(getPrivateKey(), pubkey, content);
|
||||
},
|
||||
/** Decrypt with NIP-07, or the local key. */
|
||||
decrypt: async (pubkey: string, content: string) => {
|
||||
return window.nostr?.nip04
|
||||
? window.nostr.nip04.decrypt(pubkey, content)
|
||||
: _nip04.decrypt(getPrivateKey(), pubkey, content);
|
||||
},
|
||||
};
|
||||
|
||||
export { getPublicKey, signEvent, nip04 };
|
||||
export { signer };
|
|
@ -15,7 +15,7 @@ import PlaceholderStatus from 'soapbox/features/placeholder/components/placehold
|
|||
import Thread from 'soapbox/features/status/components/thread';
|
||||
import Video from 'soapbox/features/video';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { isUserTouching } from 'soapbox/is-mobile';
|
||||
import { userTouching } from 'soapbox/is-mobile';
|
||||
import { makeGetStatus } from 'soapbox/selectors';
|
||||
|
||||
import ImageLoader from '../image-loader';
|
||||
|
@ -104,7 +104,7 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
|
|||
const getIndex = () => index !== null ? index : props.index;
|
||||
|
||||
const toggleNavigation = () => {
|
||||
setNavigationHidden(value => !value && isUserTouching());
|
||||
setNavigationHidden(value => !value && userTouching.matches);
|
||||
};
|
||||
|
||||
const handleStatusClick: React.MouseEventHandler = e => {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
|
||||
/** Breakpoint at which the application is considered "mobile". */
|
||||
const LAYOUT_BREAKPOINT = 630;
|
||||
|
||||
|
@ -11,20 +9,7 @@ export function isMobile(width: number) {
|
|||
/** Whether the device is iOS (best guess). */
|
||||
const iOS: boolean = /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream;
|
||||
|
||||
let userTouching = false;
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } as EventListenerOptions : false;
|
||||
|
||||
function touchListener(): void {
|
||||
userTouching = true;
|
||||
window.removeEventListener('touchstart', touchListener, listenerOptions);
|
||||
}
|
||||
|
||||
window.addEventListener('touchstart', touchListener, listenerOptions);
|
||||
|
||||
/** Whether the user has touched the screen since the page loaded. */
|
||||
export function isUserTouching(): boolean {
|
||||
return userTouching;
|
||||
}
|
||||
export const userTouching = window.matchMedia('(pointer: coarse)');
|
||||
|
||||
/** Whether the device is iOS (best guess). */
|
||||
export function isIOS(): boolean {
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
Record as ImmutableRecord,
|
||||
fromJS,
|
||||
} from 'immutable';
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
|
||||
import emojify from 'soapbox/features/emoji';
|
||||
import { normalizeAttachment } from 'soapbox/normalizers/attachment';
|
||||
|
@ -60,8 +61,8 @@ const normalizeStatusPoll = (statusEdit: ImmutableMap<string, any>) => {
|
|||
|
||||
const normalizeContent = (statusEdit: ImmutableMap<string, any>) => {
|
||||
const emojiMap = makeEmojiMap(statusEdit.get('emojis'));
|
||||
const contentHtml = stripCompatibilityFeatures(emojify(statusEdit.get('content'), emojiMap));
|
||||
const spoilerHtml = emojify(escapeTextContentForBrowser(statusEdit.get('spoiler_text')), emojiMap);
|
||||
const contentHtml = DOMPurify.sanitize(stripCompatibilityFeatures(emojify(statusEdit.get('content'), emojiMap)), { ADD_ATTR: ['target'] });
|
||||
const spoilerHtml = DOMPurify.sanitize(emojify(escapeTextContentForBrowser(statusEdit.get('spoiler_text')), emojiMap), { ADD_ATTR: ['target'] });
|
||||
|
||||
return statusEdit
|
||||
.set('contentHtml', contentHtml)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import escapeTextContentForBrowser from 'escape-html';
|
||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
|
||||
import emojify from 'soapbox/features/emoji';
|
||||
import { normalizeStatus } from 'soapbox/normalizers';
|
||||
|
@ -119,8 +120,8 @@ export const calculateStatus = (
|
|||
|
||||
return status.merge({
|
||||
search_index: domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || '',
|
||||
contentHtml: stripCompatibilityFeatures(emojify(status.content, emojiMap)),
|
||||
spoilerHtml: emojify(escapeTextContentForBrowser(spoilerText), emojiMap),
|
||||
contentHtml: DOMPurify.sanitize(stripCompatibilityFeatures(emojify(status.content, emojiMap)), { USE_PROFILES: { html: true } }),
|
||||
spoilerHtml: DOMPurify.sanitize(emojify(escapeTextContentForBrowser(spoilerText), emojiMap), { USE_PROFILES: { html: true } }),
|
||||
hidden: expandSpoilers ? false : spoilerText.length > 0 || status.sensitive,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import escapeTextContentForBrowser from 'escape-html';
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
import z from 'zod';
|
||||
|
||||
import emojify from 'soapbox/features/emoji';
|
||||
|
@ -115,7 +116,7 @@ const transformAccount = <T extends TransformableAccount>({ pleroma, other_setti
|
|||
|
||||
const newFields = fields.map((field) => ({
|
||||
...field,
|
||||
name_emojified: emojify(escapeTextContentForBrowser(field.name), customEmojiMap),
|
||||
name_emojified: DOMPurify.sanitize(emojify(escapeTextContentForBrowser(field.name), customEmojiMap), { USE_PROFILES: { html: true } }),
|
||||
value_emojified: emojify(field.value, customEmojiMap),
|
||||
value_plain: unescapeHTML(field.value),
|
||||
}));
|
||||
|
@ -133,7 +134,7 @@ const transformAccount = <T extends TransformableAccount>({ pleroma, other_setti
|
|||
avatar_static: account.avatar_static || account.avatar,
|
||||
discoverable: account.discoverable || account.source?.pleroma?.discoverable || false,
|
||||
display_name: displayName,
|
||||
display_name_html: emojify(escapeTextContentForBrowser(displayName), customEmojiMap),
|
||||
display_name_html: DOMPurify.sanitize(emojify(escapeTextContentForBrowser(displayName), customEmojiMap), { USE_PROFILES: { html: true } }),
|
||||
domain,
|
||||
fields: newFields,
|
||||
fqn: account.fqn || (account.acct.includes('@') ? account.acct : `${account.acct}@${domain}`),
|
||||
|
@ -141,7 +142,7 @@ const transformAccount = <T extends TransformableAccount>({ pleroma, other_setti
|
|||
moderator: pleroma?.is_moderator || false,
|
||||
local: pleroma?.is_local !== undefined ? pleroma.is_local : account.acct.split('@')[1] === undefined,
|
||||
location: account.location || pleroma?.location || other_settings?.location || '',
|
||||
note_emojified: emojify(account.note, customEmojiMap),
|
||||
note_emojified: DOMPurify.sanitize(emojify(account.note, customEmojiMap), { USE_PROFILES: { html: true } }),
|
||||
pleroma: (() => {
|
||||
if (!pleroma) return undefined;
|
||||
const { relationship, ...rest } = pleroma;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import escapeTextContentForBrowser from 'escape-html';
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
import { z } from 'zod';
|
||||
|
||||
import emojify from 'soapbox/features/emoji';
|
||||
|
@ -30,7 +31,7 @@ const pollSchema = z.object({
|
|||
|
||||
const emojifiedOptions = poll.options.map((option) => ({
|
||||
...option,
|
||||
title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap),
|
||||
title_emojified: DOMPurify.sanitize(emojify(escapeTextContentForBrowser(option.title), emojiMap), { ALLOWED_TAGS: [] }),
|
||||
}));
|
||||
|
||||
// If the user has votes, they have certainly voted.
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import type { Event, EventTemplate } from 'nostr-tools';
|
||||
|
||||
interface Nostr {
|
||||
getPublicKey(): Promise<string>;
|
||||
signEvent(event: EventTemplate): Promise<Event>;
|
||||
nip04?: {
|
||||
encrypt: (pubkey: string, plaintext: string) => Promise<string>;
|
||||
decrypt: (pubkey: string, ciphertext: string) => Promise<string>;
|
||||
};
|
||||
}
|
||||
|
||||
export default Nostr;
|
|
@ -1,7 +1,7 @@
|
|||
import type Nostr from './nostr';
|
||||
import type { NostrSigner } from 'nspec';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
nostr?: Nostr;
|
||||
nostr?: NostrSigner;
|
||||
}
|
||||
}
|
407
yarn.lock
407
yarn.lock
|
@ -1672,167 +1672,167 @@
|
|||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@lexical/clipboard@0.12.4", "@lexical/clipboard@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/clipboard/-/clipboard-0.12.4.tgz#b9c3a38ab98a67c678ee80238036a166d3161491"
|
||||
integrity sha512-kFR+UdhtLCMTQgZCyDmYzp2yjPFMNpUZ4TaRjuRBpCRFYwKMlgie4p1J4VJm6sT23kkAFZtVjOfp+gDEYnPHRQ==
|
||||
"@lexical/clipboard@0.13.1", "@lexical/clipboard@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/clipboard/-/clipboard-0.13.1.tgz#ca132306129974ea2c9e51d6a8637f8fcffcdb3d"
|
||||
integrity sha512-gMSbVeqb7S+XAi/EMMlwl+FCurLPugN2jAXcp5k5ZaUd7be8B+iupbYdoKkjt4qBhxmvmfe9k46GoC0QOPl/nw==
|
||||
dependencies:
|
||||
"@lexical/html" "0.12.4"
|
||||
"@lexical/list" "0.12.4"
|
||||
"@lexical/selection" "0.12.4"
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/html" "0.13.1"
|
||||
"@lexical/list" "0.13.1"
|
||||
"@lexical/selection" "0.13.1"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/code@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/code/-/code-0.12.4.tgz#aa91cf1b070e012b359e9ba023ef880ed8c7fec0"
|
||||
integrity sha512-pX7rJCjbjCl6VdOPl2hl/UkjP3iPPyCQgH2VQ+WlXapDd+0uZ54nPL1MKCCaFUZocHPmOmSRKKGUp6K2CNiqzg==
|
||||
"@lexical/code@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/code/-/code-0.13.1.tgz#e13688390582a4b63a639daff1f16bcb82aa854d"
|
||||
integrity sha512-QK77r3QgEtJy96ahYXNgpve8EY64BQgBSnPDOuqVrLdl92nPzjqzlsko2OZldlrt7gjXcfl9nqfhZ/CAhStfOg==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
prismjs "^1.27.0"
|
||||
|
||||
"@lexical/dragon@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/dragon/-/dragon-0.12.4.tgz#dc9961abf31a7e5a40db1b81e07a290ccdca93a5"
|
||||
integrity sha512-7DaXdQ/5GJ8HRpPYr2+SjaUi912tG9L6ukg9IglG1t51lWGxqLx2chW17tp50XDTtY05w9VnoMaxtgsuCN5Pmg==
|
||||
"@lexical/dragon@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/dragon/-/dragon-0.13.1.tgz#32ba02bff4d8f02a6317d874671ee0b0a2dcdc53"
|
||||
integrity sha512-aNlqfif4//jW7gOxbBgdrbDovU6m3EwQrUw+Y/vqRkY+sWmloyAUeNwCPH1QP3Q5cvfolzOeN5igfBljsFr+1g==
|
||||
|
||||
"@lexical/hashtag@0.12.4", "@lexical/hashtag@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/hashtag/-/hashtag-0.12.4.tgz#95e2dced69dd0378c567c855e834492f367d7a86"
|
||||
integrity sha512-iCxQRBZmgwAV6kypmxtWg7HVhBC7PKclmqLNaLDLoKBm+keEXpKnGB5iEtgK/tCMiwkzrg+wGcrw5qi+YjvM9Q==
|
||||
"@lexical/hashtag@0.13.1", "@lexical/hashtag@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/hashtag/-/hashtag-0.13.1.tgz#eb273c199a0115ec0f0191c2449e97f512360f2e"
|
||||
integrity sha512-Dl0dUG4ZXNjYYuAUR0GMGpLGsA+cps2/ln3xEmy28bZR0sKkjXugsu2QOIxZjYIPBewDrXzPcvK8md45cMYoSg==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/history@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/history/-/history-0.12.4.tgz#bb97c6a079d57ea446f40d7de647e9ee5c7f63cd"
|
||||
integrity sha512-XLbSSr9FueAxuKHo4LBi+lZNVAEReNNDCt4MM2Ol8UZhWPlpNskSB/sECYEEQ6/ItlzgtnKyKWjfDFBHRWvC2g==
|
||||
"@lexical/history@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/history/-/history-0.13.1.tgz#3bb54716dc69779d3b35894bd72637a7fc2ed284"
|
||||
integrity sha512-cZXt30MalEEiRaflE9tHeGYnwT1xSDjXLsf9M409DSU9POJyZ1fsULJrG1tWv2uFQOhwal33rve9+MatUlITrg==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/html@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/html/-/html-0.12.4.tgz#25dd678d3d2bb735fc23340867bfe87e66248495"
|
||||
integrity sha512-RD/n9n1eCuTZtLaTEI3wuUDlJjCn6j+/0c9GvzqLKhNz9f+E5zMVExhzTT4cZQh5WXbzGFNlwC/cuOtaM3wODg==
|
||||
"@lexical/html@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/html/-/html-0.13.1.tgz#e56035d0c6528ffb932390e0d3d357c82f69253a"
|
||||
integrity sha512-XkZrnCSHIUavtpMol6aG8YsJ5KqC9hMxEhAENf3HTGi3ocysCByyXOyt1EhEYpjJvgDG4wRqt25xGDbLjj1/sA==
|
||||
dependencies:
|
||||
"@lexical/selection" "0.12.4"
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/selection" "0.13.1"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/link@0.12.4", "@lexical/link@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/link/-/link-0.12.4.tgz#364628ae06396cd0182c978efaa9e66d77b34758"
|
||||
integrity sha512-gmEs0GJGDhgwV1x0IrO7Br2GCALijZLIayGWoLAgYiXZee4WZpvjbngZuC6yghYBhrme6muPRMG2sLMwV2cWiQ==
|
||||
"@lexical/link@0.13.1", "@lexical/link@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/link/-/link-0.13.1.tgz#f1c4c12c828c0251e5d7fb4fb336f2d62380fc57"
|
||||
integrity sha512-7E3B2juL2UoMj2n+CiyFZ7tlpsdViAoIE7MpegXwfe/VQ66wFwk/VxGTa/69ng2EoF7E0kh+SldvGQDrWAWb1g==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/list@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/list/-/list-0.12.4.tgz#f57fe71ff599e298569722e0364c26a5cf417082"
|
||||
integrity sha512-qxwRIz+4Aj2u2fzyGPo86vX+1ebwCnamppr/c5ZWuqpRTWtYDWjq5LQKIwAvZBxCzPdtP5jzwyZ6VYWQXYW4Kg==
|
||||
"@lexical/list@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/list/-/list-0.13.1.tgz#461cb989157bdf4a43eaa8596fdb09df60d114ee"
|
||||
integrity sha512-6U1pmNZcKLuOWiWRML8Raf9zSEuUCMlsOye82niyF6I0rpPgYo5UFghAAbGISDsyqzM1B2L4BgJ6XrCk/dJptg==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/mark@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/mark/-/mark-0.12.4.tgz#dfe221143d9d2c006b680d88ab2cba281bfb7a45"
|
||||
integrity sha512-NFFk/3AFFJARjsth8wd5HdeW8XhcaECoQ8wwnJ4fRZzgN0lu3ZSiq+CuVm0NRN5xA5KoUT6sfIQqGOzIPfvdsw==
|
||||
"@lexical/mark@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/mark/-/mark-0.13.1.tgz#084bb49a8bc1c5c5a4ed5c5d4a20c98ea85ec8b1"
|
||||
integrity sha512-dW27PW8wWDOKFqXTBUuUfV+umU0KfwvXGkPUAxRJrvwUWk5RKaS48LhgbNlQ5BfT84Q8dSiQzvbaa6T40t9a3A==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/markdown@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/markdown/-/markdown-0.12.4.tgz#ca492a9c76ce7d24e49a51603f770fdfe23d0b51"
|
||||
integrity sha512-cOk0dkafyvQI4DMwwMfkP329bRVfyhXcVF3dcRiydl6ZIgqOrj/EMi+C0qxQkcqg0MO26Rky6LLJ4vQi6AgJDg==
|
||||
"@lexical/markdown@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/markdown/-/markdown-0.13.1.tgz#1fd2efcacff4ce733682a8161a3f3d78dba37503"
|
||||
integrity sha512-6tbdme2h5Zy/M88loVQVH5G0Nt7VMR9UUkyiSaicyBRDOU2OHacaXEp+KSS/XuF+d7TA+v/SzyDq8HS77cO1wA==
|
||||
dependencies:
|
||||
"@lexical/code" "0.12.4"
|
||||
"@lexical/link" "0.12.4"
|
||||
"@lexical/list" "0.12.4"
|
||||
"@lexical/rich-text" "0.12.4"
|
||||
"@lexical/text" "0.12.4"
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/code" "0.13.1"
|
||||
"@lexical/link" "0.13.1"
|
||||
"@lexical/list" "0.13.1"
|
||||
"@lexical/rich-text" "0.13.1"
|
||||
"@lexical/text" "0.13.1"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/offset@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/offset/-/offset-0.12.4.tgz#00c0020a98e32216bd6f119949d3a3bd64b4b139"
|
||||
integrity sha512-6fjXCx+YD1TMl6GFL4wowhBgbIg+UX3j2OOXh3F7WEp3SDvzoJsJ6F7xRctrHQbluCITM3oDwOyHa1J0m5lrFg==
|
||||
"@lexical/offset@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/offset/-/offset-0.13.1.tgz#f37417822aef3dc81580d4abb96e43ba9d547225"
|
||||
integrity sha512-j/RZcztJ7dyTrfA2+C3yXDzWDXV+XmMpD5BYeQCEApaHvlo20PHt1BISk7RcrnQW8PdzGvpKblRWf//c08LS9w==
|
||||
|
||||
"@lexical/overflow@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/overflow/-/overflow-0.12.4.tgz#3e7725e356044a5c9a7a80e53edc23cddf026da9"
|
||||
integrity sha512-mEWgVukoOgcyDruHvzk1amy9jgGDVXFYiPn20ykxgrVQz6XEpq+lfyic/BUnN4toNR8p6jc/Yxi2lF1ELCU0Kg==
|
||||
"@lexical/overflow@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/overflow/-/overflow-0.13.1.tgz#42c036dc3ad3eb929fda5aa0a00a725b74f72669"
|
||||
integrity sha512-Uw34j+qG2UJRCIR+bykfFMduFk7Pc4r/kNt8N1rjxGuGXAsreTVch1iOhu7Ev6tJgkURsduKuaJCAi7iHnKl7g==
|
||||
|
||||
"@lexical/plain-text@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/plain-text/-/plain-text-0.12.4.tgz#10ef4d56e1569e0d8ad1bc12569cffd736414957"
|
||||
integrity sha512-osbqOyt19oFG0kTbV71jxxCdgnUqNYW6QXIIaS1SwcCN/N1CdFZ0sNpjPkHIFx9AdZ/Tmi4u9SNFUo16DjvThA==
|
||||
"@lexical/plain-text@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/plain-text/-/plain-text-0.13.1.tgz#e7e713029443c30facce27b34836bf604cf92c0f"
|
||||
integrity sha512-4j5KAsMKUvJ8LhVDSS4zczbYXzdfmgYSAVhmqpSnJtud425Nk0TAfpUBLFoivxZB7KMoT1LGWQZvd47IvJPvtA==
|
||||
|
||||
"@lexical/react@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/react/-/react-0.12.4.tgz#4c53c32d8575dff685334b116e5a2bdf19a34da5"
|
||||
integrity sha512-tz4ebqJ++YP/Y6FCjk5aU3bvgrps8+i9abqvaaNCSzSQavI0qHtdS7EGy4S9qyO6qKuthXcOGIQxGTweRTkDsA==
|
||||
"@lexical/react@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/react/-/react-0.13.1.tgz#6c35bf43e24560d2ca3aa2c6ff607ef37de87bac"
|
||||
integrity sha512-Sy6EL230KAb0RZsZf1dZrRrc3+rvCDQWltcd8C/cqBUYlxsLYCW9s4f3RB2werngD/PtLYbBB48SYXNkIALITA==
|
||||
dependencies:
|
||||
"@lexical/clipboard" "0.12.4"
|
||||
"@lexical/code" "0.12.4"
|
||||
"@lexical/dragon" "0.12.4"
|
||||
"@lexical/hashtag" "0.12.4"
|
||||
"@lexical/history" "0.12.4"
|
||||
"@lexical/link" "0.12.4"
|
||||
"@lexical/list" "0.12.4"
|
||||
"@lexical/mark" "0.12.4"
|
||||
"@lexical/markdown" "0.12.4"
|
||||
"@lexical/overflow" "0.12.4"
|
||||
"@lexical/plain-text" "0.12.4"
|
||||
"@lexical/rich-text" "0.12.4"
|
||||
"@lexical/selection" "0.12.4"
|
||||
"@lexical/table" "0.12.4"
|
||||
"@lexical/text" "0.12.4"
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/yjs" "0.12.4"
|
||||
"@lexical/clipboard" "0.13.1"
|
||||
"@lexical/code" "0.13.1"
|
||||
"@lexical/dragon" "0.13.1"
|
||||
"@lexical/hashtag" "0.13.1"
|
||||
"@lexical/history" "0.13.1"
|
||||
"@lexical/link" "0.13.1"
|
||||
"@lexical/list" "0.13.1"
|
||||
"@lexical/mark" "0.13.1"
|
||||
"@lexical/markdown" "0.13.1"
|
||||
"@lexical/overflow" "0.13.1"
|
||||
"@lexical/plain-text" "0.13.1"
|
||||
"@lexical/rich-text" "0.13.1"
|
||||
"@lexical/selection" "0.13.1"
|
||||
"@lexical/table" "0.13.1"
|
||||
"@lexical/text" "0.13.1"
|
||||
"@lexical/utils" "0.13.1"
|
||||
"@lexical/yjs" "0.13.1"
|
||||
react-error-boundary "^3.1.4"
|
||||
|
||||
"@lexical/rich-text@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/rich-text/-/rich-text-0.12.4.tgz#545a1d6bd88e930c572d17fe504a8796f6af0c9d"
|
||||
integrity sha512-gWMDmdRRFPk00JfQv52650qcpjTN6oBrrYwBydYvEG8WTC8o1k8qEOZaOFja6GElPt0520dpyvcWHTlIL0jv3Q==
|
||||
"@lexical/rich-text@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/rich-text/-/rich-text-0.13.1.tgz#8251e81a3985a4d76bef027cf6c0dc90c661e4ec"
|
||||
integrity sha512-HliB9Ync06mv9DBg/5j0lIsTJp+exLHlaLJe+n8Zq1QNTzZzu2LsIT/Crquk50In7K/cjtlaQ/d5RB0LkjMHYg==
|
||||
|
||||
"@lexical/selection@0.12.4", "@lexical/selection@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/selection/-/selection-0.12.4.tgz#756922edbf42f3cb0bd6f99239d77ba2615c859c"
|
||||
integrity sha512-9lJt9PBJW7lWYiPDo/PGl2nZ6NrdYaDBidEoMNhyusPjeBEr35z4Hm0qWUhDrPDQPhK2i1oBw6nZa94bxuS9Lw==
|
||||
"@lexical/selection@0.13.1", "@lexical/selection@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/selection/-/selection-0.13.1.tgz#466d7cd0ee1b04680bd949112f1f5cb6a6618efa"
|
||||
integrity sha512-Kt9eSwjxPznj7yzIYipu9yYEgmRJhHiq3DNxHRxInYcZJWWNNHum2xKyxwwcN8QYBBzgfPegfM/geqQEJSV1lQ==
|
||||
|
||||
"@lexical/table@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/table/-/table-0.12.4.tgz#b40426de069b7e962e95e38f2ff1bc10ca649388"
|
||||
integrity sha512-Lyy6y1HOQqzU8O2cH5Zhzek46B0UU7NceM2fJKM7qiBSuxY/nE0BzkFq0xDk3x5W+vhXob6Z32sJSNFImtuqKw==
|
||||
"@lexical/table@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/table/-/table-0.13.1.tgz#814d3b8a2afb821aff151c92cce831809f9d67a1"
|
||||
integrity sha512-VQzgkfkEmnvn6C64O/kvl0HI3bFoBh3WA/U67ALw+DS11Mb5CKjbt0Gzm/258/reIxNMpshjjicpWMv9Miwauw==
|
||||
dependencies:
|
||||
"@lexical/utils" "0.12.4"
|
||||
"@lexical/utils" "0.13.1"
|
||||
|
||||
"@lexical/text@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/text/-/text-0.12.4.tgz#65ba9620492d673cd68c8380725d4e4fe845e603"
|
||||
integrity sha512-r/7402eCf6C/7BqUNR7ZLZQQjsE62wjeuf0rFeW1ulOpwiti/dFn1o+EsCb0hvNeHPzfGgRC+FuDT9KSEKu7Ig==
|
||||
"@lexical/text@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/text/-/text-0.13.1.tgz#12104d42da7a707a19853679f3a88e8ed6ce8084"
|
||||
integrity sha512-NYy3TZKt3qzReDwN2Rr5RxyFlg84JjXP2JQGMrXSSN7wYe73ysQIU6PqdVrz4iZkP+w34F3pl55dJ24ei3An9w==
|
||||
|
||||
"@lexical/utils@0.12.4", "@lexical/utils@^0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/utils/-/utils-0.12.4.tgz#83ed97d31201e1b911cfa38b940909c3cca41d77"
|
||||
integrity sha512-ColV11ANBY6deT7CdGwP4lzv3pb5caFfFLcVKdGDMMJSUYFQ5l69aZvDP2qWWnNqzGLb+AJSunMd142wWc5LGg==
|
||||
"@lexical/utils@0.13.1", "@lexical/utils@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/utils/-/utils-0.13.1.tgz#f2a72f71c859933781294830b38b25b5b33122a9"
|
||||
integrity sha512-AtQQKzYymkbOaQxaBXjRBS8IPxF9zWQnqwHTUTrJqJ4hX71aIQd/thqZbfQETAFJfC8pNBZw5zpxN6yPHk23dQ==
|
||||
dependencies:
|
||||
"@lexical/list" "0.12.4"
|
||||
"@lexical/selection" "0.12.4"
|
||||
"@lexical/table" "0.12.4"
|
||||
"@lexical/list" "0.13.1"
|
||||
"@lexical/selection" "0.13.1"
|
||||
"@lexical/table" "0.13.1"
|
||||
|
||||
"@lexical/yjs@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/yjs/-/yjs-0.12.4.tgz#ea986b66932558062bab2ccc1b46c34c0260ea3e"
|
||||
integrity sha512-qtCiABugE1CiZ7K5iFfQnB1KqfWtLyiRK0nxAaSxuZzQTO4+Kh3WDh7ULppPa53Sf3pKpw8Sq2XB4AXP6csbkg==
|
||||
"@lexical/yjs@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@lexical/yjs/-/yjs-0.13.1.tgz#2a71ae3c4b3cc5c660bbe66d537eb0cbf3c7c1b6"
|
||||
integrity sha512-4GbqQM+PwNTV59AZoNrfTe/0rLjs+cX6Y6yAdZSRPBwr5L3JzYeU1TTcFCVQTtsE7KF8ddVP8sD7w9pi8rOWLA==
|
||||
dependencies:
|
||||
"@lexical/offset" "0.12.4"
|
||||
"@lexical/offset" "0.13.1"
|
||||
|
||||
"@mdn/browser-compat-data@^5.2.34", "@mdn/browser-compat-data@^5.3.13":
|
||||
version "5.3.16"
|
||||
resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-5.3.16.tgz#c3b6585c256461fe5e2eac85182b11b36ea2678b"
|
||||
integrity sha512-b0kKg2weqKDLI+Ai5+tocgUEIidccdSfzUndbS2YnwIp5aVvd3M0D+DCcbrsSOSgMyrV9QKMqogtqMIjKwvDxw==
|
||||
|
||||
"@noble/ciphers@^0.2.0":
|
||||
"@noble/ciphers@0.2.0", "@noble/ciphers@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.2.0.tgz#a12cda60f3cf1ab5d7c77068c3711d2366649ed7"
|
||||
integrity sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==
|
||||
|
@ -1844,16 +1844,35 @@
|
|||
dependencies:
|
||||
"@noble/hashes" "1.3.1"
|
||||
|
||||
"@noble/curves@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35"
|
||||
integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.3.2"
|
||||
|
||||
"@noble/curves@~1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e"
|
||||
integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==
|
||||
dependencies:
|
||||
"@noble/hashes" "1.3.3"
|
||||
|
||||
"@noble/hashes@1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9"
|
||||
integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==
|
||||
|
||||
"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
|
||||
"@noble/hashes@1.3.2", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
|
||||
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
|
||||
|
||||
"@noble/hashes@1.3.3", "@noble/hashes@^1.3.3", "@noble/hashes@~1.3.2":
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
|
||||
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
|
@ -2108,6 +2127,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
|
||||
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
|
||||
|
||||
"@scure/base@^1.1.5", "@scure/base@~1.1.4":
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157"
|
||||
integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==
|
||||
|
||||
"@scure/bip32@1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10"
|
||||
|
@ -2117,6 +2141,15 @@
|
|||
"@noble/hashes" "~1.3.1"
|
||||
"@scure/base" "~1.1.0"
|
||||
|
||||
"@scure/bip32@^1.3.3":
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8"
|
||||
integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==
|
||||
dependencies:
|
||||
"@noble/curves" "~1.3.0"
|
||||
"@noble/hashes" "~1.3.2"
|
||||
"@scure/base" "~1.1.4"
|
||||
|
||||
"@scure/bip39@1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a"
|
||||
|
@ -2125,6 +2158,14 @@
|
|||
"@noble/hashes" "~1.3.0"
|
||||
"@scure/base" "~1.1.0"
|
||||
|
||||
"@scure/bip39@^1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527"
|
||||
integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==
|
||||
dependencies:
|
||||
"@noble/hashes" "~1.3.2"
|
||||
"@scure/base" "~1.1.4"
|
||||
|
||||
"@sentry-internal/tracing@7.74.1":
|
||||
version "7.74.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.74.1.tgz#55ff387e61d2c9533a9a0d099d376332426c8e08"
|
||||
|
@ -2375,6 +2416,13 @@
|
|||
"@types/node" "*"
|
||||
"@types/responselike" "^1.0.0"
|
||||
|
||||
"@types/dompurify@^3.0.5":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-3.0.5.tgz#02069a2fcb89a163bacf1a788f73cb415dd75cb7"
|
||||
integrity sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==
|
||||
dependencies:
|
||||
"@types/trusted-types" "*"
|
||||
|
||||
"@types/escape-html@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-1.0.1.tgz#b19b4646915f0ae2c306bf984dc0a59c5cfc97ba"
|
||||
|
@ -2612,6 +2660,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564"
|
||||
integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==
|
||||
|
||||
"@types/trusted-types@*":
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
|
||||
integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
|
||||
|
||||
"@types/trusted-types@^2.0.2":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.4.tgz#2b38784cd16957d3782e8e2b31c03bc1d13b4d65"
|
||||
|
@ -3885,6 +3938,13 @@ cssstyle@^3.0.0:
|
|||
dependencies:
|
||||
rrweb-cssom "^0.6.0"
|
||||
|
||||
cssstyle@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.0.1.tgz#ef29c598a1e90125c870525490ea4f354db0660a"
|
||||
integrity sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==
|
||||
dependencies:
|
||||
rrweb-cssom "^0.6.0"
|
||||
|
||||
csstype@^3.0.2:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b"
|
||||
|
@ -4101,6 +4161,11 @@ domhandler@^4.2.0, domhandler@^4.3.1:
|
|||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
dompurify@^3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.8.tgz#e0021ab1b09184bc8af7e35c7dd9063f43a8a437"
|
||||
integrity sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==
|
||||
|
||||
domutils@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
||||
|
@ -5292,10 +5357,10 @@ human-signals@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
|
||||
integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
|
||||
|
||||
husky@^8.0.0:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
|
||||
integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==
|
||||
husky@^9.0.0:
|
||||
version "9.0.10"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.10.tgz#ddca8908deb5f244e9286865ebc80b54387672c2"
|
||||
integrity sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
version "0.6.3"
|
||||
|
@ -5699,6 +5764,15 @@ isexe@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
isomorphic-dompurify@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-dompurify/-/isomorphic-dompurify-2.3.0.tgz#bc48fbdf52f84cf7e0a63a5e8ec89052e7dbc3c5"
|
||||
integrity sha512-FCoKY4/mW/jnn/+VgE7wXGC2D/RXzVCAmGYuGWEuZXtyWnwmE2100caciIv+RbHk90q9LA0OW5IBn2f+ywHtww==
|
||||
dependencies:
|
||||
"@types/dompurify" "^3.0.5"
|
||||
dompurify "^3.0.8"
|
||||
jsdom "^24.0.0"
|
||||
|
||||
iterator.prototype@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0"
|
||||
|
@ -5792,6 +5866,33 @@ jsdom@^23.0.0:
|
|||
ws "^8.14.2"
|
||||
xml-name-validator "^5.0.0"
|
||||
|
||||
jsdom@^24.0.0:
|
||||
version "24.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-24.0.0.tgz#e2dc04e4c79da368481659818ee2b0cd7c39007c"
|
||||
integrity sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==
|
||||
dependencies:
|
||||
cssstyle "^4.0.1"
|
||||
data-urls "^5.0.0"
|
||||
decimal.js "^10.4.3"
|
||||
form-data "^4.0.0"
|
||||
html-encoding-sniffer "^4.0.0"
|
||||
http-proxy-agent "^7.0.0"
|
||||
https-proxy-agent "^7.0.2"
|
||||
is-potential-custom-element-name "^1.0.1"
|
||||
nwsapi "^2.2.7"
|
||||
parse5 "^7.1.2"
|
||||
rrweb-cssom "^0.6.0"
|
||||
saxes "^6.0.0"
|
||||
symbol-tree "^3.2.4"
|
||||
tough-cookie "^4.1.3"
|
||||
w3c-xmlserializer "^5.0.0"
|
||||
webidl-conversions "^7.0.0"
|
||||
whatwg-encoding "^3.1.1"
|
||||
whatwg-mimetype "^4.0.0"
|
||||
whatwg-url "^14.0.0"
|
||||
ws "^8.16.0"
|
||||
xml-name-validator "^5.0.0"
|
||||
|
||||
jsesc@^2.5.1:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||
|
@ -5987,10 +6088,10 @@ levn@^0.4.1:
|
|||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
lexical@^0.12.4:
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/lexical/-/lexical-0.12.4.tgz#1f38d40eb1b5bdcf30a79864027bf7443de52fb5"
|
||||
integrity sha512-giNrnp45H6P4IHFhkKaHEPTF+bKLBWdEIDL/FGjRZf+to7l7TORIBk/23Zdchzt/VGgKGWu950EOvGh53gkVMQ==
|
||||
lexical@^0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/lexical/-/lexical-0.13.1.tgz#0abffe9bc05a7a9da8a6128ea478bf08c11654db"
|
||||
integrity sha512-jaqRYzVEfBKbX4FwYpd/g+MyOjRaraAel0iQsTrwvx3hyN0bswUZuzb6H6nGlFSjcdrc77wKpyKwoWj4aUd+Bw==
|
||||
|
||||
li@^1.3.0:
|
||||
version "1.3.0"
|
||||
|
@ -6214,6 +6315,11 @@ lowercase-keys@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
|
||||
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
|
||||
|
||||
lru-cache@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
|
||||
integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
|
||||
|
||||
lru-cache@^4.1.2:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
|
@ -6510,6 +6616,25 @@ nostr-tools@^1.14.0, nostr-tools@^1.14.2:
|
|||
"@scure/bip32" "1.3.1"
|
||||
"@scure/bip39" "1.2.1"
|
||||
|
||||
nostr-tools@^2.1.4:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.1.5.tgz#d38ac1139343cf13654841b8727bab8dd70563eb"
|
||||
integrity sha512-Gug/j54YGQ0ewB09dZW3mS9qfXWFlcOQMlyb1MmqQsuNO/95mfNOQSBi+jZ61O++Y+jG99SzAUPFLopUsKf0MA==
|
||||
dependencies:
|
||||
"@noble/ciphers" "0.2.0"
|
||||
"@noble/curves" "1.2.0"
|
||||
"@noble/hashes" "1.3.1"
|
||||
"@scure/base" "1.1.1"
|
||||
"@scure/bip32" "1.3.1"
|
||||
"@scure/bip39" "1.2.1"
|
||||
optionalDependencies:
|
||||
nostr-wasm v0.1.0
|
||||
|
||||
nostr-wasm@v0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nostr-wasm/-/nostr-wasm-0.1.0.tgz#17af486745feb2b7dd29503fdd81613a24058d94"
|
||||
integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==
|
||||
|
||||
npm-run-path@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||
|
@ -6524,6 +6649,18 @@ npm-run-path@^5.1.0:
|
|||
dependencies:
|
||||
path-key "^4.0.0"
|
||||
|
||||
nspec@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nspec/-/nspec-0.1.0.tgz#abde817cf34cb042d7315a70cf515037e489401b"
|
||||
integrity sha512-HPVyFFVR2x49K7HJzEjlvvBR7x5t79G6bh7/SQvfm25hXVFq9xvYBQ6i3nluwJkizcBxm+fvErM5yqJEnM/1tA==
|
||||
dependencies:
|
||||
"@scure/base" "^1.1.5"
|
||||
"@scure/bip32" "^1.3.3"
|
||||
"@scure/bip39" "^1.2.2"
|
||||
lru-cache "^10.2.0"
|
||||
nostr-tools "^2.1.4"
|
||||
zod "^3.22.4"
|
||||
|
||||
nth-check@^2.0.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||
|
@ -9483,6 +9620,11 @@ ws@^8.14.2:
|
|||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
|
||||
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
|
||||
|
||||
ws@^8.16.0:
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
|
||||
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
|
||||
|
||||
xcase@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xcase/-/xcase-2.0.1.tgz#c7fa72caa0f440db78fd5673432038ac984450b9"
|
||||
|
@ -9560,3 +9702,8 @@ zod@^3.21.0, zod@^3.21.4:
|
|||
version "3.22.3"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.3.tgz#2fbc96118b174290d94e8896371c95629e87a060"
|
||||
integrity sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==
|
||||
|
||||
zod@^3.22.4:
|
||||
version "3.22.4"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
||||
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
|
||||
|
|
Ładowanie…
Reference in New Issue