import Foundation extension Content { func saveToDisk() throws { //print("Starting save") for page in pages { try storage.save(pageMetadata: page.pageFile, for: page.id) } for post in posts { try storage.save(post: post.postFile, for: post.id) } for tag in tags { try storage.save(tagMetadata: tag.tagFile, for: tag.id) } try storage.save(settings: settings.file) let fileDescriptions: [FileDescriptions] = files.sorted().compactMap { file in guard !file.englishDescription.isEmpty || !file.germanDescription.isEmpty else { return nil } return FileDescriptions( fileId: file.id, german: file.germanDescription.nonEmpty, english: file.englishDescription.nonEmpty) } try storage.save(fileDescriptions: fileDescriptions) do { try storage.deletePostFiles(notIn: posts.map { $0.id }) try storage.deletePageFiles(notIn: pages.map { $0.id }) try storage.deleteTagFiles(notIn: tags.map { $0.id }) try storage.deleteFileResources(notIn: files.map { $0.id }) } catch { print("Failed to remove unused files: \(error)") } } } private extension Page { var pageFile: PageFile { .init(isDraft: isDraft, tags: tags.map { $0.id }, createdDate: createdDate, startDate: startDate, endDate: hasEndDate ? endDate : nil, german: german.pageFile, english: english.pageFile) } } private extension LocalizedPage { var pageFile: LocalizedPageFile { .init(url: urlString, files: files.sorted(), externalFiles: externalFiles.sorted(), requiredFiles: requiredFiles.sorted(), title: title, linkPreviewImage: linkPreviewImage?.id, linkPreviewTitle: linkPreviewTitle, linkPreviewDescription: linkPreviewDescription, lastModifiedDate: lastModified, originalURL: originalUrl) } } private extension Post { var postFile: PostFile { .init( isDraft: isDraft, createdDate: createdDate, startDate: startDate, endDate: hasEndDate ? endDate : nil, tags: tags.map { $0.id }, german: german.postFile, english: english.postFile, linkedPageId: linkedPage?.id) } } private extension LocalizedPost { var postFile: LocalizedPostFile { .init(images: images.map { $0.id }, title: title.nonEmpty, content: content, lastModifiedDate: lastModified, linkPreviewImage: linkPreviewImage?.id, linkPreviewTitle: linkPreviewTitle, linkPreviewDescription: linkPreviewDescription) } } private extension Tag { var tagFile: TagFile { .init(id: id, isVisible: isVisible, german: german.tagFile, english: english.tagFile) } } private extension LocalizedTag { var tagFile: LocalizedTagFile { .init(urlComponent: urlComponent, name: name, subtitle: subtitle, description: description, thumbnail: thumbnail?.id, originalURL: originalUrl) } } private extension NavigationBarSettings { var file: NavigationBarSettingsFile { .init(navigationIconPath: iconPath, navigationTags: tags.map { $0.id }) } } extension Settings { var file: SettingsFile { .init( outputDirectoryPath: outputDirectoryPath, navigationBar: navigationBar.file, posts: posts.file, pages: pages.file, german: german.file, english: english.file) } } private extension PostSettings { var file: PostSettingsFile { .init(postsPerPage: postsPerPage, contentWidth: contentWidth) } } private extension PageSettings { var file: PageSettingsFile { .init(pageUrlPrefix: pageUrlPrefix, contentWidth: contentWidth) } } private extension LocalizedSettings { var file: LocalizedSettingsFile { .init(navigationBarIconDescription: navigationBarIconDescription, posts: posts.file) } } private extension LocalizedPostSettings { var file: LocalizedPostSettingsFile { .init( feedTitle: title, feedDescription: description, feedUrlPrefix: feedUrlPrefix) } }