feat: Added "Page size" option when exporting Super notes as PDF
This commit is contained in:
@@ -128,7 +128,7 @@ async function configureWindow(remoteBridge: CrossProcessBridge) {
|
||||
/* Use custom title bar. Take the sn-titlebar-height off of
|
||||
the app content height so its not overflowing */
|
||||
sheet.insertRule(
|
||||
'[role="dialog"]:not(.challenge-modal) { height: calc(100vh - var(--sn-desktop-titlebar-height)) !important; margin-top: var(--sn-desktop-titlebar-height); }',
|
||||
'[role="dialog"]:not(.challenge-modal) { max-height: calc(100vh - var(--sn-desktop-titlebar-height)) !important; margin-top: var(--sn-desktop-titlebar-height); }',
|
||||
sheet.cssRules.length,
|
||||
)
|
||||
sheet.insertRule(
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import { FileItem, PrefKey, PrefValue } from '@standardnotes/models'
|
||||
|
||||
export interface SuperConverterServiceInterface {
|
||||
isValidSuperString(superString: string): boolean
|
||||
convertSuperStringToOtherFormat: (
|
||||
superString: string,
|
||||
toFormat: 'txt' | 'md' | 'html' | 'json' | 'pdf',
|
||||
config?: {
|
||||
embedBehavior?: PrefValue[PrefKey.SuperNoteExportEmbedBehavior]
|
||||
getFileItem?: (id: string) => FileItem | undefined
|
||||
getFileBase64?: (id: string) => Promise<string | undefined>
|
||||
pdf?: {
|
||||
pageSize?: PrefValue[PrefKey.SuperNoteExportPDFPageSize]
|
||||
}
|
||||
},
|
||||
) => Promise<string>
|
||||
convertOtherFormatToSuperString: (
|
||||
otherFormatString: string,
|
||||
|
||||
@@ -42,6 +42,7 @@ export const PrefDefaults = {
|
||||
[PrefKey.SuperNoteExportFormat]: 'json',
|
||||
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference',
|
||||
[PrefKey.SuperNoteExportUseMDFrontmatter]: true,
|
||||
[PrefKey.SuperNoteExportPDFPageSize]: 'A4',
|
||||
[PrefKey.SystemViewPreferences]: {},
|
||||
[PrefKey.AuthenticatorNames]: '',
|
||||
[PrefKey.ComponentPreferences]: {},
|
||||
|
||||
@@ -43,6 +43,7 @@ export enum PrefKey {
|
||||
SuperNoteExportFormat = 'superNoteExportFormat',
|
||||
SuperNoteExportEmbedBehavior = 'superNoteExportEmbedBehavior',
|
||||
SuperNoteExportUseMDFrontmatter = 'superNoteExportUseMDFrontmatter',
|
||||
SuperNoteExportPDFPageSize = 'superNoteExportPDFPageSize',
|
||||
AuthenticatorNames = 'authenticatorNames',
|
||||
PaneGesturesEnabled = 'paneGesturesEnabled',
|
||||
ComponentPreferences = 'componentPreferences',
|
||||
@@ -90,6 +91,7 @@ export type PrefValue = {
|
||||
[PrefKey.SuperNoteExportFormat]: 'json' | 'md' | 'html' | 'pdf'
|
||||
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference' | 'inline' | 'separate'
|
||||
[PrefKey.SuperNoteExportUseMDFrontmatter]: boolean
|
||||
[PrefKey.SuperNoteExportPDFPageSize]: 'A3' | 'A4' | 'LETTER' | 'LEGAL' | 'TABLOID'
|
||||
[PrefKey.AuthenticatorNames]: string
|
||||
[PrefKey.PaneGesturesEnabled]: boolean
|
||||
[PrefKey.ComponentPreferences]: AllComponentPreferences
|
||||
|
||||
@@ -499,7 +499,7 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
</>
|
||||
)}
|
||||
|
||||
<ModalOverlay isOpen={showExportSuperModal} close={closeSuperExportModal}>
|
||||
<ModalOverlay isOpen={showExportSuperModal} close={closeSuperExportModal} className="md:max-w-[25vw]">
|
||||
<SuperExportModal notes={notes} exportNotes={downloadSelectedItems} close={closeSuperExportModal} />
|
||||
</ModalOverlay>
|
||||
</>
|
||||
|
||||
@@ -6,6 +6,7 @@ import RadioButtonGroup from '../RadioButtonGroup/RadioButtonGroup'
|
||||
import { useEffect } from 'react'
|
||||
import Switch from '../Switch/Switch'
|
||||
import { noteHasEmbeddedFiles } from '@/Utils/NoteExportUtils'
|
||||
import Dropdown from '../Dropdown/Dropdown'
|
||||
|
||||
type Props = {
|
||||
notes: SNNote[]
|
||||
@@ -19,6 +20,7 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
const superNoteExportFormat = usePreference(PrefKey.SuperNoteExportFormat)
|
||||
const superNoteExportEmbedBehavior = usePreference(PrefKey.SuperNoteExportEmbedBehavior)
|
||||
const superNoteExportUseMDFrontmatter = usePreference(PrefKey.SuperNoteExportUseMDFrontmatter)
|
||||
const superNoteExportPDFPageSize = usePreference(PrefKey.SuperNoteExportPDFPageSize)
|
||||
|
||||
useEffect(() => {
|
||||
if (superNoteExportFormat === 'json' && superNoteExportEmbedBehavior === 'separate') {
|
||||
@@ -60,23 +62,25 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
]}
|
||||
>
|
||||
<div className="mb-2">
|
||||
<div className="mb-3 text-base">We detected your selection includes Super notes.</div>
|
||||
<div className="mb-1">What format do you want to export them in?</div>
|
||||
<RadioButtonGroup
|
||||
items={[
|
||||
{ label: 'Super (.json)', value: 'json' },
|
||||
{ label: 'Markdown (.md)', value: 'md' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
{ label: 'PDF', value: 'pdf' },
|
||||
]}
|
||||
value={superNoteExportFormat}
|
||||
onChange={(value) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportFormat,
|
||||
value as PrefValue[PrefKey.SuperNoteExportFormat],
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<div className="text-base">Choose export format {notes.length > 1 ? 'for Super notes' : ''}</div>
|
||||
<Dropdown
|
||||
label="Export format"
|
||||
items={[
|
||||
{ label: 'Super (.json)', value: 'json' },
|
||||
{ label: 'Markdown (.md)', value: 'md' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
{ label: 'PDF', value: 'pdf' },
|
||||
]}
|
||||
value={superNoteExportFormat}
|
||||
onChange={(value) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportFormat,
|
||||
value as PrefValue[PrefKey.SuperNoteExportFormat],
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{superNoteExportFormat === 'md' && (
|
||||
<div className="mt-2 text-xs text-passive-0">
|
||||
Note that conversion to Markdown is not lossless. Some features like collapsible blocks and formatting like
|
||||
@@ -84,6 +88,33 @@ const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{superNoteExportFormat === 'pdf' && (
|
||||
<div className="mt-4 flex items-center justify-between">
|
||||
<div className="text-base">Page size</div>
|
||||
<Dropdown
|
||||
label="Page size"
|
||||
items={
|
||||
[
|
||||
{ label: 'A3', value: 'A3' },
|
||||
{ label: 'A4', value: 'A4' },
|
||||
{ label: 'Letter', value: 'LETTER' },
|
||||
{ label: 'Legal', value: 'LEGAL' },
|
||||
{ label: 'Tabloid', value: 'TABLOID' },
|
||||
] satisfies {
|
||||
label: string
|
||||
value: PrefValue[PrefKey.SuperNoteExportPDFPageSize]
|
||||
}[]
|
||||
}
|
||||
value={superNoteExportPDFPageSize}
|
||||
onChange={(value) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportPDFPageSize,
|
||||
value as PrefValue[PrefKey.SuperNoteExportPDFPageSize],
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{superNoteExportFormat === 'md' && (
|
||||
<div className="mt-4">
|
||||
<Switch
|
||||
|
||||
@@ -22,6 +22,7 @@ import { $isCollapsibleTitleNode } from '../../../Plugins/CollapsiblePlugin/Coll
|
||||
import { PDFDataNode, PDFWorker } from './PDFWorker'
|
||||
import { wrap } from 'comlink'
|
||||
import { getBase64FromBlob } from '@/Utils'
|
||||
import { PrefKey, PrefValue } from '@standardnotes/snjs'
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: {
|
||||
@@ -422,7 +423,7 @@ const PDFWorkerComlink = wrap<PDFWorker>(new Worker(new URL('./PDFWorker.tsx', i
|
||||
/**
|
||||
* @returns The PDF as a base64 string
|
||||
*/
|
||||
export function $generatePDFFromNodes(editor: LexicalEditor) {
|
||||
export function $generatePDFFromNodes(editor: LexicalEditor, pageSize: PrefValue[PrefKey.SuperNoteExportPDFPageSize]) {
|
||||
return new Promise<string>((resolve) => {
|
||||
editor.getEditorState().read(() => {
|
||||
const root = $getRoot()
|
||||
@@ -430,7 +431,7 @@ export function $generatePDFFromNodes(editor: LexicalEditor) {
|
||||
|
||||
const pdfDataNodes = getPDFDataNodesFromLexicalNodes(nodes)
|
||||
|
||||
void PDFWorkerComlink.renderPDF(pdfDataNodes).then((blob) => {
|
||||
void PDFWorkerComlink.renderPDF(pdfDataNodes, pageSize).then((blob) => {
|
||||
void getBase64FromBlob(blob).then((base64) => {
|
||||
resolve(base64)
|
||||
})
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
TextProps,
|
||||
SVGProps,
|
||||
ImageWithSrcProp,
|
||||
PageProps,
|
||||
} from '@react-pdf/renderer'
|
||||
import { expose } from 'comlink'
|
||||
|
||||
@@ -72,10 +73,11 @@ const Node = ({ node }: { node: PDFDataNode }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const PDFDocument = ({ nodes }: { nodes: PDFDataNode[] }) => {
|
||||
const PDFDocument = ({ nodes, pageSize }: { nodes: PDFDataNode[]; pageSize: PageProps['size'] }) => {
|
||||
return (
|
||||
<Document>
|
||||
<Page
|
||||
size={pageSize}
|
||||
style={{
|
||||
paddingVertical: 35,
|
||||
paddingHorizontal: 35,
|
||||
@@ -92,8 +94,8 @@ const PDFDocument = ({ nodes }: { nodes: PDFDataNode[] }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const renderPDF = (nodes: PDFDataNode[]) => {
|
||||
return pdf(<PDFDocument nodes={nodes} />).toBlob()
|
||||
const renderPDF = (nodes: PDFDataNode[], pageSize: PageProps['size']) => {
|
||||
return pdf(<PDFDocument pageSize={pageSize} nodes={nodes} />).toBlob()
|
||||
}
|
||||
|
||||
expose({
|
||||
|
||||
@@ -56,6 +56,9 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
embedBehavior?: PrefValue[PrefKey.SuperNoteExportEmbedBehavior]
|
||||
getFileItem?: (id: string) => FileItem | undefined
|
||||
getFileBase64?: (id: string) => Promise<string | undefined>
|
||||
pdf?: {
|
||||
pageSize?: PrefValue[PrefKey.SuperNoteExportPDFPageSize]
|
||||
}
|
||||
},
|
||||
): Promise<string> {
|
||||
if (superString.length === 0) {
|
||||
@@ -145,8 +148,8 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
resolve()
|
||||
break
|
||||
case 'pdf': {
|
||||
void import('../Lexical/Utils/PDFExport/PDFExport').then(({ $generatePDFFromNodes }) => {
|
||||
void $generatePDFFromNodes(this.exportEditor).then((pdf) => {
|
||||
void import('../Lexical/Utils/PDFExport/PDFExport').then(({ $generatePDFFromNodes }): void => {
|
||||
void $generatePDFFromNodes(this.exportEditor, config?.pdf?.pageSize || 'A4').then((pdf) => {
|
||||
content = pdf
|
||||
resolve()
|
||||
})
|
||||
|
||||
@@ -99,6 +99,12 @@ export const getNoteBlob = async (
|
||||
}
|
||||
return await getBase64FromBlob(fileBlob)
|
||||
},
|
||||
pdf: {
|
||||
pageSize: application.getPreference(
|
||||
PrefKey.SuperNoteExportPDFPageSize,
|
||||
PrefDefaults[PrefKey.SuperNoteExportPDFPageSize],
|
||||
),
|
||||
},
|
||||
})
|
||||
const useMDFrontmatter =
|
||||
format === 'md' &&
|
||||
|
||||
Reference in New Issue
Block a user