import Foundation import Ink struct PageContentGenerator { private let files: FileProcessor init(files: FileProcessor) { self.files = files } func generate(page: Page, language: String, at url: URL) throws -> String { var errorToThrow: Error? = nil let content = try wrap(.missingPage(page: url.path, language: language)) { try String(contentsOf: url) } var hasCodeContent = false let imageModifier = Modifier(target: .images) { html, markdown in let result = processMarkdownImage(markdown: markdown, html: html, page: page) switch result { case .success(let content): return content case .failure(let error): errorToThrow = error return "" } } let codeModifier = Modifier(target: .codeBlocks) { html, markdown in if markdown.starts(with: "```swift") { #warning("Syntax highlight swift code") return html } hasCodeContent = true return html } let parser = MarkdownParser(modifiers: [imageModifier, codeModifier]) #warning("Check links in markdown for (missing) files to copy") if hasCodeContent { #warning("Automatically add hljs hightlighting if code samples are found") } let result = parser.html(from: content) if let error = errorToThrow { throw error } return result } private func processMarkdownImage(markdown: Substring, html: String, page: Page) -> Result { let fileAndTitle = markdown .components(separatedBy: "(").last! .components(separatedBy: ")").first! let file = fileAndTitle.components(separatedBy: " \"").first! // Remove title let rightSubtitle: String? if fileAndTitle.contains(" \"") { rightSubtitle = fileAndTitle.dropBeforeFirst("\"").dropAfterLast("\"") } else { rightSubtitle = nil } let leftSubtitle = markdown .components(separatedBy: "]").first! .components(separatedBy: "[").last!.nonEmpty #warning("Specify page image width in configuration") let pageImageWidth = 748 let size: NSSize let imagePath = page.pathRelativeToRootForContainedInputFile(file) do { size = try files.requireImage( source: imagePath, destination: imagePath, width: pageImageWidth, desiredHeight: nil, createDoubleVersion: true) } catch { return .failure(error) } let file2x = file.insert("@2x", beforeLast: ".") #warning("Move HTML code to single location") let result = articelImage( image: file, image2x: file2x, width: size.width, height: size.height, rightSubtitle: rightSubtitle, leftSubtitle: leftSubtitle) return .success(result) } private func articelImage(image: String, image2x: String, width: CGFloat, height: CGFloat, rightSubtitle: String?, leftSubtitle: String?) -> String { let subtitleCode = subtitle(left: leftSubtitle, right: rightSubtitle) return fullImageCode(image: image, image2x: image2x, width: width, height: height, subtitle: subtitleCode) } private func articleImageWithoutSubtitle(image: String, image2x: String, width: CGFloat, height: CGFloat) -> String { """ """ } private func subtitle(left: String?, right: String?) -> String { guard left != nil || right != nil else { return "" } let leftCode = left.unwrapped { "\($0)" } ?? "" let rightCode = right.unwrapped { "\($0)" } ?? "" return """
\(leftCode) \(rightCode)
""" } private func fullImageCode(image: String, image2x: String, width: CGFloat, height: CGFloat, subtitle: String) -> String { """ \(subtitle) """ } }