Skip to content

Commit

Permalink
chore: fix duplicate file name error when exporting notes and refacto…
Browse files Browse the repository at this point in the history
…r file name utils (#2877) [skip e2e]
  • Loading branch information
amanharwara authored May 7, 2024
1 parent 71d2dbc commit c3265d7
Show file tree
Hide file tree
Showing 16 changed files with 61 additions and 56 deletions.
3 changes: 2 additions & 1 deletion packages/filepicker/src/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { formatSizeToReadableString, parseFileName } from './utils'
import { formatSizeToReadableString } from './utils'
import { parseFileName } from '@standardnotes/utils'

describe('utils', () => {
describe('parseFileName', () => {
Expand Down
12 changes: 0 additions & 12 deletions packages/filepicker/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@ export async function readFile(file: File): Promise<Uint8Array> {
})
}

export function parseFileName(fileName: string): {
name: string
ext: string
} {
const pattern = /(?:\.([^.]+))?$/
const extMatches = pattern.exec(fileName)
const ext = extMatches?.[1] || ''
const name = fileName.includes('.') ? fileName.substring(0, fileName.lastIndexOf('.')) : fileName

return { name, ext }
}

export function saveFile(name: string, bytes: Uint8Array): void {
const link = document.createElement('a')
const blob = new Blob([bytes], {
Expand Down
24 changes: 4 additions & 20 deletions packages/ui-services/src/Archive/ArchiveManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName, createZippableFileName, sanitizeFileName } from '@standardnotes/utils'
import {
BackupFile,
BackupFileDecryptedContextualPayload,
Expand All @@ -8,22 +8,6 @@ import {
import { ContentType } from '@standardnotes/domain-core'
import { ApplicationInterface } from '@standardnotes/services'

export function sanitizeFileName(name: string): string {
return name.trim().replace(/[.\\/:"?*|<>]/g, '_')
}

function zippableFileName(name: string, suffix = '', format = 'txt'): string {
const sanitizedName = sanitizeFileName(name)
const nameEnd = suffix + '.' + format
const maxFileNameLength = 100
return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd
}

export function parseAndCreateZippableFileName(name: string, suffix = '') {
const { name: parsedName, ext } = parseFileName(name)
return zippableFileName(parsedName, suffix, ext)
}

type ZippableData = {
name: string
content: Blob
Expand Down Expand Up @@ -87,7 +71,7 @@ export class ArchiveManager {
type: 'text/plain',
})

const fileName = zippableFileName('Standard Notes Backup and Import File')
const fileName = createZippableFileName('Standard Notes Backup and Import File')
await zipWriter.add(fileName, new zip.BlobReader(blob))

for (let index = 0; index < items.length; index++) {
Expand All @@ -109,7 +93,7 @@ export class ArchiveManager {

const blob = new Blob([contents], { type: 'text/plain' })
const fileName =
`Items/${sanitizeFileName(item.content_type)}/` + zippableFileName(name, `-${item.uuid.split('-')[0]}`)
`Items/${sanitizeFileName(item.content_type)}/` + createZippableFileName(name, `-${item.uuid.split('-')[0]}`)
await zipWriter.add(fileName, new zip.BlobReader(blob))
}

Expand Down Expand Up @@ -137,7 +121,7 @@ export class ArchiveManager {
const currentFileNameIndex = filenameCounts[file.name]

await writer.add(
zippableFileName(name, currentFileNameIndex > 0 ? ` - ${currentFileNameIndex}` : '', ext),
createZippableFileName(name, currentFileNameIndex > 0 ? ` - ${currentFileNameIndex}` : '', ext),
new zip.BlobReader(file.content),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName } from '@standardnotes/utils'
import { Converter } from '../Converter'

export class HTMLConverter implements Converter {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-services/src/Import/Importer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName } from '@standardnotes/utils'
import {
FeatureStatus,
FeaturesClientInterface,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName } from '@standardnotes/utils'
import { Converter } from '../Converter'

export class PlaintextConverter implements Converter {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName } from '@standardnotes/utils'
import { Converter } from '../Converter'
import { ConversionResult } from '../ConversionResult'

Expand Down
38 changes: 38 additions & 0 deletions packages/utils/src/Domain/FileName/FileNameUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export function parseFileName(fileName: string): {
name: string
ext: string
} {
const pattern = /(?:\.([^.]+))$/
const extMatches = pattern.exec(fileName)
const ext = extMatches?.[1] || ''
const name = fileName.includes('.') ? fileName.substring(0, fileName.lastIndexOf('.')) : fileName

return { name, ext }
}

export function sanitizeFileName(name: string): string {
return name.trim().replace(/[.\\/:"?*|<>]/g, '_')
}

export function truncateFileName(name: string, maxLength: number): string {
return name.length > maxLength ? name.slice(0, maxLength) : name
}

const MaxFileNameLength = 100

export function createZippableFileName(
name: string,
suffix = '',
format = 'txt',
maxLength = MaxFileNameLength,
): string {
const sanitizedName = sanitizeFileName(name)
const truncatedName = truncateFileName(sanitizedName, maxLength)
const nameEnd = suffix + '.' + format
return truncatedName + nameEnd
}

export function parseAndCreateZippableFileName(name: string, suffix = '') {
const { name: parsedName, ext } = parseFileName(name)
return createZippableFileName(parsedName, suffix, ext)
}
1 change: 1 addition & 0 deletions packages/utils/src/Domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './Utils/Utils'
export * from './Uuid/Utils'
export * from './Uuid/UuidGenerator'
export * from './Uuid/UuidMap'
export * from './FileName/FileNameUtils'
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import ImagePreview from './ImagePreview'
import { ImageZoomLevelProps } from './ImageZoomLevelProps'
import { PreviewableTextFileTypes, RequiresNativeFilePreview } from './isFilePreviewable'
import TextPreview from './TextPreview'
import { parseFileName } from '@standardnotes/filepicker'
import { sanitizeFileName } from '@standardnotes/ui-services'
import { parseFileName, sanitizeFileName } from '@standardnotes/utils'
import VideoPreview from './VideoPreview'

type Props = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { alertDialog, sanitizeFileName } from '@standardnotes/ui-services'
import { alertDialog } from '@standardnotes/ui-services'
import {
STRING_IMPORT_SUCCESS,
STRING_INVALID_IMPORT_FILE,
Expand All @@ -10,6 +10,7 @@ import {
STRING_ENC_NOT_ENABLED,
} from '@/Constants/Strings'
import { BackupFile } from '@standardnotes/snjs'
import { sanitizeFileName } from '@standardnotes/utils'
import { ChangeEventHandler, MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react'
import { WebApplication } from '@/Application/WebApplication'
import { observer } from 'mobx-react-lite'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DecoratorBlockNode, SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode'
import { parseAndCreateZippableFileName } from '@standardnotes/ui-services'
import { parseAndCreateZippableFileName } from '@standardnotes/utils'
import { DOMExportOutput, Spread } from 'lexical'

type SerializedFileExportNode = Spread<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +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'
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName } from '@standardnotes/utils'

export class HeadlessSuperConverter implements SuperConverterServiceInterface {
private importEditor: LexicalEditor
Expand Down
10 changes: 2 additions & 8 deletions packages/web/src/javascripts/Controllers/FilesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@ import {
ArchiveManager,
confirmDialog,
IsNativeMobileWeb,
parseAndCreateZippableFileName,
VaultDisplayServiceInterface,
} from '@standardnotes/ui-services'
import { Strings, StringUtils } from '@/Constants/Strings'
import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays'
import {
ClassicFileReader,
StreamingFileReader,
StreamingFileSaver,
ClassicFileSaver,
parseFileName,
} from '@standardnotes/filepicker'
import { ClassicFileReader, StreamingFileReader, StreamingFileSaver, ClassicFileSaver } from '@standardnotes/filepicker'
import { parseAndCreateZippableFileName, parseFileName } from '@standardnotes/utils'
import {
AlertService,
ChallengeReason,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { getBase64FromBlob } from '@/Utils'
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName, sanitizeFileName } from '@standardnotes/utils'
import { MobileDeviceInterface } from '@standardnotes/snjs'
import { addToast, ToastType, dismissToast } from '@standardnotes/toast'
import { sanitizeFileName } from '@standardnotes/ui-services'

export const downloadBlobOnAndroid = async (
mobileDevice: MobileDeviceInterface,
Expand Down
8 changes: 4 additions & 4 deletions packages/web/src/javascripts/Utils/NoteExportUtils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { WebApplication } from '@/Application/WebApplication'
import { HeadlessSuperConverter } from '@/Components/SuperEditor/Tools/HeadlessSuperConverter'
import { NoteType, PrefKey, SNNote, PrefDefaults, FileItem, PrefValue } from '@standardnotes/snjs'
import { WebApplicationInterface, parseAndCreateZippableFileName } from '@standardnotes/ui-services'
import { ZipDirectoryEntry } from '@zip.js/zip.js'
import { WebApplicationInterface } from '@standardnotes/ui-services'
import { type ZipDirectoryEntry } from '@zip.js/zip.js'
// @ts-expect-error Using inline loaders to load CSS as string
import superEditorCSS from '!css-loader?{"sourceMap":false}!sass-loader!../Components/SuperEditor/Lexical/Theme/editor.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import snColorsCSS from '!css-loader?{"sourceMap":false}!sass-loader!@standardnotes/styles/src/Styles/_colors.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import exportOverridesCSS from '!css-loader?{"sourceMap":false}!sass-loader!../Components/SuperEditor/Lexical/Theme/export-overrides.scss'
import { getBase64FromBlob } from './Utils'
import { parseFileName } from '@standardnotes/filepicker'
import { parseFileName, parseAndCreateZippableFileName } from '@standardnotes/utils'

export const getNoteFormat = (application: WebApplicationInterface, note: SNNote) => {
if (note.noteType === NoteType.Super) {
Expand Down Expand Up @@ -238,7 +238,7 @@ export const createNoteExport = async (

for (const note of notes) {
const blob = await getNoteBlob(application, note, superEmbedBehaviorPref)
const _name = getNoteFileName(application, note)
const _name = parseAndCreateZippableFileName(getNoteFileName(application, note))

filenameCounts[_name] = filenameCounts[_name] == undefined ? 0 : filenameCounts[_name] + 1

Expand Down

0 comments on commit c3265d7

Please sign in to comment.