refactor: importer service (#2674)

This commit is contained in:
Aman Harwara
2023-12-05 02:55:32 +05:30
committed by GitHub
parent 9265e7afe9
commit 85ecb10924
17 changed files with 509 additions and 518 deletions

View File

@@ -4,33 +4,30 @@
import { jsonTextContentData, htmlTestData, jsonListContentData } from './testData'
import { GoogleKeepConverter } from './GoogleKeepConverter'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { GenerateUuid } from '@standardnotes/services'
import { FileItem, SuperConverterServiceInterface } from '@standardnotes/snjs'
import { ContentType, DecryptedTransferPayload, NoteContent } from '@standardnotes/snjs'
import { CreateNoteFn } from '../Converter'
describe('GoogleKeepConverter', () => {
const crypto = {
generateUUID: () => String(Math.random()),
} as unknown as PureCryptoInterface
const superConverterService: SuperConverterServiceInterface = {
isValidSuperString: () => true,
convertOtherFormatToSuperString: (data: string) => data,
convertSuperStringToOtherFormat: async (data: string) => data,
getEmbeddedFileIDsFromSuperString: () => [],
uploadAndReplaceInlineFilesInSuperString: async (
superString: string,
_uploadFile: (file: File) => Promise<FileItem | undefined>,
_linkFile: (file: FileItem) => Promise<void>,
_generateUuid: GenerateUuid,
) => superString,
}
const generateUuid = new GenerateUuid(crypto)
const createNote: CreateNoteFn = ({ title, text, createdAt, updatedAt, trashed, archived, pinned }) =>
({
uuid: Math.random().toString(),
created_at: createdAt,
updated_at: updatedAt,
content_type: ContentType.TYPES.Note,
content: {
title,
text,
trashed,
archived,
pinned,
references: [],
},
}) as unknown as DecryptedTransferPayload<NoteContent>
it('should parse json data', () => {
const converter = new GoogleKeepConverter(superConverterService, generateUuid)
const converter = new GoogleKeepConverter()
const textContent = converter.tryParseAsJson(jsonTextContentData, false)
const textContent = converter.tryParseAsJson(jsonTextContentData, createNote, (md) => md)
expect(textContent).not.toBeNull()
expect(textContent?.created_at).toBeInstanceOf(Date)
@@ -43,7 +40,7 @@ describe('GoogleKeepConverter', () => {
expect(textContent?.content.archived).toBe(false)
expect(textContent?.content.pinned).toBe(false)
const listContent = converter.tryParseAsJson(jsonListContentData, false)
const listContent = converter.tryParseAsJson(jsonListContentData, createNote, (md) => md)
expect(listContent).not.toBeNull()
expect(listContent?.created_at).toBeInstanceOf(Date)
@@ -58,13 +55,15 @@ describe('GoogleKeepConverter', () => {
})
it('should parse html data', () => {
const converter = new GoogleKeepConverter(superConverterService, generateUuid)
const converter = new GoogleKeepConverter()
const result = converter.tryParseAsHtml(
htmlTestData,
{
name: 'note-2.html',
},
createNote,
(html) => html,
false,
)

View File

@@ -1,9 +1,6 @@
import { ContentType } from '@standardnotes/domain-core'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { readFileAsText } from '../Utils'
import { GenerateUuid } from '@standardnotes/services'
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
import { NoteType } from '@standardnotes/features'
import { Converter, CreateNoteFn } from '../Converter'
type Content =
| {
@@ -25,28 +22,44 @@ type GoogleKeepJsonNote = {
userEditedTimestampUsec: number
} & Content
export class GoogleKeepConverter {
constructor(
private superConverterService: SuperConverterServiceInterface,
private _generateUuid: GenerateUuid,
) {}
export class GoogleKeepConverter implements Converter {
constructor() {}
async convertGoogleKeepBackupFileToNote(
file: File,
isEntitledToSuper: boolean,
): Promise<DecryptedTransferPayload<NoteContent>> {
const content = await readFileAsText(file)
getImportType(): string {
return 'google-keep'
}
const possiblePayloadFromJson = this.tryParseAsJson(content, isEntitledToSuper)
getSupportedFileTypes(): string[] {
return ['text/html', 'application/json']
}
if (possiblePayloadFromJson) {
return possiblePayloadFromJson
isContentValid(content: string): boolean {
try {
const parsed = JSON.parse(content)
return GoogleKeepConverter.isValidGoogleKeepJson(parsed)
} catch (error) {
console.error(error)
}
const possiblePayloadFromHtml = this.tryParseAsHtml(content, file, isEntitledToSuper)
return false
}
convert: Converter['convert'] = async (
file,
{ createNote, canUseSuper, convertHTMLToSuper, convertMarkdownToSuper, readFileAsText },
) => {
const content = await readFileAsText(file)
const possiblePayloadFromJson = this.tryParseAsJson(content, createNote, convertMarkdownToSuper)
if (possiblePayloadFromJson) {
return [possiblePayloadFromJson]
}
const possiblePayloadFromHtml = this.tryParseAsHtml(content, file, createNote, convertHTMLToSuper, canUseSuper)
if (possiblePayloadFromHtml) {
return possiblePayloadFromHtml
return [possiblePayloadFromHtml]
}
throw new Error('Could not parse Google Keep backup file')
@@ -55,7 +68,9 @@ export class GoogleKeepConverter {
tryParseAsHtml(
data: string,
file: { name: string },
isEntitledToSuper: boolean,
createNote: CreateNoteFn,
convertHTMLToSuper: (html: string) => string,
canUseSuper: boolean,
): DecryptedTransferPayload<NoteContent> {
const rootElement = document.createElement('html')
rootElement.innerHTML = data
@@ -85,18 +100,18 @@ export class GoogleKeepConverter {
const checked = item.classList.contains('checked')
item.setAttribute('aria-checked', checked ? 'true' : 'false')
if (!isEntitledToSuper) {
if (!canUseSuper) {
item.textContent = `- ${checked ? '[x]' : '[ ]'} ${item.textContent?.trim()}\n`
}
})
})
if (!isEntitledToSuper) {
if (!canUseSuper) {
// Replace <br> with \n so line breaks get recognised
contentElement.innerHTML = contentElement.innerHTML.replace(/<br>/g, '\n')
content = contentElement.textContent
} else {
content = this.superConverterService.convertOtherFormatToSuperString(rootElement.innerHTML, 'html')
content = convertHTMLToSuper(rootElement.innerHTML)
}
if (!content) {
@@ -105,25 +120,13 @@ export class GoogleKeepConverter {
const title = rootElement.getElementsByClassName('title')[0]?.textContent || file.name
return {
created_at: date,
created_at_timestamp: date.getTime(),
updated_at: date,
updated_at_timestamp: date.getTime(),
uuid: this._generateUuid.execute().getValue(),
content_type: ContentType.TYPES.Note,
content: {
title: title,
text: content,
references: [],
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
return createNote({
createdAt: date,
updatedAt: date,
title: title,
text: content,
noteType: NoteType.Super,
})
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -148,7 +151,11 @@ export class GoogleKeepConverter {
)
}
tryParseAsJson(data: string, isEntitledToSuper: boolean): DecryptedTransferPayload<NoteContent> | null {
tryParseAsJson(
data: string,
createNote: CreateNoteFn,
convertMarkdownToSuper: (md: string) => string,
): DecryptedTransferPayload<NoteContent> | null {
try {
const parsed = JSON.parse(data) as GoogleKeepJsonNote
if (!GoogleKeepConverter.isValidGoogleKeepJson(parsed)) {
@@ -165,31 +172,17 @@ export class GoogleKeepConverter {
})
.join('\n')
}
if (isEntitledToSuper) {
text = this.superConverterService.convertOtherFormatToSuperString(text, 'md')
}
return {
created_at: date,
created_at_timestamp: date.getTime(),
updated_at: date,
updated_at_timestamp: date.getTime(),
uuid: this._generateUuid.execute().getValue(),
content_type: ContentType.TYPES.Note,
content: {
title: parsed.title,
text,
references: [],
archived: Boolean(parsed.isArchived),
trashed: Boolean(parsed.isTrashed),
pinned: Boolean(parsed.isPinned),
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
text = convertMarkdownToSuper(text)
return createNote({
createdAt: date,
updatedAt: date,
title: parsed.title,
text,
archived: Boolean(parsed.isArchived),
trashed: Boolean(parsed.isTrashed),
pinned: Boolean(parsed.isPinned),
noteType: NoteType.Super,
})
} catch (e) {
console.error(e)
return null