mirror of
https://github.com/standardnotes/app
synced 2026-09-13 09:46:02 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfa2e75adc | ||
|
|
418d1a7371 | ||
|
|
813304c959 | ||
|
|
ba236a2f2b | ||
|
|
2757884d10 | ||
|
|
f2bcab6131 | ||
|
|
327f732adc |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.26.77](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api
|
||||
|
||||
## [1.26.76](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api",
|
||||
"version": "1.26.76",
|
||||
"version": "1.26.77",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.1.397](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.396](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.395](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.394](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@standardnotes/clipper",
|
||||
"description": "Web clipper browser extension for Standard Notes",
|
||||
"version": "1.1.394",
|
||||
"version": "1.1.397",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-mv2": "yarn clean && webpack --config ./webpack.config.prod.js",
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.109.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
### Features
|
||||
|
||||
* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))
|
||||
|
||||
## [3.108.334](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.333](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.332](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
content="
|
||||
default-src 'self' blob:;
|
||||
script-src 'self' 'unsafe-eval';
|
||||
worker-src blob:;
|
||||
worker-src 'self' blob:;
|
||||
connect-src * data: blob:;
|
||||
style-src 'unsafe-inline' 'self' http://localhost:* http://127.0.0.1:45653;
|
||||
frame-src * blob:;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@standardnotes/desktop",
|
||||
"main": "./app/dist/index.js",
|
||||
"version": "3.108.332",
|
||||
"version": "3.109.0",
|
||||
"license": "AGPL-3.0",
|
||||
"author": "Standard Notes.",
|
||||
"private": true,
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.21.99](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/encryption
|
||||
|
||||
## [1.21.98](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/encryption
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/encryption",
|
||||
"version": "1.21.98",
|
||||
"version": "1.21.99",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.28.114](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/filepicker
|
||||
|
||||
## [1.28.113](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/filepicker
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/filepicker",
|
||||
"version": "1.28.113",
|
||||
"version": "1.28.114",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.19.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
### Features
|
||||
|
||||
* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))
|
||||
|
||||
## [1.18.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files",
|
||||
"version": "1.18.10",
|
||||
"version": "1.19.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
export interface SuperConverterServiceInterface {
|
||||
isValidSuperString(superString: string): boolean
|
||||
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => Promise<string>
|
||||
convertSuperStringToOtherFormat: (
|
||||
superString: string,
|
||||
toFormat: 'txt' | 'md' | 'html' | 'json' | 'pdf',
|
||||
) => Promise<string>
|
||||
convertOtherFormatToSuperString: (
|
||||
otherFormatString: string,
|
||||
fromFormat: 'txt' | 'md' | 'html' | 'json',
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.58.56](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.58.55](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.58.54](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.58.53](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/mobile",
|
||||
"version": "3.58.53",
|
||||
"version": "3.58.56",
|
||||
"author": "Standard Notes.",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.52.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
### Features
|
||||
|
||||
* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))
|
||||
|
||||
# [1.51.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/models",
|
||||
"version": "1.51.0",
|
||||
"version": "1.52.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -87,7 +87,7 @@ export type PrefValue = {
|
||||
[PrefKey.MomentsDefaultTagUuid]: string | undefined
|
||||
[PrefKey.ClipperDefaultTagUuid]: string | undefined
|
||||
[PrefKey.SystemViewPreferences]: Partial<Record<SystemViewId, TagPreferences>>
|
||||
[PrefKey.SuperNoteExportFormat]: 'json' | 'md' | 'html'
|
||||
[PrefKey.SuperNoteExportFormat]: 'json' | 'md' | 'html' | 'pdf'
|
||||
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference' | 'inline' | 'separate'
|
||||
[PrefKey.SuperNoteExportUseMDFrontmatter]: boolean
|
||||
[PrefKey.AuthenticatorNames]: string
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.4.691](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.690](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.689](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.688](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/releases",
|
||||
"version": "1.4.688",
|
||||
"version": "1.4.691",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/releases.json",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.68.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/services
|
||||
|
||||
## [1.68.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/services
|
||||
|
||||
# [1.68.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/services",
|
||||
"version": "1.68.0",
|
||||
"version": "1.68.2",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { AnyItemInterface } from '@standardnotes/models'
|
||||
import { SyncBackoffService } from './SyncBackoffService'
|
||||
|
||||
describe('SyncBackoffService', () => {
|
||||
const createService = () => new SyncBackoffService()
|
||||
|
||||
it('should not be in backoff if no backoff was set', () => {
|
||||
const service = createService()
|
||||
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(false)
|
||||
})
|
||||
|
||||
it('should be in backoff if backoff was set', () => {
|
||||
const service = createService()
|
||||
|
||||
service.backoffItem({ uuid: '123' } as jest.Mocked<AnyItemInterface>)
|
||||
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(true)
|
||||
})
|
||||
|
||||
it('should not be in backoff if backoff expired', () => {
|
||||
const service = createService()
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_000_000)
|
||||
|
||||
service.backoffItem({ uuid: '123' } as jest.Mocked<AnyItemInterface>)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(2_000_000)
|
||||
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(false)
|
||||
})
|
||||
|
||||
it('should double backoff penalty on each backoff', () => {
|
||||
const service = createService()
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_000_000)
|
||||
|
||||
service.backoffItem({ uuid: '123' } as jest.Mocked<AnyItemInterface>)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_000_000)
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(true)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_000_000)
|
||||
service.backoffItem({ uuid: '123' } as jest.Mocked<AnyItemInterface>)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_001_000)
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(true)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_000_000)
|
||||
service.backoffItem({ uuid: '123' } as jest.Mocked<AnyItemInterface>)
|
||||
|
||||
jest.spyOn(Date, 'now').mockReturnValueOnce(1_003_000)
|
||||
expect(service.isItemInBackoff({ uuid: '123' } as jest.Mocked<AnyItemInterface>)).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
import { AnyItemInterface } from '@standardnotes/models'
|
||||
import { SyncBackoffServiceInterface } from './SyncBackoffServiceInterface'
|
||||
|
||||
export class SyncBackoffService implements SyncBackoffServiceInterface {
|
||||
private backoffPenalties: Map<string, number>
|
||||
private backoffStartTimestamps: Map<string, number>
|
||||
|
||||
constructor() {
|
||||
this.backoffPenalties = new Map<string, number>()
|
||||
this.backoffStartTimestamps = new Map<string, number>()
|
||||
}
|
||||
|
||||
isItemInBackoff(item: AnyItemInterface): boolean {
|
||||
const backoffStartingTimestamp = this.backoffStartTimestamps.get(item.uuid)
|
||||
if (!backoffStartingTimestamp) {
|
||||
return false
|
||||
}
|
||||
|
||||
const backoffPenalty = this.backoffPenalties.get(item.uuid)
|
||||
if (!backoffPenalty) {
|
||||
return false
|
||||
}
|
||||
|
||||
const backoffEndTimestamp = backoffStartingTimestamp + backoffPenalty
|
||||
|
||||
return backoffEndTimestamp > Date.now()
|
||||
}
|
||||
|
||||
backoffItem(item: AnyItemInterface): void {
|
||||
const backoffPenalty = this.backoffPenalties.get(item.uuid) || 0
|
||||
|
||||
const newBackoffPenalty = backoffPenalty === 0 ? 1_000 : backoffPenalty * 2
|
||||
|
||||
this.backoffPenalties.set(item.uuid, newBackoffPenalty)
|
||||
this.backoffStartTimestamps.set(item.uuid, Date.now())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { AnyItemInterface } from '@standardnotes/models'
|
||||
|
||||
export interface SyncBackoffServiceInterface {
|
||||
isItemInBackoff(item: AnyItemInterface): boolean
|
||||
backoffItem(item: AnyItemInterface): void
|
||||
}
|
||||
@@ -181,6 +181,8 @@ export * from './Subscription/AppleIAPReceipt'
|
||||
export * from './Subscription/SubscriptionManager'
|
||||
export * from './Subscription/SubscriptionManagerEvent'
|
||||
export * from './Subscription/SubscriptionManagerInterface'
|
||||
export * from './Sync/SyncBackoffService'
|
||||
export * from './Sync/SyncBackoffServiceInterface'
|
||||
export * from './Sync/SyncMode'
|
||||
export * from './Sync/SyncOpStatus'
|
||||
export * from './Sync/SyncOptions'
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.205.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/snjs
|
||||
|
||||
## [2.205.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/snjs
|
||||
|
||||
# [2.205.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -145,6 +145,8 @@ import {
|
||||
IsVaultAdmin,
|
||||
IsReadonlyVaultMember,
|
||||
DesignateSurvivor,
|
||||
SyncBackoffService,
|
||||
SyncBackoffServiceInterface,
|
||||
} from '@standardnotes/services'
|
||||
import { ItemManager } from '../../Services/Items/ItemManager'
|
||||
import { PayloadManager } from '../../Services/Payloads/PayloadManager'
|
||||
@@ -1351,6 +1353,10 @@ export class Dependencies {
|
||||
)
|
||||
})
|
||||
|
||||
this.factory.set(TYPES.SyncBackoffService, () => {
|
||||
return new SyncBackoffService()
|
||||
})
|
||||
|
||||
this.factory.set(TYPES.SyncService, () => {
|
||||
return new SyncService(
|
||||
this.get<ItemManager>(TYPES.ItemManager),
|
||||
@@ -1369,6 +1375,7 @@ export class Dependencies {
|
||||
this.get<Logger>(TYPES.Logger),
|
||||
this.get<WebSocketsService>(TYPES.WebSocketsService),
|
||||
this.get<SyncFrequencyGuardInterface>(TYPES.SyncFrequencyGuard),
|
||||
this.get<SyncBackoffServiceInterface>(TYPES.SyncBackoffService),
|
||||
this.get<InternalEventBus>(TYPES.InternalEventBus),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -30,6 +30,7 @@ export const TYPES = {
|
||||
SubscriptionManager: Symbol.for('SubscriptionManager'),
|
||||
HistoryManager: Symbol.for('HistoryManager'),
|
||||
SyncFrequencyGuard: Symbol.for('SyncFrequencyGuard'),
|
||||
SyncBackoffService: Symbol.for('SyncBackoffService'),
|
||||
SyncService: Symbol.for('SyncService'),
|
||||
ProtectionService: Symbol.for('ProtectionService'),
|
||||
UserService: Symbol.for('UserService'),
|
||||
|
||||
@@ -86,6 +86,7 @@ import {
|
||||
ApplicationSyncOptions,
|
||||
WebSocketsServiceEvent,
|
||||
WebSocketsService,
|
||||
SyncBackoffServiceInterface,
|
||||
} from '@standardnotes/services'
|
||||
import { OfflineSyncResponse } from './Offline/Response'
|
||||
import {
|
||||
@@ -171,6 +172,7 @@ export class SyncService
|
||||
private logger: LoggerInterface,
|
||||
private sockets: WebSocketsService,
|
||||
private syncFrequencyGuard: SyncFrequencyGuardInterface,
|
||||
private syncBackoffService: SyncBackoffServiceInterface,
|
||||
protected override internalEventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(internalEventBus)
|
||||
@@ -452,7 +454,11 @@ export class SyncService
|
||||
}
|
||||
|
||||
private itemsNeedingSync() {
|
||||
return this.itemManager.getDirtyItems()
|
||||
const dirtyItems = this.itemManager.getDirtyItems()
|
||||
|
||||
const itemsWithoutBackoffPenalty = dirtyItems.filter((item) => !this.syncBackoffService.isItemInBackoff(item))
|
||||
|
||||
return itemsWithoutBackoffPenalty
|
||||
}
|
||||
|
||||
public async markAllItemsAsNeedingSyncAndPersist(): Promise<void> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/snjs",
|
||||
"version": "2.205.0",
|
||||
"version": "2.205.2",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
### Features
|
||||
|
||||
* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))
|
||||
|
||||
## [1.4.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/toast
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/toast",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.0",
|
||||
"private": true,
|
||||
"main": "./src/index.ts",
|
||||
"scripts": {
|
||||
|
||||
@@ -90,8 +90,8 @@ export const Toast = forwardRef(({ toast, index }: Props, ref: ForwardedRef<HTML
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
<div className="grid gap-x-2.5 gap-y-1 overflow-hidden grid-cols-[1fr,auto] pl-3 pr-3.5 py-2.5">
|
||||
{icon ? <div className="sn-icon flex flex-shrink-0 items-center justify-center">{icon}</div> : null}
|
||||
<div className="grid gap-x-2.5 gap-y-1 overflow-hidden grid-cols-[min-content,auto] pl-3 pr-3.5 py-2.5">
|
||||
{icon ? <div className="sn-icon flex items-center justify-center">{icon}</div> : null}
|
||||
{toast.title && <div className="text-text text-sm font-semibold col-start-2">{toast.title}</div>}
|
||||
<div className="text-text text-sm [word-wrap:anywhere] col-start-2">{toast.message}</div>
|
||||
{hasActions && (
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.35.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/ui-services
|
||||
|
||||
## [1.35.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/ui-services
|
||||
|
||||
## [1.35.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/ui-services
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/ui-services",
|
||||
"version": "1.35.20",
|
||||
"version": "1.35.22",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.186.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)
|
||||
|
||||
### Features
|
||||
|
||||
* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))
|
||||
|
||||
## [3.185.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.185.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.185.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.186.0",
|
||||
"title": "[3.186.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-24)",
|
||||
"date": null,
|
||||
"body": "### Features\n\n* Super notes can now be exported as PDF ([#2776](https://github.com/standardnotes/app/issues/2776)) ([418d1a7](https://github.com/standardnotes/app/commit/418d1a7371d8fb981de80737a9d1ec4d7772476c))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Super notes can now be exported as PDF (#2776) (418d1a7)"
|
||||
],
|
||||
"Features": [
|
||||
"Super notes can now be exported as PDF (#2776) (418d1a7)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.185.4",
|
||||
"title": "[3.185.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-23)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.185.3",
|
||||
"title": "[3.185.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-21)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.185.2",
|
||||
"title": "[3.185.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2024-01-20)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/web",
|
||||
"version": "3.185.2",
|
||||
"version": "3.186.0",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/app.js",
|
||||
"author": "Standard Notes",
|
||||
@@ -111,6 +111,8 @@
|
||||
"@ariakit/react": "^0.3.9",
|
||||
"@lexical/headless": "0.12.6",
|
||||
"@radix-ui/react-slot": "^1.0.1",
|
||||
"@react-pdf/renderer": "^3.3.2",
|
||||
"comlink": "^4.4.1",
|
||||
"fast-diff": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,22 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
downloadSelectedItems().catch(console.error)
|
||||
}, [downloadSelectedItems, notes])
|
||||
|
||||
const shareSelectedItems = useCallback(() => {
|
||||
createNoteExport(application, notes)
|
||||
.then((result) => {
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
const { blob, fileName } = result
|
||||
|
||||
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), blob, fileName).catch(
|
||||
console.error,
|
||||
)
|
||||
})
|
||||
.catch(console.error)
|
||||
}, [application, notes])
|
||||
|
||||
const closeMenuAndToggleNotesList = useCallback(() => {
|
||||
const isMobileScreen = matchMedia(MutuallyExclusiveMediaQueryBreakpoints.sm).matches
|
||||
if (isMobileScreen) {
|
||||
@@ -347,34 +363,14 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
if (application.isNativeMobileWeb()) {
|
||||
createNoteExport(application, notes)
|
||||
.then((result) => {
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
const { blob, fileName } = result
|
||||
|
||||
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), blob, fileName).catch(
|
||||
console.error,
|
||||
)
|
||||
})
|
||||
.catch(console.error)
|
||||
} else {
|
||||
exportSelectedItems()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
|
||||
{application.platform === Platform.Android ? 'Share' : 'Export'}
|
||||
<MenuItem onClick={exportSelectedItems}>
|
||||
<Icon type="download" className={iconClass} />
|
||||
Export
|
||||
</MenuItem>
|
||||
{application.platform === Platform.Android && (
|
||||
<MenuItem onClick={exportSelectedItems}>
|
||||
<Icon type="download" className={iconClass} />
|
||||
Export
|
||||
<MenuItem onClick={shareSelectedItems}>
|
||||
<Icon type="share" className={iconClass} />
|
||||
Share
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={duplicateSelectedItems} disabled={areSomeNotesInReadonlySharedVault}>
|
||||
|
||||
@@ -15,6 +15,7 @@ type Props = {
|
||||
|
||||
const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
const application = useApplication()
|
||||
|
||||
const superNoteExportFormat = usePreference(PrefKey.SuperNoteExportFormat)
|
||||
const superNoteExportEmbedBehavior = usePreference(PrefKey.SuperNoteExportEmbedBehavior)
|
||||
const superNoteExportUseMDFrontmatter = usePreference(PrefKey.SuperNoteExportUseMDFrontmatter)
|
||||
@@ -26,10 +27,15 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
if (superNoteExportFormat === 'md' && superNoteExportEmbedBehavior === 'reference') {
|
||||
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'separate')
|
||||
}
|
||||
if (superNoteExportFormat === 'pdf' && superNoteExportEmbedBehavior !== 'inline') {
|
||||
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'inline')
|
||||
}
|
||||
}, [application, superNoteExportEmbedBehavior, superNoteExportFormat])
|
||||
|
||||
const someNotesHaveEmbeddedFiles = notes.some(noteHasEmbeddedFiles)
|
||||
|
||||
const canShowEmbeddedFileOptions = !['json', 'pdf'].includes(superNoteExportFormat)
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Export notes"
|
||||
@@ -61,6 +67,7 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
{ label: 'Super (.json)', value: 'json' },
|
||||
{ label: 'Markdown (.md)', value: 'md' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
{ label: 'PDF', value: 'pdf' },
|
||||
]}
|
||||
value={superNoteExportFormat}
|
||||
onChange={(value) => {
|
||||
@@ -93,7 +100,7 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
</Switch>
|
||||
</div>
|
||||
)}
|
||||
{superNoteExportFormat !== 'json' && someNotesHaveEmbeddedFiles && (
|
||||
{canShowEmbeddedFileOptions && someNotesHaveEmbeddedFiles && (
|
||||
<div className="mb-2 mt-4">
|
||||
<div className="mb-1">How do you want embedded files to be handled?</div>
|
||||
<RadioButtonGroup
|
||||
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
import { StyleSheet } from '@react-pdf/renderer'
|
||||
import {
|
||||
$getRoot,
|
||||
$isElementNode,
|
||||
$isParagraphNode,
|
||||
$isLineBreakNode,
|
||||
$isTextNode,
|
||||
LexicalEditor,
|
||||
LexicalNode,
|
||||
ElementNode,
|
||||
} from 'lexical'
|
||||
import { $isLinkNode } from '@lexical/link'
|
||||
import { $isHeadingNode, type HeadingNode, $isQuoteNode } from '@lexical/rich-text'
|
||||
import { $isListNode, $isListItemNode, ListType } from '@lexical/list'
|
||||
import { $isTableNode, $isTableRowNode, $isTableCellNode } from '@lexical/table'
|
||||
import { $isCodeNode } from '@lexical/code'
|
||||
import { $isInlineFileNode } from '../../../Plugins/InlineFilePlugin/InlineFileNode'
|
||||
import { $isRemoteImageNode } from '../../../Plugins/RemoteImagePlugin/RemoteImageNode'
|
||||
import { $isCollapsibleContainerNode } from '../../../Plugins/CollapsiblePlugin/CollapsibleContainerNode'
|
||||
import { $isCollapsibleContentNode } from '../../../Plugins/CollapsiblePlugin/CollapsibleContentNode'
|
||||
import { $isCollapsibleTitleNode } from '../../../Plugins/CollapsiblePlugin/CollapsibleTitleNode'
|
||||
import { PDFDataNode, PDFWorker } from './PDFWorker'
|
||||
import { wrap } from 'comlink'
|
||||
import { getBase64FromBlob } from '@/Utils'
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: {
|
||||
paddingVertical: 35,
|
||||
paddingHorizontal: 35,
|
||||
lineHeight: 1.5,
|
||||
fontSize: 12,
|
||||
gap: 14,
|
||||
},
|
||||
block: {
|
||||
gap: 14,
|
||||
},
|
||||
wrap: {
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
listMarker: {
|
||||
flexShrink: 0,
|
||||
height: '100%',
|
||||
marginRight: 2,
|
||||
},
|
||||
collapsibleTitle: {
|
||||
backgroundColor: 'rgba(0,0,0,0.05)',
|
||||
paddingTop: 4,
|
||||
paddingBottom: 2,
|
||||
paddingHorizontal: 6,
|
||||
borderTopLeftRadius: 6,
|
||||
borderTopRightRadius: 6,
|
||||
},
|
||||
quote: {
|
||||
borderLeftWidth: 4,
|
||||
color: 'rgba(46, 46, 46)',
|
||||
borderLeftColor: '#72767e',
|
||||
paddingLeft: 12,
|
||||
paddingVertical: 4,
|
||||
gap: 4,
|
||||
},
|
||||
})
|
||||
|
||||
const getListItemNode = ({
|
||||
children,
|
||||
value,
|
||||
listType,
|
||||
checked,
|
||||
}: {
|
||||
children: PDFDataNode[] | undefined
|
||||
value: number
|
||||
listType: ListType
|
||||
checked?: boolean
|
||||
}): PDFDataNode => {
|
||||
const marker = listType === 'bullet' ? '\u2022' : `${value}.`
|
||||
|
||||
return {
|
||||
type: 'View',
|
||||
style: styles.row,
|
||||
children: [
|
||||
listType === 'check'
|
||||
? {
|
||||
type: 'View',
|
||||
style: {
|
||||
width: 14,
|
||||
height: 14,
|
||||
borderRadius: 2,
|
||||
borderWidth: 1,
|
||||
borderColor: checked ? '#086dd6' : '#000',
|
||||
backgroundColor: checked ? '#086dd6' : 'transparent',
|
||||
marginRight: 6,
|
||||
},
|
||||
children: checked
|
||||
? [
|
||||
{
|
||||
type: 'Svg',
|
||||
viewBox: '0 0 20 20',
|
||||
fill: '#ffffff',
|
||||
children: [
|
||||
{
|
||||
type: 'Path',
|
||||
d: 'M17.5001 5.83345L7.50008 15.8334L2.91675 11.2501L4.09175 10.0751L7.50008 13.4751L16.3251 4.65845L17.5001 5.83345Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
}
|
||||
: {
|
||||
type: 'View',
|
||||
style: styles.listMarker,
|
||||
children: [
|
||||
{
|
||||
type: 'Text',
|
||||
children: marker + ' ',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'Text',
|
||||
style: {
|
||||
flex: 1,
|
||||
},
|
||||
children,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
const MinimumHeadingFontSize = 13
|
||||
const MaxHeadingLevel = 6
|
||||
const getFontSizeForHeading = (heading: HeadingNode) => {
|
||||
const level = parseInt(heading.getTag().slice(1))
|
||||
const multiplier = (MaxHeadingLevel - level) * 2
|
||||
|
||||
return MinimumHeadingFontSize + multiplier
|
||||
}
|
||||
|
||||
const getNodeTextAlignment = (node: ElementNode) => {
|
||||
const formatType = node.getFormatType()
|
||||
|
||||
if (!formatType) {
|
||||
return 'left'
|
||||
}
|
||||
|
||||
if (formatType === 'start') {
|
||||
return 'left'
|
||||
}
|
||||
|
||||
if (formatType === 'end') {
|
||||
return 'right'
|
||||
}
|
||||
|
||||
return formatType
|
||||
}
|
||||
|
||||
const getPDFDataNodeFromLexicalNode = (node: LexicalNode): PDFDataNode => {
|
||||
const parent = node.getParent()
|
||||
|
||||
if ($isLineBreakNode(node)) {
|
||||
return {
|
||||
type: 'Text',
|
||||
children: '\n',
|
||||
}
|
||||
}
|
||||
|
||||
if ($isTextNode(node)) {
|
||||
const isInlineCode = node.hasFormat('code')
|
||||
const isCodeNodeText = $isCodeNode(parent)
|
||||
const isBold = node.hasFormat('bold')
|
||||
const isItalic = node.hasFormat('italic')
|
||||
const isHighlight = node.hasFormat('highlight')
|
||||
|
||||
let font = isInlineCode || isCodeNodeText ? 'Courier' : 'Helvetica'
|
||||
if (isBold || isItalic) {
|
||||
font += '-'
|
||||
if (isBold) {
|
||||
font += 'Bold'
|
||||
}
|
||||
if (isItalic) {
|
||||
font += 'Oblique'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Text',
|
||||
children: node.getTextContent(),
|
||||
style: {
|
||||
fontFamily: font,
|
||||
textDecoration: node.hasFormat('underline')
|
||||
? 'underline'
|
||||
: node.hasFormat('strikethrough')
|
||||
? 'line-through'
|
||||
: undefined,
|
||||
backgroundColor: isInlineCode ? '#f1f1f1' : isHighlight ? 'rgb(255,255,0)' : undefined,
|
||||
fontSize: isInlineCode || isCodeNodeText ? 11 : undefined,
|
||||
textAlign: $isElementNode(parent) ? getNodeTextAlignment(parent) : 'left',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if ($isCodeNode(node)) {
|
||||
const children = node.getChildren()
|
||||
const lines: LexicalNode[][] = [[]]
|
||||
|
||||
for (let i = 0, currentLine = 0; i < children.length; i++) {
|
||||
const child = children[i]
|
||||
|
||||
if (!$isLineBreakNode(child)) {
|
||||
lines[currentLine].push(child)
|
||||
} else {
|
||||
lines.push([])
|
||||
currentLine++
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.column,
|
||||
{
|
||||
backgroundColor: 'rgba(0,0,0,0.05)',
|
||||
padding: 12,
|
||||
borderRadius: 6,
|
||||
fontFamily: 'Courier',
|
||||
},
|
||||
],
|
||||
children: lines.map((line) => {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [styles.row, styles.wrap],
|
||||
children: line.map((child) => {
|
||||
return getPDFDataNodeFromLexicalNode(child)
|
||||
}),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
if ($isInlineFileNode(node) || $isRemoteImageNode(node)) {
|
||||
if (!node.__src.startsWith('data:')) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: styles.block,
|
||||
children: [
|
||||
{
|
||||
type: 'Link',
|
||||
src: node.__src,
|
||||
children: node.__src,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'Image',
|
||||
src: node.__src,
|
||||
}
|
||||
}
|
||||
|
||||
const children =
|
||||
$isElementNode(node) || $isTableNode(node) || $isTableCellNode(node) || $isTableRowNode(node)
|
||||
? node.getChildren().map((child) => {
|
||||
return getPDFDataNodeFromLexicalNode(child)
|
||||
})
|
||||
: undefined
|
||||
|
||||
if ($isLinkNode(node)) {
|
||||
return {
|
||||
type: 'Link',
|
||||
src: node.getURL(),
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isListItemNode(node)) {
|
||||
if (!$isListNode(parent)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const listType = parent.getListType()
|
||||
|
||||
const isNestedList = node.getChildren().some((child) => $isListNode(child))
|
||||
|
||||
if (isNestedList) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.column,
|
||||
{
|
||||
marginLeft: 10,
|
||||
},
|
||||
],
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
return getListItemNode({
|
||||
children,
|
||||
listType,
|
||||
value: node.getValue(),
|
||||
checked: node.getChecked(),
|
||||
})
|
||||
}
|
||||
|
||||
if ($isListNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.column,
|
||||
{
|
||||
gap: 7,
|
||||
},
|
||||
],
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isCollapsibleContentNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.block,
|
||||
styles.column,
|
||||
{
|
||||
padding: 6,
|
||||
},
|
||||
],
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isCollapsibleContainerNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.column,
|
||||
{
|
||||
backgroundColor: 'rgba(0,0,0,0.05)',
|
||||
borderRadius: 6,
|
||||
},
|
||||
],
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isParagraphNode(node) && node.getTextContent().length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
if ($isTableCellNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: {
|
||||
backgroundColor: node.hasHeader() ? '#f4f5f7' : undefined,
|
||||
borderColor: '#e3e3e3',
|
||||
borderWidth: 1,
|
||||
flex: 1,
|
||||
padding: 2,
|
||||
},
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isTableRowNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: styles.row,
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isTableNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
if ($isElementNode(node)) {
|
||||
return {
|
||||
type: 'View',
|
||||
style: [
|
||||
styles.block,
|
||||
styles.row,
|
||||
styles.wrap,
|
||||
{
|
||||
fontSize: $isHeadingNode(node) ? getFontSizeForHeading(node) : undefined,
|
||||
},
|
||||
$isCollapsibleTitleNode(node) ? styles.collapsibleTitle : {},
|
||||
$isQuoteNode(node) ? styles.quote : {},
|
||||
],
|
||||
children: [
|
||||
{
|
||||
type: 'Text',
|
||||
style: {
|
||||
lineHeight: $isHeadingNode(node) ? 1 : 1.5,
|
||||
},
|
||||
children,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'View',
|
||||
style: [styles.block, styles.row, styles.wrap],
|
||||
children: [{ type: 'Text', children: node.getTextContent() }],
|
||||
}
|
||||
}
|
||||
|
||||
const getPDFDataNodesFromLexicalNodes = (nodes: LexicalNode[]): PDFDataNode[] => {
|
||||
return nodes.map(getPDFDataNodeFromLexicalNode)
|
||||
}
|
||||
|
||||
const PDFWorkerComlink = wrap<PDFWorker>(new Worker(new URL('./PDFWorker.tsx', import.meta.url)))
|
||||
|
||||
/**
|
||||
* @returns The PDF as a base64 string
|
||||
*/
|
||||
export function $generatePDFFromNodes(editor: LexicalEditor) {
|
||||
return new Promise<string>((resolve) => {
|
||||
editor.getEditorState().read(() => {
|
||||
const root = $getRoot()
|
||||
const nodes = root.getChildren()
|
||||
|
||||
const pdfDataNodes = getPDFDataNodesFromLexicalNodes(nodes)
|
||||
|
||||
void PDFWorkerComlink.renderPDF(pdfDataNodes).then((blob) => {
|
||||
void getBase64FromBlob(blob).then((base64) => {
|
||||
resolve(base64)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
Document,
|
||||
Page,
|
||||
View,
|
||||
Text,
|
||||
pdf,
|
||||
Link,
|
||||
Image,
|
||||
Svg,
|
||||
Path,
|
||||
ViewProps,
|
||||
LinkProps,
|
||||
PathProps,
|
||||
TextProps,
|
||||
SVGProps,
|
||||
ImageWithSrcProp,
|
||||
} from '@react-pdf/renderer'
|
||||
import { expose } from 'comlink'
|
||||
|
||||
export type PDFDataNode =
|
||||
| ((
|
||||
| ({
|
||||
type: 'View'
|
||||
} & Omit<ViewProps, 'children'>)
|
||||
| ({
|
||||
type: 'Text'
|
||||
} & Omit<TextProps, 'children'>)
|
||||
| ({
|
||||
type: 'Link'
|
||||
} & Omit<LinkProps, 'children'>)
|
||||
| ({
|
||||
type: 'Image'
|
||||
} & Omit<ImageWithSrcProp, 'children'>)
|
||||
| ({
|
||||
type: 'Svg'
|
||||
} & Omit<SVGProps, 'children'>)
|
||||
| ({
|
||||
type: 'Path'
|
||||
} & Omit<PathProps, 'children'>)
|
||||
) & {
|
||||
children?: PDFDataNode[] | string
|
||||
})
|
||||
| null
|
||||
|
||||
const Node = ({ node }: { node: PDFDataNode }) => {
|
||||
if (!node) {
|
||||
return null
|
||||
}
|
||||
|
||||
const children =
|
||||
typeof node.children === 'string'
|
||||
? node.children
|
||||
: node.children?.map((child, index) => {
|
||||
return <Node node={child} key={index} />
|
||||
})
|
||||
|
||||
switch (node.type) {
|
||||
case 'View':
|
||||
return <View {...node}>{children}</View>
|
||||
case 'Text':
|
||||
return <Text {...node}>{children}</Text>
|
||||
case 'Link':
|
||||
return <Link {...node}>{children}</Link>
|
||||
case 'Image':
|
||||
return <Image {...node} />
|
||||
case 'Svg':
|
||||
return <Svg {...node}>{children}</Svg>
|
||||
case 'Path': {
|
||||
const { children: _, ...props } = node
|
||||
return <Path {...props} />
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PDFDocument = ({ nodes }: { nodes: PDFDataNode[] }) => {
|
||||
return (
|
||||
<Document>
|
||||
<Page
|
||||
style={{
|
||||
paddingVertical: 35,
|
||||
paddingHorizontal: 35,
|
||||
lineHeight: 1.5,
|
||||
fontSize: 12,
|
||||
gap: 14,
|
||||
}}
|
||||
>
|
||||
{nodes.map((node, index) => {
|
||||
return <Node node={node} key={index} />
|
||||
})}
|
||||
</Page>
|
||||
</Document>
|
||||
)
|
||||
}
|
||||
|
||||
const renderPDF = (nodes: PDFDataNode[]) => {
|
||||
return pdf(<PDFDocument nodes={nodes} />).toBlob()
|
||||
}
|
||||
|
||||
expose({
|
||||
renderPDF,
|
||||
})
|
||||
|
||||
export type PDFWorker = {
|
||||
renderPDF: typeof renderPDF
|
||||
}
|
||||
+114
-112
@@ -12,7 +12,6 @@ import { classNames } from '@standardnotes/snjs'
|
||||
import Icon from '@/Components/Icon/Icon'
|
||||
import StyledTooltip from '@/Components/StyledTooltip/StyledTooltip'
|
||||
import { TOGGLE_LINK_COMMAND } from '@lexical/link'
|
||||
import Portal from '@/Components/Portal/Portal'
|
||||
import { mergeRegister } from '@lexical/utils'
|
||||
import { KeyboardKey } from '@standardnotes/ui-services'
|
||||
import Button from '@/Components/Button/Button'
|
||||
@@ -20,6 +19,9 @@ import { sanitizeUrl } from '../../Lexical/Utils/sanitizeUrl'
|
||||
import { getSelectedNode } from '../../Lexical/Utils/getSelectedNode'
|
||||
import { $isLinkTextNode } from './ToolbarLinkTextEditor'
|
||||
import { useElementResize } from '@/Hooks/useElementRect'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { ElementIds } from '@/Constants/ElementIDs'
|
||||
import { getAdjustedStylesForNonPortalPopover } from '@/Components/Popover/Utils/getAdjustedStylesForNonPortal'
|
||||
|
||||
const FloatingLinkEditor = ({
|
||||
linkUrl,
|
||||
@@ -90,7 +92,8 @@ const FloatingLinkEditor = ({
|
||||
maxHeightFunction: () => 'none',
|
||||
})
|
||||
if (calculatedStyles) {
|
||||
Object.entries(calculatedStyles).forEach(([key, value]) => {
|
||||
const adjustedStyles = getAdjustedStylesForNonPortalPopover(linkEditorElement, calculatedStyles)
|
||||
Object.entries(adjustedStyles).forEach(([key, value]) => {
|
||||
linkEditorElement.style.setProperty(key, value)
|
||||
})
|
||||
linkEditorElement.style.opacity = '1'
|
||||
@@ -145,50 +148,28 @@ const FloatingLinkEditor = ({
|
||||
setTimeout(updateLinkEditorPosition)
|
||||
}, [isEditMode, updateLinkEditorPosition])
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<div
|
||||
id="super-link-editor"
|
||||
className="absolute bottom-12 left-1/2 z-modal w-[calc(100%_-_1rem)] -translate-x-1/2 rounded-lg border border-border bg-contrast px-2 py-1 shadow-sm shadow-contrast translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)] md:bottom-[unset] md:left-0 md:top-0 md:w-auto md:translate-x-0 md:opacity-0"
|
||||
ref={linkEditorRef}
|
||||
>
|
||||
{isEditMode ? (
|
||||
<div
|
||||
className="flex flex-col gap-2 py-1"
|
||||
onBlur={(event) => {
|
||||
if (!linkEditorRef.current?.contains(event.relatedTarget as Node)) {
|
||||
setEditMode(false)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isLinkText && (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Icon type="plain-text" className="flex-shrink-0" />
|
||||
<input
|
||||
value={editedLinkText}
|
||||
onChange={(event) => {
|
||||
setEditedLinkText(event.target.value)
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === KeyboardKey.Enter) {
|
||||
event.preventDefault()
|
||||
handleSubmission()
|
||||
} else if (event.key === KeyboardKey.Escape) {
|
||||
event.preventDefault()
|
||||
setEditMode(false)
|
||||
}
|
||||
}}
|
||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[20ch]"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
return createPortal(
|
||||
<div
|
||||
id="super-link-editor"
|
||||
className="absolute bottom-12 left-1/2 z-modal w-[calc(100%_-_1rem)] -translate-x-1/2 rounded-lg border border-border bg-contrast px-2 py-1 shadow-sm shadow-contrast translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)] md:bottom-[unset] md:left-0 md:top-0 md:w-auto md:translate-x-0 md:opacity-0"
|
||||
ref={linkEditorRef}
|
||||
>
|
||||
{isEditMode ? (
|
||||
<div
|
||||
className="flex flex-col gap-2 py-1"
|
||||
onBlur={(event) => {
|
||||
if (!linkEditorRef.current?.contains(event.relatedTarget as Node)) {
|
||||
setEditMode(false)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isLinkText && (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Icon type="link" className="flex-shrink-0" />
|
||||
<Icon type="plain-text" className="flex-shrink-0" />
|
||||
<input
|
||||
ref={focusInput}
|
||||
value={editedLinkUrl}
|
||||
value={editedLinkText}
|
||||
onChange={(event) => {
|
||||
setEditedLinkUrl(event.target.value)
|
||||
setEditedLinkText(event.target.value)
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === KeyboardKey.Enter) {
|
||||
@@ -199,84 +180,105 @@ const FloatingLinkEditor = ({
|
||||
setEditMode(false)
|
||||
}
|
||||
}}
|
||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[40ch]"
|
||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[20ch]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-1.5">
|
||||
<StyledTooltip showOnMobile showOnHover label="Cancel editing">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setEditMode(false)
|
||||
editor.focus()
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</StyledTooltip>
|
||||
<StyledTooltip showOnMobile showOnHover label="Save link">
|
||||
<Button primary onClick={handleSubmission} onMouseDown={(event) => event.preventDefault()}>
|
||||
Apply
|
||||
</Button>
|
||||
</StyledTooltip>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Icon type="link" className="flex-shrink-0" />
|
||||
<input
|
||||
ref={focusInput}
|
||||
value={editedLinkUrl}
|
||||
onChange={(event) => {
|
||||
setEditedLinkUrl(event.target.value)
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === KeyboardKey.Enter) {
|
||||
event.preventDefault()
|
||||
handleSubmission()
|
||||
} else if (event.key === KeyboardKey.Escape) {
|
||||
event.preventDefault()
|
||||
setEditMode(false)
|
||||
}
|
||||
}}
|
||||
className="flex-grow rounded-sm bg-contrast p-1 text-text sm:min-w-[40ch]"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<a
|
||||
className={classNames(
|
||||
'mr-1 flex flex-grow items-center gap-2 overflow-hidden whitespace-nowrap underline',
|
||||
isAutoLink && 'py-2.5',
|
||||
)}
|
||||
href={linkUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Icon type="open-in" className="ml-1 flex-shrink-0" />
|
||||
<div className="max-w-[35ch] overflow-hidden text-ellipsis">{linkUrl}</div>
|
||||
</a>
|
||||
<StyledTooltip showOnMobile showOnHover label="Copy link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
<div className="flex items-center justify-end gap-1.5">
|
||||
<StyledTooltip showOnMobile showOnHover label="Cancel editing">
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(linkUrl).catch(console.error)
|
||||
setEditMode(false)
|
||||
editor.focus()
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="copy" size="medium" />
|
||||
</button>
|
||||
Cancel
|
||||
</Button>
|
||||
</StyledTooltip>
|
||||
<StyledTooltip showOnMobile showOnHover label="Save link">
|
||||
<Button primary onClick={handleSubmission} onMouseDown={(event) => event.preventDefault()}>
|
||||
Apply
|
||||
</Button>
|
||||
</StyledTooltip>
|
||||
{!isAutoLink && (
|
||||
<>
|
||||
<StyledTooltip showOnMobile showOnHover label="Edit link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
onClick={() => {
|
||||
setEditedLinkUrl(linkUrl)
|
||||
setEditMode(true)
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="pencil-filled" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
<StyledTooltip showOnMobile showOnHover label="Remove link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="trash-filled" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Portal>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1">
|
||||
<a
|
||||
className={classNames(
|
||||
'mr-1 flex flex-grow items-center gap-2 overflow-hidden whitespace-nowrap underline',
|
||||
isAutoLink && 'py-2.5',
|
||||
)}
|
||||
href={linkUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Icon type="open-in" className="ml-1 flex-shrink-0" />
|
||||
<div className="max-w-[35ch] overflow-hidden text-ellipsis">{linkUrl}</div>
|
||||
</a>
|
||||
<StyledTooltip showOnMobile showOnHover label="Copy link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(linkUrl).catch(console.error)
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="copy" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
{!isAutoLink && (
|
||||
<>
|
||||
<StyledTooltip showOnMobile showOnHover label="Edit link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
onClick={() => {
|
||||
setEditedLinkUrl(linkUrl)
|
||||
setEditMode(true)
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="pencil-filled" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
<StyledTooltip showOnMobile showOnHover label="Remove link">
|
||||
<button
|
||||
className="flex select-none items-center justify-center rounded p-2 enabled:hover:bg-default disabled:opacity-50 md:border md:border-transparent enabled:hover:md:translucent-ui:border-[--popover-border-color]"
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null)
|
||||
}}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
>
|
||||
<Icon type="trash-filled" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>,
|
||||
document.getElementById(ElementIds.SuperEditor) ?? document.body,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+40
-24
@@ -18,6 +18,7 @@ import { $createFileExportNode } from '../Lexical/Nodes/FileExportNode'
|
||||
import { $createInlineFileNode } from '../Plugins/InlineFilePlugin/InlineFileNode'
|
||||
import { $convertFromMarkdownString } from '../Lexical/Utils/MarkdownImport'
|
||||
import { $convertToMarkdownString } from '../Lexical/Utils/MarkdownExport'
|
||||
|
||||
export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
private importEditor: LexicalEditor
|
||||
private exportEditor: LexicalEditor
|
||||
@@ -50,7 +51,7 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
|
||||
async convertSuperStringToOtherFormat(
|
||||
superString: string,
|
||||
toFormat: 'txt' | 'md' | 'html' | 'json',
|
||||
toFormat: 'txt' | 'md' | 'html' | 'json' | 'pdf',
|
||||
config?: {
|
||||
embedBehavior?: PrefValue[PrefKey.SuperNoteExportEmbedBehavior]
|
||||
getFileItem?: (id: string) => FileItem | undefined
|
||||
@@ -92,7 +93,8 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
if (!fileItem) {
|
||||
return
|
||||
}
|
||||
if (embedBehavior === 'inline' && getFileBase64) {
|
||||
const canInlineFileType = toFormat === 'pdf' ? fileItem.mimeType.startsWith('image/') : true
|
||||
if (embedBehavior === 'inline' && getFileBase64 && canInlineFileType) {
|
||||
const fileBase64 = await getFileBase64(fileNode.getId())
|
||||
if (!fileBase64) {
|
||||
return
|
||||
@@ -122,31 +124,45 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
)
|
||||
})
|
||||
|
||||
this.exportEditor.update(
|
||||
() => {
|
||||
switch (toFormat) {
|
||||
case 'txt':
|
||||
case 'md': {
|
||||
const paragraphs = $nodesOfType(ParagraphNode)
|
||||
for (const paragraph of paragraphs) {
|
||||
if (paragraph.isEmpty()) {
|
||||
paragraph.remove()
|
||||
await new Promise<void>((resolve) => {
|
||||
this.exportEditor.update(
|
||||
() => {
|
||||
switch (toFormat) {
|
||||
case 'txt':
|
||||
case 'md': {
|
||||
const paragraphs = $nodesOfType(ParagraphNode)
|
||||
for (const paragraph of paragraphs) {
|
||||
if (paragraph.isEmpty()) {
|
||||
paragraph.remove()
|
||||
}
|
||||
}
|
||||
content = $convertToMarkdownString(MarkdownTransformers)
|
||||
resolve()
|
||||
break
|
||||
}
|
||||
content = $convertToMarkdownString(MarkdownTransformers)
|
||||
break
|
||||
case 'html':
|
||||
content = $generateHtmlFromNodes(this.exportEditor)
|
||||
resolve()
|
||||
break
|
||||
case 'pdf': {
|
||||
void import('../Lexical/Utils/PDFExport/PDFExport').then(({ $generatePDFFromNodes }) => {
|
||||
void $generatePDFFromNodes(this.exportEditor).then((pdf) => {
|
||||
content = pdf
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'json':
|
||||
default:
|
||||
content = superString
|
||||
resolve()
|
||||
break
|
||||
}
|
||||
case 'html':
|
||||
content = $generateHtmlFromNodes(this.exportEditor)
|
||||
break
|
||||
case 'json':
|
||||
default:
|
||||
content = superString
|
||||
break
|
||||
}
|
||||
},
|
||||
{ discrete: true },
|
||||
)
|
||||
},
|
||||
{ discrete: true },
|
||||
)
|
||||
})
|
||||
|
||||
if (typeof content !== 'string') {
|
||||
throw new Error('Could not export note')
|
||||
|
||||
@@ -77,6 +77,9 @@ export const getNoteBlob = async (
|
||||
case 'md':
|
||||
type = 'text/markdown'
|
||||
break
|
||||
case 'pdf':
|
||||
type = 'application/pdf'
|
||||
break
|
||||
default:
|
||||
type = 'text/plain'
|
||||
break
|
||||
@@ -103,11 +106,15 @@ export const getNoteBlob = async (
|
||||
PrefKey.SuperNoteExportUseMDFrontmatter,
|
||||
PrefDefaults[PrefKey.SuperNoteExportUseMDFrontmatter],
|
||||
)
|
||||
// result is a data url string if format is pdf
|
||||
const result =
|
||||
format === 'html' ? superHTML(note, content) : useMDFrontmatter ? superMarkdown(note, content) : content
|
||||
const blob = new Blob([result], {
|
||||
type,
|
||||
})
|
||||
const blob =
|
||||
format === 'pdf'
|
||||
? await fetch(result).then((res) => res.blob())
|
||||
: new Blob([result], {
|
||||
type,
|
||||
})
|
||||
return blob
|
||||
}
|
||||
const blob = new Blob([note.text], {
|
||||
@@ -132,7 +139,7 @@ const noteRequiresFolder = (
|
||||
if (!isSuperNote(note)) {
|
||||
return false
|
||||
}
|
||||
if (superExportFormat === 'json') {
|
||||
if (superExportFormat === 'json' || superExportFormat === 'pdf') {
|
||||
return false
|
||||
}
|
||||
if (superEmbedBehavior !== 'separate') {
|
||||
@@ -178,10 +185,13 @@ export const createNoteExport = async (
|
||||
PrefKey.SuperNoteExportFormat,
|
||||
PrefDefaults[PrefKey.SuperNoteExportFormat],
|
||||
)
|
||||
const superEmbedBehaviorPref = application.getPreference(
|
||||
PrefKey.SuperNoteExportEmbedBehavior,
|
||||
PrefDefaults[PrefKey.SuperNoteExportEmbedBehavior],
|
||||
)
|
||||
const superEmbedBehaviorPref =
|
||||
superExportFormatPref === 'pdf'
|
||||
? 'inline'
|
||||
: application.getPreference(
|
||||
PrefKey.SuperNoteExportEmbedBehavior,
|
||||
PrefDefaults[PrefKey.SuperNoteExportEmbedBehavior],
|
||||
)
|
||||
|
||||
if (notes.length === 1 && !noteRequiresFolder(notes[0], superExportFormatPref, superEmbedBehaviorPref)) {
|
||||
const blob = await getNoteBlob(application, notes[0], superEmbedBehaviorPref)
|
||||
|
||||
@@ -82,6 +82,7 @@ module.exports = (env) => {
|
||||
crypto: false,
|
||||
path: false,
|
||||
url: false,
|
||||
fs: false,
|
||||
},
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src/javascripts'),
|
||||
@@ -97,7 +98,8 @@ module.exports = (env) => {
|
||||
* Exclude all node_modules, except for those we need to run through our babel rules because
|
||||
* they may contain class properties and other ES6+ syntax.
|
||||
*/
|
||||
exclude: /node_modules\/(?!(@standardnotes\/common|@standardnotes\/domain-core|webextension-polyfill))/,
|
||||
exclude:
|
||||
/node_modules\/(?!(@standardnotes\/common|@standardnotes\/domain-core|webextension-polyfill|yoga-layout))/,
|
||||
use: [
|
||||
'babel-loader',
|
||||
{
|
||||
|
||||
@@ -2478,6 +2478,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.20.13":
|
||||
version: 7.23.8
|
||||
resolution: "@babel/runtime@npm:7.23.8"
|
||||
dependencies:
|
||||
regenerator-runtime: ^0.14.0
|
||||
checksum: 0bd5543c26811153822a9f382fd39886f66825ff2a397a19008011376533747cd05c33a91f6248c0b8b0edf0448d7c167ebfba34786088f1b7eb11c65be7dfc3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.21.0":
|
||||
version: 7.23.4
|
||||
resolution: "@babel/runtime@npm:7.23.4"
|
||||
@@ -5655,6 +5664,165 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/fns@npm:2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "@react-pdf/fns@npm:2.1.0"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
checksum: b7360daa769971ffa4cf8c45d953a30bd35c33fdaf03b9ef5bf3ab5f82d6b46f2450b061019aeabc6309024cae4a83333b08656aa79d1a11f962c656ca74487f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/font@npm:^2.4.2":
|
||||
version: 2.4.2
|
||||
resolution: "@react-pdf/font@npm:2.4.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/types": ^2.4.0
|
||||
cross-fetch: ^3.1.5
|
||||
fontkit: ^2.0.2
|
||||
is-url: ^1.2.4
|
||||
checksum: 910f7422f278a1a5c6374d746c70d416c8d172004fbc0e8acdf828e1dfd727f0ac70d4505f334886c74b25fd7d46acc1d8b1c178f84aae39714fff989c853369
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/image@npm:^2.3.1":
|
||||
version: 2.3.1
|
||||
resolution: "@react-pdf/image@npm:2.3.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/png-js": ^2.3.0
|
||||
cross-fetch: ^3.1.5
|
||||
jpeg-exif: ^1.1.4
|
||||
checksum: 7e8bb017a548df5d104af567f692e345f19a89c9a626e1630c71155b1055ef93445b12576074b05f628cfb48037efe8e9c9e04e7fc74b97d13172fb80deb2938
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/layout@npm:^3.10.2":
|
||||
version: 3.10.2
|
||||
resolution: "@react-pdf/layout@npm:3.10.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/fns": 2.1.0
|
||||
"@react-pdf/image": ^2.3.1
|
||||
"@react-pdf/pdfkit": ^3.1.1
|
||||
"@react-pdf/primitives": ^3.1.1
|
||||
"@react-pdf/stylesheet": ^4.2.2
|
||||
"@react-pdf/textkit": ^4.3.0
|
||||
"@react-pdf/types": ^2.4.0
|
||||
cross-fetch: ^3.1.5
|
||||
emoji-regex: ^10.3.0
|
||||
queue: ^6.0.1
|
||||
yoga-layout: ^2.0.1
|
||||
checksum: 356e3e611d5913fa780605e3301b6939a50b2f4671163da5a5aff78d2ef666b2cc34b091913a0a98edc3559cb65cf0c49c5463827ad4f54b38c8ec7f67a0371d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/pdfkit@npm:^3.1.1":
|
||||
version: 3.1.1
|
||||
resolution: "@react-pdf/pdfkit@npm:3.1.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/png-js": ^2.3.0
|
||||
browserify-zlib: ^0.2.0
|
||||
crypto-js: ^4.2.0
|
||||
fontkit: ^2.0.2
|
||||
jpeg-exif: ^1.1.4
|
||||
vite-compatible-readable-stream: ^3.6.1
|
||||
checksum: 34e10401c56dcee4a85230466672ad695b856ddb5202dba2606c86dce451f2dd9a2056e75385bce91f645f6e6110ec2b8800a592e9ff66422e69d18457a87a20
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/png-js@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "@react-pdf/png-js@npm:2.3.0"
|
||||
dependencies:
|
||||
browserify-zlib: ^0.2.0
|
||||
checksum: 34f03fa5b97fc78bfe636d768ebb19cebedf391369b8b2572590379c4aadeac135b871893f0af486cd6c410ead32b09a31d08f53a1c4a7460a7a25460c9ff140
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/primitives@npm:^3.1.1":
|
||||
version: 3.1.1
|
||||
resolution: "@react-pdf/primitives@npm:3.1.1"
|
||||
checksum: a52c0cfff74d29d36e2e4c1c2b8935faf2f13bbe3800901e93354ea044385d8716166e45f3a49bb729e6d9944d7a8239056f5af80b345cb2984e245b2e719c1d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/render@npm:^3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "@react-pdf/render@npm:3.4.0"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/fns": 2.1.0
|
||||
"@react-pdf/primitives": ^3.1.1
|
||||
"@react-pdf/textkit": ^4.3.0
|
||||
"@react-pdf/types": ^2.4.0
|
||||
abs-svg-path: ^0.1.1
|
||||
color-string: ^1.9.1
|
||||
normalize-svg-path: ^1.1.0
|
||||
parse-svg-path: ^0.1.2
|
||||
svg-arc-to-cubic-bezier: ^3.2.0
|
||||
checksum: 48f19f6be45d48da50ee1d9f5994cda17cb74add7d14d740689d1148d57e29e4c895770b630213b23e7df25f9d0439f6d0caaba1c303d38a51a3d57394d25db7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/renderer@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "@react-pdf/renderer@npm:3.3.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/font": ^2.4.2
|
||||
"@react-pdf/layout": ^3.10.2
|
||||
"@react-pdf/pdfkit": ^3.1.1
|
||||
"@react-pdf/primitives": ^3.1.1
|
||||
"@react-pdf/render": ^3.4.0
|
||||
"@react-pdf/types": ^2.4.0
|
||||
events: ^3.3.0
|
||||
object-assign: ^4.1.1
|
||||
prop-types: ^15.6.2
|
||||
queue: ^6.0.1
|
||||
scheduler: ^0.17.0
|
||||
peerDependencies:
|
||||
react: ^16.8.6 || ^17.0.0 || ^18.0.0
|
||||
checksum: 4bc9286a739d2626a0b26e9edb31bf8a196f18b3d93c0901bb33e471fd8bc0055a79a530271c34b1eb127fd4053bd8b001ec56623f660cb0628f098bff4c9c71
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/stylesheet@npm:^4.2.2":
|
||||
version: 4.2.2
|
||||
resolution: "@react-pdf/stylesheet@npm:4.2.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/fns": 2.1.0
|
||||
"@react-pdf/types": ^2.4.0
|
||||
color-string: ^1.9.1
|
||||
hsl-to-hex: ^1.0.0
|
||||
media-engine: ^1.0.3
|
||||
postcss-value-parser: ^4.1.0
|
||||
checksum: f6ce9ecc0c03591563a69c8d1a28fcb56227e7b746913cfe6fa5e205cafedc98328636779ef9f1974cc77222bdbf2966f3d81178df52039595a746d892013a8e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/textkit@npm:^4.3.0":
|
||||
version: 4.3.0
|
||||
resolution: "@react-pdf/textkit@npm:4.3.0"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.20.13
|
||||
"@react-pdf/fns": 2.1.0
|
||||
hyphen: ^1.6.4
|
||||
unicode-properties: ^1.4.1
|
||||
checksum: d4ce3e405160be1337241580cb0043f1b2117accfe5850e84d813a07c5c0d2cc106bed6c9c70fd1eff324c1fd7f8bf276ef314fe39addde5c9eb986130267e62
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-pdf/types@npm:^2.4.0":
|
||||
version: 2.4.0
|
||||
resolution: "@react-pdf/types@npm:2.4.0"
|
||||
checksum: a9b826753c8ffdf9a812e7169e5c827451aff62c73269f1251275927edd07f9444cdddbdc8afa426df74996725189ce3ac7987df45d8089a42cb68b549fdfb6e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sideway/address@npm:^4.1.3":
|
||||
version: 4.1.4
|
||||
resolution: "@sideway/address@npm:4.1.4"
|
||||
@@ -7502,6 +7670,7 @@ __metadata:
|
||||
"@lexical/react": 0.12.6
|
||||
"@pmmmwh/react-refresh-webpack-plugin": ^0.5.10
|
||||
"@radix-ui/react-slot": ^1.0.1
|
||||
"@react-pdf/renderer": ^3.3.2
|
||||
"@simplewebauthn/browser": ^8.0.2
|
||||
"@standardnotes/authenticator": ^2.4.0
|
||||
"@standardnotes/autobiography-theme": ^1.2.7
|
||||
@@ -7536,6 +7705,7 @@ __metadata:
|
||||
autoprefixer: ^10.4.13
|
||||
babel-loader: ^9.1.2
|
||||
circular-dependency-plugin: ^5.2.2
|
||||
comlink: ^4.4.1
|
||||
copy-webpack-plugin: ^11.0.0
|
||||
css-loader: "*"
|
||||
dayjs: ^1.11.9
|
||||
@@ -7734,6 +7904,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/helpers@npm:^0.4.2":
|
||||
version: 0.4.36
|
||||
resolution: "@swc/helpers@npm:0.4.36"
|
||||
dependencies:
|
||||
legacy-swc-helpers: "npm:@swc/helpers@=0.4.14"
|
||||
tslib: ^2.4.0
|
||||
checksum: 20b9f021a9711633d709ef1c231423eb079cb7ed14ad191dc9583b0b46684a95d0e87c3efd7472e7673ddbd30eb200c21490ab43ad251df8f845cd09df3d236f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@szmarczak/http-timer@npm:^4.0.5":
|
||||
version: 4.0.6
|
||||
resolution: "@szmarczak/http-timer@npm:4.0.6"
|
||||
@@ -9033,6 +9213,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"abs-svg-path@npm:^0.1.1":
|
||||
version: 0.1.1
|
||||
resolution: "abs-svg-path@npm:0.1.1"
|
||||
checksum: af1a167c09e8bdb76c80adca7333f3d828e5b50e37b9702aa03675e271919e7b1eeaa35cce939970ecba14769953b7465ea34c2129ab683ddff9d973a07f164f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"accepts@npm:^1.3.7, accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.7, accepts@npm:~1.3.8":
|
||||
version: 1.3.8
|
||||
resolution: "accepts@npm:1.3.8"
|
||||
@@ -10201,7 +10388,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-js@npm:^1.1.2, base64-js@npm:^1.2.3, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
|
||||
"base64-js@npm:^1.1.2, base64-js@npm:^1.2.3, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
|
||||
version: 1.5.1
|
||||
resolution: "base64-js@npm:1.5.1"
|
||||
checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005
|
||||
@@ -10462,6 +10649,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"brotli@npm:^1.3.2":
|
||||
version: 1.3.3
|
||||
resolution: "brotli@npm:1.3.3"
|
||||
dependencies:
|
||||
base64-js: ^1.1.2
|
||||
checksum: 2c97329f4ccb8e4332cedd2f63b85c2e15ffb305b1cbf046df86201434caf93cb7992ca73c0f7053b6a1417f595069ec7783c26e01510cefc10035a0f466e594
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browser-process-hrtime@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "browser-process-hrtime@npm:1.0.0"
|
||||
@@ -10469,6 +10665,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browserify-zlib@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "browserify-zlib@npm:0.2.0"
|
||||
dependencies:
|
||||
pako: ~1.0.5
|
||||
checksum: 5cd9d6a665190fedb4a97dfbad8dabc8698d8a507298a03f42c734e96d58ca35d3c7d4085e283440bbca1cd1938cff85031728079bedb3345310c58ab1ec92d6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browserslist@npm:^4.14.5, browserslist@npm:^4.21.5, browserslist@npm:^4.21.9":
|
||||
version: 4.21.9
|
||||
resolution: "browserslist@npm:4.21.9"
|
||||
@@ -11409,6 +11614,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clone@npm:^2.1.2":
|
||||
version: 2.1.2
|
||||
resolution: "clone@npm:2.1.2"
|
||||
checksum: aaf106e9bc025b21333e2f4c12da539b568db4925c0501a1bf4070836c9e848c892fa22c35548ce0d1132b08bbbfa17a00144fe58fccdab6fa900fec4250f67d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cluster-key-slot@npm:^1.1.0":
|
||||
version: 1.1.2
|
||||
resolution: "cluster-key-slot@npm:1.1.2"
|
||||
@@ -11488,7 +11700,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"color-string@npm:^1.6.0":
|
||||
"color-string@npm:^1.6.0, color-string@npm:^1.9.1":
|
||||
version: 1.9.1
|
||||
resolution: "color-string@npm:1.9.1"
|
||||
dependencies:
|
||||
@@ -11567,6 +11779,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"comlink@npm:^4.4.1":
|
||||
version: 4.4.1
|
||||
resolution: "comlink@npm:4.4.1"
|
||||
checksum: 16d58a8f590087fc45432e31d6c138308dfd4b75b89aec0b7f7bb97ad33d810381bd2b1e608a1fb2cf05979af9cbfcdcaf1715996d5fcf77aeb013b6da3260af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"command-exists@npm:^1.2.8":
|
||||
version: 1.2.9
|
||||
resolution: "command-exists@npm:1.2.9"
|
||||
@@ -12155,6 +12374,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-fetch@npm:^3.1.5":
|
||||
version: 3.1.8
|
||||
resolution: "cross-fetch@npm:3.1.8"
|
||||
dependencies:
|
||||
node-fetch: ^2.6.12
|
||||
checksum: 78f993fa099eaaa041122ab037fe9503ecbbcb9daef234d1d2e0b9230a983f64d645d088c464e21a247b825a08dc444a6e7064adfa93536d3a9454b4745b3632
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-fetch@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "cross-fetch@npm:4.0.0"
|
||||
@@ -12192,6 +12420,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"crypto-js@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "crypto-js@npm:4.2.0"
|
||||
checksum: f051666dbc077c8324777f44fbd3aaea2986f198fe85092535130d17026c7c2ccf2d23ee5b29b36f7a4a07312db2fae23c9094b644cc35f7858b1b4fcaf27774
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"crypto-random-string@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "crypto-random-string@npm:4.0.0"
|
||||
@@ -12801,6 +13036,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dfa@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "dfa@npm:1.2.0"
|
||||
checksum: 83b954b856a4a0c4282550a35532ac66dfc6362a08500a4b09c0d7a306c6813cbf50cc18d81bf8997d98559fc2675df89f6ece255d92517cc46f6bf8ef5ff727
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"didyoumean@npm:^1.2.2":
|
||||
version: 1.2.2
|
||||
resolution: "didyoumean@npm:1.2.2"
|
||||
@@ -13281,6 +13523,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"emoji-regex@npm:^10.3.0":
|
||||
version: 10.3.0
|
||||
resolution: "emoji-regex@npm:10.3.0"
|
||||
checksum: 5da48edfeb9462fb1ae5495cff2d79129974c696853fb0ce952cbf560f29a2756825433bf51cfd5157ec7b9f93f46f31d712e896d63e3d8ac9c3832bdb45ab73
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"emoji-regex@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "emoji-regex@npm:8.0.0"
|
||||
@@ -14781,6 +15030,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fontkit@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "fontkit@npm:2.0.2"
|
||||
dependencies:
|
||||
"@swc/helpers": ^0.4.2
|
||||
brotli: ^1.3.2
|
||||
clone: ^2.1.2
|
||||
dfa: ^1.2.0
|
||||
fast-deep-equal: ^3.1.3
|
||||
restructure: ^3.0.0
|
||||
tiny-inflate: ^1.0.3
|
||||
unicode-properties: ^1.4.0
|
||||
unicode-trie: ^2.0.0
|
||||
checksum: ef5841a46cb46af56496646136a4e61f014360caacb8d69e3a4abfda9d89d66d2a68b0855494c070c4e0675fb57724c9db37154913413609ebb065d35b23838e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"for-each@npm:^0.3.3":
|
||||
version: 0.3.3
|
||||
resolution: "for-each@npm:0.3.3"
|
||||
@@ -15954,6 +16220,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hsl-to-hex@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "hsl-to-hex@npm:1.0.0"
|
||||
dependencies:
|
||||
hsl-to-rgb-for-reals: ^1.1.0
|
||||
checksum: e748cea0d9cdf444727bd3fc3f62515d0c5806ad4b52850730d365e54f6f0ae1e41e2076ab17de8523ab5ebdd30c62323f26b2cdd383529755ad27d1a33965b8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hsl-to-rgb-for-reals@npm:^1.1.0":
|
||||
version: 1.1.1
|
||||
resolution: "hsl-to-rgb-for-reals@npm:1.1.1"
|
||||
checksum: b31452617e6c399509c5b8016999d659f9e347e71290da287bf0f536da031609d51b240535dc8eb3dbd7770a7b367d9896ab6a13794db7d16e4cf86e363e156f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"html-encoding-sniffer@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "html-encoding-sniffer@npm:3.0.0"
|
||||
@@ -16208,6 +16490,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hyphen@npm:^1.6.4":
|
||||
version: 1.10.4
|
||||
resolution: "hyphen@npm:1.10.4"
|
||||
checksum: 94446608a00f62c102fe272d443d0985a41ec1f6f5f606f21a0d454687f269b0a7c4b65988bef77a7c53e64ebc32b7388ea76333426f87eaa57118dae6ea4e51
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-corefoundation@npm:^1.1.7":
|
||||
version: 1.1.7
|
||||
resolution: "iconv-corefoundation@npm:1.1.7"
|
||||
@@ -17097,6 +17386,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-url@npm:^1.2.4":
|
||||
version: 1.2.4
|
||||
resolution: "is-url@npm:1.2.4"
|
||||
checksum: 100e74b3b1feab87a43ef7653736e88d997eb7bd32e71fd3ebc413e58c1cbe56269699c776aaea84244b0567f2a7d68dfaa512a062293ed2f9fdecb394148432
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-utf8@npm:^0.2.1":
|
||||
version: 0.2.1
|
||||
resolution: "is-utf8@npm:0.2.1"
|
||||
@@ -17844,6 +18140,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jpeg-exif@npm:^1.1.4":
|
||||
version: 1.1.4
|
||||
resolution: "jpeg-exif@npm:1.1.4"
|
||||
checksum: a8693a7eeb6c6572ca39acc8bbaf4bac1eea1331a26ec7d460410c0c7aefcb944bbc6c31d3c4649a308eea9da89ee4d38e35fe2f2604e4bf2ed09abd600cff0b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-base64@npm:^2.4.9":
|
||||
version: 2.6.4
|
||||
resolution: "js-base64@npm:2.6.4"
|
||||
@@ -18395,6 +18698,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"legacy-swc-helpers@npm:@swc/helpers@=0.4.14":
|
||||
version: 0.4.14
|
||||
resolution: "@swc/helpers@npm:0.4.14"
|
||||
dependencies:
|
||||
tslib: ^2.4.0
|
||||
checksum: 273fd3f3fc461a92f3790cc551ea054745c6d6959afbe1232e6d7aa1c722bbc114d308aab96bef5c78fc0303c85c7b472ef00e2253251cc89737f3b1af56e5a5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"leven@npm:^3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "leven@npm:3.1.0"
|
||||
@@ -19194,6 +19506,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"media-engine@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "media-engine@npm:1.0.3"
|
||||
checksum: 3c2834077e7223d95cc137e4d13f777750887748a04b3aa29d1abfb05b35ad483ea074b7798827aedc29a6a6f6da299c5822d1ce99414d6c9c81b4299dbbd85a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"media-typer@npm:0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "media-typer@npm:0.3.0"
|
||||
@@ -20747,6 +21066,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"normalize-svg-path@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "normalize-svg-path@npm:1.1.0"
|
||||
dependencies:
|
||||
svg-arc-to-cubic-bezier: ^3.0.0
|
||||
checksum: 106e108b2f99e9e222a1c6edfc859523c6c3c2b0a6ba64743ed08af120b23b9bc2c16682bc2ae043a24c011c34c8252376c68525cf11735c6f110b571740eb2e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"normalize-url@npm:^6.0.1":
|
||||
version: 6.1.0
|
||||
resolution: "normalize-url@npm:6.1.0"
|
||||
@@ -21520,7 +21848,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pako@npm:~1.0.2":
|
||||
"pako@npm:^0.2.5":
|
||||
version: 0.2.9
|
||||
resolution: "pako@npm:0.2.9"
|
||||
checksum: 055f9487cd57fbb78df84315873bbdd089ba286f3499daed47d2effdc6253e981f5db6898c23486de76d4a781559f890d643bd3a49f70f1b4a18019c98aa5125
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pako@npm:~1.0.2, pako@npm:~1.0.5":
|
||||
version: 1.0.11
|
||||
resolution: "pako@npm:1.0.11"
|
||||
checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16
|
||||
@@ -21616,6 +21951,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parse-svg-path@npm:^0.1.2":
|
||||
version: 0.1.2
|
||||
resolution: "parse-svg-path@npm:0.1.2"
|
||||
checksum: bba7d4b4207fcc9eaf553b0d34db96ea8a1173635bc94528b5b66e1581902d4792d8d6229103764f01af4d839274234e97a4fa1c6f0fe7dcce195383848cec56
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parse-url@npm:^8.1.0":
|
||||
version: 8.1.0
|
||||
resolution: "parse-url@npm:8.1.0"
|
||||
@@ -22433,7 +22775,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prop-types@npm:*, prop-types@npm:^15.8.1":
|
||||
"prop-types@npm:*, prop-types@npm:^15.6.2, prop-types@npm:^15.8.1":
|
||||
version: 15.8.1
|
||||
resolution: "prop-types@npm:15.8.1"
|
||||
dependencies:
|
||||
@@ -22633,7 +22975,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"queue@npm:6.0.2":
|
||||
"queue@npm:6.0.2, queue@npm:^6.0.1":
|
||||
version: 6.0.2
|
||||
resolution: "queue@npm:6.0.2"
|
||||
dependencies:
|
||||
@@ -23573,6 +23915,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"restructure@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "restructure@npm:3.0.0"
|
||||
checksum: 4525b5414ec0f2dc4ad66b5fbcebbc2f49e7ad778c30ce45b8b8f776af67e2c0752eb309748d7a597add6fc064e688df2662c834ffeaaea580af6d43087dc7d3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ret@npm:~0.1.10":
|
||||
version: 0.1.15
|
||||
resolution: "ret@npm:0.1.15"
|
||||
@@ -23852,6 +24201,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"scheduler@npm:^0.17.0":
|
||||
version: 0.17.0
|
||||
resolution: "scheduler@npm:0.17.0"
|
||||
dependencies:
|
||||
loose-envify: ^1.1.0
|
||||
object-assign: ^4.1.1
|
||||
checksum: 18d1e66cad3d26e3becd99b006d0744cda3556dbb356fc5b30df6d5499c85a308d18ee55353e01595f7c047b526564603ea80ef3d927a325faedc53ede03680c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"scheduler@npm:^0.23.0":
|
||||
version: 0.23.0
|
||||
resolution: "scheduler@npm:0.23.0"
|
||||
@@ -25241,6 +25600,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"svg-arc-to-cubic-bezier@npm:^3.0.0, svg-arc-to-cubic-bezier@npm:^3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "svg-arc-to-cubic-bezier@npm:3.2.0"
|
||||
checksum: 55bf17756d558b9c0daddf636a6c9f2fe01fd5ac412229dfa2d4b29740226a82c980bcd3b5eb09ce311cbea282106c7549d97f8c8dba3a5a7b75f786bcb5e155
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"svg-jest@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "svg-jest@npm:1.0.1"
|
||||
@@ -25603,6 +25969,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tiny-inflate@npm:^1.0.0, tiny-inflate@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "tiny-inflate@npm:1.0.3"
|
||||
checksum: 4086a1f8938dafa4a20c63b099aeb47bf8fef5aca991bf4ea4b35dd2684fa52363b2c19b3e76660311e7613cb7c4f063bc48751b9bdf9555e498d997c30bc2d6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tiny-typed-emitter@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "tiny-typed-emitter@npm:2.1.0"
|
||||
@@ -26358,6 +26731,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unicode-properties@npm:^1.4.0, unicode-properties@npm:^1.4.1":
|
||||
version: 1.4.1
|
||||
resolution: "unicode-properties@npm:1.4.1"
|
||||
dependencies:
|
||||
base64-js: ^1.3.0
|
||||
unicode-trie: ^2.0.0
|
||||
checksum: 337fba8a3c4707692d662fafbea60718ca9d8dfd2147cb2642bc4a1b5ad11136d848fa9c92818a35f59e6c866674ec7fd140e3e25412aea8fb8817f1b32fc3fe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unicode-property-aliases-ecmascript@npm:^2.0.0":
|
||||
version: 2.1.0
|
||||
resolution: "unicode-property-aliases-ecmascript@npm:2.1.0"
|
||||
@@ -26365,6 +26748,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unicode-trie@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "unicode-trie@npm:2.0.0"
|
||||
dependencies:
|
||||
pako: ^0.2.5
|
||||
tiny-inflate: ^1.0.0
|
||||
checksum: 19e637ce20953ec1fbfa9087abef4746a50352679b833be27924e4ba7ad753cc4073b74263747ccfccb5e38b30b17468cbb96f361eb49903ff8602396280b5a4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"union-value@npm:^1.0.0":
|
||||
version: 1.0.1
|
||||
resolution: "union-value@npm:1.0.1"
|
||||
@@ -26730,6 +27123,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vite-compatible-readable-stream@npm:^3.6.1":
|
||||
version: 3.6.1
|
||||
resolution: "vite-compatible-readable-stream@npm:3.6.1"
|
||||
dependencies:
|
||||
inherits: ^2.0.3
|
||||
string_decoder: ^1.1.1
|
||||
util-deprecate: ^1.0.1
|
||||
checksum: 7fd50738616a7bd012fb936b7036877940a0a83078fbe2584726fa9d1a5d15c934a5883e12e16213d6be54996b4ad7b6368d2897f9867a6c1110d03eacd91302
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vlq@npm:^1.0.0":
|
||||
version: 1.0.1
|
||||
resolution: "vlq@npm:1.0.1"
|
||||
@@ -27657,6 +28061,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yoga-layout@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "yoga-layout@npm:2.0.1"
|
||||
checksum: 65a83b1bf019dcb506c1b10cb0c278718b8eb9ef07c2967c1c8c66c2ce8b3edf44028fbc75e05c5b6492060add7e8e742da22b4afbb44ab199f7bae76114a92a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"zip-dir@npm:2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "zip-dir@npm:2.0.0"
|
||||
|
||||
Reference in New Issue
Block a user