import Foundation extension Content { private func convert(_ tag: LocalizedTagFile, images: [String : FileResource]) -> LocalizedTag { LocalizedTag( content: self, urlComponent: tag.urlComponent, name: tag.name, subtitle: tag.subtitle, description: tag.description, thumbnail: tag.thumbnail.map { images[$0] }, originalUrl: tag.originalURL) } private func convert(_ post: LocalizedPostFile, images: [String : FileResource]) -> LocalizedPost { LocalizedPost( content: self, title: post.title, text: post.content, lastModified: post.lastModifiedDate, images: post.images.compactMap { images[$0] }, linkPreviewImage: post.linkPreviewImage.map { images[$0] }, linkPreviewTitle: post.linkPreviewTitle, linkPreviewDescription: post.linkPreviewDescription) } private func convert(_ page: LocalizedPageFile, images: [String : FileResource]) -> LocalizedPage { LocalizedPage( content: self, urlString: page.url, title: page.title, lastModified: page.lastModifiedDate, originalUrl: page.originalURL, files: Set(page.files), externalFiles: Set(page.externalFiles), requiredFiles: Set(page.requiredFiles), linkPreviewImage: page.linkPreviewImage.map { images[$0] }, linkPreviewTitle: page.linkPreviewTitle, linkPreviewDescription: page.linkPreviewDescription) } func loadFromDisk() throws { let storage = Storage(baseFolder: URL(filePath: contentPath)) let settings = try storage.loadSettings() let imageDescriptions = try storage.loadFileDescriptions().reduce(into: [:]) { descriptions, description in descriptions[description.fileId] = description } let tagData = try storage.loadAllTags() let pagesData = try storage.loadAllPages() let postsData = try storage.loadAllPosts() let fileList = try storage.loadAllFiles() let externalFiles = try storage.loadExternalFileList() let tagOverviewData = try storage.loadTagOverview() var files: [String : FileResource] = fileList.reduce(into: [:]) { files, fileId in let descriptions = imageDescriptions[fileId] files[fileId] = FileResource( content: self, id: fileId, isExternallyStored: false, en: descriptions?.english ?? "", de: descriptions?.german ?? "") } for fileId in externalFiles { let descriptions = imageDescriptions[fileId] files[fileId] = FileResource( content: self, id: fileId, isExternallyStored: true, en: descriptions?.english ?? "", de: descriptions?.german ?? "") } let images = files.filter { $0.value.type.isImage } let tags = tagData.reduce(into: [:]) { (tags, data) in tags[data.key] = Tag( content: self, id: data.value.id, isVisible: data.value.isVisible, german: convert(data.value.german, images: images), english: convert(data.value.english, images: images)) } let pages: [String : Page] = loadPages(pagesData, tags: tags, images: images) let posts = postsData.map { postId, post in let linkedPage = post.linkedPageId.map { pages[$0] } let german = convert(post.german, images: images) let english = convert(post.english, images: images) return Post( content: self, id: postId, isDraft: post.isDraft, createdDate: post.createdDate, startDate: post.startDate, endDate: post.endDate, tags: post.tags.map { tags[$0]! }, german: german, english: english, linkedPage: linkedPage) } let tagOverview = tagOverviewData.map { file in TagOverviewPage( content: self, german: .init(content: self, file: file.german, image: file.german.linkPreviewImage.map { files[$0] }), english: .init(content: self, file: file.english, image: file.english.linkPreviewImage.map { files[$0] })) } self.tags = tags.values.sorted() self.pages = pages.values.sorted(ascending: false) { $0.startDate } self.files = files.values.sorted { $0.id } self.posts = posts.sorted(ascending: false) { $0.startDate } self.tagOverview = tagOverview self.settings = makeSettings(settings, tags: tags, pages: pages, files: files) } private func makeSettings(_ settings: SettingsFile, tags: [String : Tag], pages: [String : Page], files: [String : FileResource]) -> Settings { #warning("Notify about missing links") let navigationItems: [Item] = settings.navigationItems.compactMap { switch $0.type { case .tag: return tags[$0.id] case .page: return pages[$0.id] case .tagOverview: return tagOverview default: return nil } } let posts = PostSettings(file: settings.posts, files: files) let pages = PageSettings(file: settings.pages, files: files) let paths = PathSettings(file: settings.paths) return Settings( paths: paths, navigationItems: navigationItems, posts: posts, pages: pages, german: .init(file: settings.german), english: .init(file: settings.english)) } private func loadPages(_ pagesData: [String : PageFile], tags: [String : Tag], images: [String : FileResource]) -> [String : Page] { pagesData.reduce(into: [:]) { pages, data in let (pageId, page) = data pages[pageId] = Page( content: self, id: pageId, externalLink: page.externalLink, isDraft: page.isDraft, createdDate: page.createdDate, startDate: page.startDate, endDate: page.endDate, german: convert(page.german, images: images), english: convert(page.english, images: images), tags: page.tags.map { tags[$0]! }) } } }