diff --git a/CHDataManagement.xcodeproj/project.pbxproj b/CHDataManagement.xcodeproj/project.pbxproj index 4a63198..e1e7328 100644 --- a/CHDataManagement.xcodeproj/project.pbxproj +++ b/CHDataManagement.xcodeproj/project.pbxproj @@ -127,7 +127,7 @@ E29D318B2D0B07EE0051B7F4 /* ContentBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D318A2D0B07E60051B7F4 /* ContentBox.swift */; }; E29D318E2D0B2E680051B7F4 /* PageSettingsContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D318D2D0B2E640051B7F4 /* PageSettingsContentView.swift */; }; E29D31902D0B34870051B7F4 /* GenerationAnomaly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D318F2D0B34870051B7F4 /* GenerationAnomaly.swift */; }; - E29D31942D0B7D280051B7F4 /* SvgImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31932D0B7D250051B7F4 /* SvgImage.swift */; }; + E29D31942D0B7D280051B7F4 /* SimpleImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31932D0B7D250051B7F4 /* SimpleImage.swift */; }; E29D31962D0C186E0051B7F4 /* PathSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31952D0C18690051B7F4 /* PathSettings.swift */; }; E29D31982D0C19340051B7F4 /* PathSettingsFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D31972D0C19300051B7F4 /* PathSettingsFile.swift */; }; E29D319B2D0C452B0051B7F4 /* PageIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29D319A2D0C452B0051B7F4 /* PageIssue.swift */; }; @@ -217,6 +217,8 @@ E2FE0F262D2AF9B0002963B7 /* ImageCompareCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0F252D2AF9AA002963B7 /* ImageCompareCommand.swift */; }; E2FE0F282D2AFB11002963B7 /* ImageCompare.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0F272D2AFB0A002963B7 /* ImageCompare.swift */; }; E2FE0F2A2D2AFBE6002963B7 /* ImageCompareIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0F292D2AFBE3002963B7 /* ImageCompareIcons.swift */; }; + E2FE0F2C2D2B119A002963B7 /* ImageCommandProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0F2B2D2B1196002963B7 /* ImageCommandProcessor.swift */; }; + E2FE0F312D2B1952002963B7 /* PartialSvgImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE0F302D2B1952002963B7 /* PartialSvgImage.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -336,7 +338,7 @@ E29D318A2D0B07E60051B7F4 /* ContentBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBox.swift; sourceTree = ""; }; E29D318D2D0B2E640051B7F4 /* PageSettingsContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsContentView.swift; sourceTree = ""; }; E29D318F2D0B34870051B7F4 /* GenerationAnomaly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerationAnomaly.swift; sourceTree = ""; }; - E29D31932D0B7D250051B7F4 /* SvgImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SvgImage.swift; sourceTree = ""; }; + E29D31932D0B7D250051B7F4 /* SimpleImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleImage.swift; sourceTree = ""; }; E29D31952D0C18690051B7F4 /* PathSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathSettings.swift; sourceTree = ""; }; E29D31972D0C19300051B7F4 /* PathSettingsFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathSettingsFile.swift; sourceTree = ""; }; E29D319A2D0C452B0051B7F4 /* PageIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageIssue.swift; sourceTree = ""; }; @@ -425,6 +427,8 @@ E2FE0F252D2AF9AA002963B7 /* ImageCompareCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompareCommand.swift; sourceTree = ""; }; E2FE0F272D2AFB0A002963B7 /* ImageCompare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompare.swift; sourceTree = ""; }; E2FE0F292D2AFBE3002963B7 /* ImageCompareIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompareIcons.swift; sourceTree = ""; }; + E2FE0F2B2D2B1196002963B7 /* ImageCommandProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCommandProcessor.swift; sourceTree = ""; }; + E2FE0F302D2B1952002963B7 /* PartialSvgImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialSvgImage.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -526,7 +530,7 @@ children = ( E29D31C12D0DBED70051B7F4 /* AudioPlayer */, E29D31AB2D0DA52C0051B7F4 /* Icons */, - E29D31932D0B7D250051B7F4 /* SvgImage.swift */, + E2FE0F2F2D2B18B0002963B7 /* Images */, E29D318A2D0B07E60051B7F4 /* ContentBox.swift */, E29D31882D0AED1B0051B7F4 /* ModelViewer.swift */, E29D31822D0A43D60051B7F4 /* RelatedPageLink.swift */, @@ -590,6 +594,7 @@ E29D31B62D0DAC030051B7F4 /* Page Content */ = { isa = PBXGroup; children = ( + E2FE0F2B2D2B1196002963B7 /* ImageCommandProcessor.swift */, E2FE0F252D2AF9AA002963B7 /* ImageCompareCommand.swift */, E2FE0F212D2A849B002963B7 /* VideoCommandProcessor.swift */, E2FE0F142D269188002963B7 /* PageHtmlProcessor.swift */, @@ -748,14 +753,12 @@ isa = PBXGroup; children = ( E29D311E2D0320D90051B7F4 /* ContentElements */, - E25DA58A2D020C9200AEF16D /* PageImage.swift */, E25DA51E2CFF15C100AEF16D /* NavigationBar.swift */, E2FE0EF92D25AFB5002963B7 /* PageHeader.swift */, E25DA51A2CFF08AF00AEF16D /* PostFeedPageNavigation.swift */, E2B85F422C4294F60047CD0C /* FeedEntry.swift */, E2A21C452CBAE2E50060935B /* FeedEntryContent.swift */, E2A21C272CB29B290060935B /* FeedEntryData.swift */, - E2B85F442C429ED60047CD0C /* ImageGallery.swift */, E2B85F402C4294790047CD0C /* PageHead.swift */, E25DA51C2CFF135B00AEF16D /* GenericPage.swift */, ); @@ -880,6 +883,17 @@ path = "Page Generators"; sourceTree = ""; }; + E2FE0F2F2D2B18B0002963B7 /* Images */ = { + isa = PBXGroup; + children = ( + E2FE0F302D2B1952002963B7 /* PartialSvgImage.swift */, + E2B85F442C429ED60047CD0C /* ImageGallery.swift */, + E25DA58A2D020C9200AEF16D /* PageImage.swift */, + E29D31932D0B7D250051B7F4 /* SimpleImage.swift */, + ); + path = Images; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1015,7 +1029,7 @@ E2A37D2D2CED2EF10000979F /* OptionalTextField.swift in Sources */, E2A37D2B2CED2CC30000979F /* TagDetailView.swift in Sources */, E2A21C282CB29B2A0060935B /* FeedEntryData.swift in Sources */, - E29D31942D0B7D280051B7F4 /* SvgImage.swift in Sources */, + E29D31942D0B7D280051B7F4 /* SimpleImage.swift in Sources */, E29D31632D06E95D0051B7F4 /* NavigationIcon.swift in Sources */, E22990462D10B7A7009F8D77 /* SecurityScopeStatus.swift in Sources */, E29D31512D06168E0051B7F4 /* PostListView.swift in Sources */, @@ -1124,6 +1138,7 @@ E29D31C32D0DBEF20051B7F4 /* Song.swift in Sources */, E229902A2D0F5A14009F8D77 /* DetailTitle.swift in Sources */, E29D31532D0618740051B7F4 /* AddPageView.swift in Sources */, + E2FE0F2C2D2B119A002963B7 /* ImageCommandProcessor.swift in Sources */, E2FE0F112D268E7E002963B7 /* PageCodeProcessor.swift in Sources */, E22990202D0ECBE5009F8D77 /* TagOverviewDetailView.swift in Sources */, E29D31C02D0DB9F20051B7F4 /* AudioPlayerContent.swift in Sources */, @@ -1162,6 +1177,7 @@ E2FE0F192D2723E3002963B7 /* ImageSet.swift in Sources */, E2A21C362CB9A3D70060935B /* PathSettingsView.swift in Sources */, E29D31362D0435430051B7F4 /* TabSelection.swift in Sources */, + E2FE0F312D2B1952002963B7 /* PartialSvgImage.swift in Sources */, E2FE0F262D2AF9B0002963B7 /* ImageCompareCommand.swift in Sources */, E2FE0F1E2D281AE1002963B7 /* TagOverviewGenerator.swift in Sources */, E29D31572D06D38B0051B7F4 /* AddTagView.swift in Sources */, diff --git a/CHDataManagement/Generator/Page Content/ImageCommandProcessor.swift b/CHDataManagement/Generator/Page Content/ImageCommandProcessor.swift new file mode 100644 index 0000000..33247e2 --- /dev/null +++ b/CHDataManagement/Generator/Page Content/ImageCommandProcessor.swift @@ -0,0 +1,65 @@ +struct ImageCommandProcessor: CommandProcessor { + + let commandType: ShorthandMarkdownKey = .image + + let content: Content + + let results: PageGenerationResults + + let language: ContentLanguage + + init(content: Content, results: PageGenerationResults, language: ContentLanguage) { + self.content = content + self.results = results + self.language = language + } + + private var thumbnailWidth: Int { + content.settings.pages.contentWidth + } + + private var largeImageWidth: Int { + content.settings.pages.largeImageWidth + } + + /** + Format: `![image](;]` + */ + func process(_ arguments: [String], markdown: Substring) -> String { + guard (1...2).contains(arguments.count) else { + results.invalid(command: .image, markdown) + return "" + } + let imageId = arguments[0] + + guard let image = content.image(imageId) else { + results.missing(file: imageId, source: "Image command") + return "" + } + results.used(file: image) + + if image.type == .svg || image.type == .gif { + return simple(image: image) + } + + let thumbnail = image.imageSet(width: thumbnailWidth, height: thumbnailWidth, language: language) + results.require(imageSet: thumbnail) + + let largeImage = image.imageSet(width: largeImageWidth, height: largeImageWidth, language: language) + results.require(imageSet: largeImage) + + let caption = arguments.count == 2 ? arguments[1] : nil + return PageImage( + imageId: imageId.replacingOccurrences(of: ".", with: "-"), + thumbnail: thumbnail, + largeImage: largeImage, + caption: caption).content + } + + private func simple(image: FileResource) -> String { + results.require(file: image) + let path = image.absoluteUrl + let altText = image.localized(in: language) + return SimpleImage(imagePath: path, altText: altText).content + } +} diff --git a/CHDataManagement/Generator/PageContentGenerator.swift b/CHDataManagement/Generator/PageContentGenerator.swift index 89b380d..012889e 100644 --- a/CHDataManagement/Generator/PageContentGenerator.swift +++ b/CHDataManagement/Generator/PageContentGenerator.swift @@ -27,20 +27,14 @@ final class PageContentParser { private let imageCompare: ImageCompareCommandProcessor + private let images: ImageCommandProcessor + // MARK: Other handlers private let inlineLink: InlineLinkProcessor private let code: PageCodeProcessor - var largeImageWidth: Int { - content.settings.pages.largeImageWidth - } - - var thumbnailWidth: Int { - content.settings.pages.contentWidth - } - init(content: Content, language: ContentLanguage, results: PageGenerationResults) { self.content = content self.results = results @@ -53,6 +47,7 @@ final class PageContentParser { self.html = .init(content: content, results: results, language: language) self.video = .init(content: content, results: results, language: language) self.imageCompare = .init(content: content, results: results, language: language) + self.images = .init(content: content, results: results, language: language) self.inlineLink = .init(content: content, results: results, language: language) self.code = .init(results: results) @@ -105,7 +100,7 @@ final class PageContentParser { let rawCommand = percentDecoded(markdown.between("![", and: "]").trimmed) guard rawCommand != "" else { - return handleImage(arguments, markdown: markdown) + return images.process(arguments, markdown: markdown) } guard let command = ShorthandMarkdownKey(rawValue: rawCommand) else { @@ -116,7 +111,7 @@ final class PageContentParser { switch command { case .image: - return handleImage(arguments, markdown: markdown) + return images.process(arguments, markdown: markdown) case .labels: return labelHandler.process(arguments, markdown: markdown) case .buttons: @@ -144,42 +139,6 @@ final class PageContentParser { } } - /** - Format: `![image](;]` - */ - private func handleImage(_ arguments: [String], markdown: Substring) -> String { - guard (1...2).contains(arguments.count) else { - results.invalid(command: .image, markdown) - return "" - } - let imageId = arguments[0] - - guard let image = content.image(imageId) else { - results.missing(file: imageId, source: "Image command") - return "" - } - results.used(file: image) - - - guard !image.type.isSvg else { - let path = image.absoluteUrl - let altText = image.localized(in: language) - return SvgImage(imagePath: path, altText: altText).content - } - let thumbnail = image.imageSet(width: thumbnailWidth, height: thumbnailWidth, language: language) - results.require(imageSet: thumbnail) - - let largeImage = image.imageSet(width: largeImageWidth, height: largeImageWidth, language: language) - results.require(imageSet: largeImage) - - let caption = arguments.count == 2 ? arguments[1] : nil - return PageImage( - imageId: imageId.replacingOccurrences(of: ".", with: "-"), - thumbnail: thumbnail, - largeImage: largeImage, - caption: caption).content - } - /** Format: `![page]()` */ @@ -298,7 +257,7 @@ final class PageContentParser { results.missing(file: imageId, source: "SVG command") return "" } - guard image.type.isSvg else { + guard image.type == .svg else { results.invalid(command: .svg, markdown) return "" } @@ -313,17 +272,3 @@ final class PageContentParser { .content } } - -/* -private func handleGif(file: String, altText: String) -> String { - let imagePath = page.pathRelativeToRootForContainedInputFile(file) - results.require(file: imagePath, source: page.path) - - guard let size = results.getImageSize(atPath: imagePath, source: page.path) else { - return "" - } - let width = Int(size.width) - let height = Int(size.height) - return factory.html.image(file: file, width: width, height: height, altText: altText) -} -*/ diff --git a/CHDataManagement/Main/MainView.swift b/CHDataManagement/Main/MainView.swift index 3440872..a78ffbd 100644 --- a/CHDataManagement/Main/MainView.swift +++ b/CHDataManagement/Main/MainView.swift @@ -15,7 +15,6 @@ import SFSafeSymbols - Images: Show list of generated versions **Features** - - GIF Support (No image set, don't rescale) - Files: Optional Property `customFilePath` for external files to place them in another location - Files: Property `version` and `sourceUrl` to track asset files - Posts: Generate separate pages for posts to link to diff --git a/CHDataManagement/Model/Settings/PageSettings.swift b/CHDataManagement/Model/Settings/PageSettings.swift index bd17e2e..1654c8b 100644 --- a/CHDataManagement/Model/Settings/PageSettings.swift +++ b/CHDataManagement/Model/Settings/PageSettings.swift @@ -42,6 +42,7 @@ final class PageSettings: ObservableObject { self.audioPlayerCssFile = file.audioPlayerCssFile.map { files[$0] } self.modelViewerJsFile = file.modelViewerJsFile.map { files[$0] } self.imageCompareCssFile = file.imageCompareCssFile.map { files[$0] } + self.imageCompareJsFile = file.imageCompareJsFile.map { files[$0] } } var file: PageSettingsFile { diff --git a/CHDataManagement/Page Elements/ImageGallery.swift b/CHDataManagement/Page Elements/ContentElements/Images/ImageGallery.swift similarity index 100% rename from CHDataManagement/Page Elements/ImageGallery.swift rename to CHDataManagement/Page Elements/ContentElements/Images/ImageGallery.swift diff --git a/CHDataManagement/Page Elements/PageImage.swift b/CHDataManagement/Page Elements/ContentElements/Images/PageImage.swift similarity index 100% rename from CHDataManagement/Page Elements/PageImage.swift rename to CHDataManagement/Page Elements/ContentElements/Images/PageImage.swift diff --git a/CHDataManagement/Page Elements/ContentElements/SvgImage.swift b/CHDataManagement/Page Elements/ContentElements/Images/PartialSvgImage.swift similarity index 67% rename from CHDataManagement/Page Elements/ContentElements/SvgImage.swift rename to CHDataManagement/Page Elements/ContentElements/Images/PartialSvgImage.swift index 19b7f7d..edf15af 100644 --- a/CHDataManagement/Page Elements/ContentElements/SvgImage.swift +++ b/CHDataManagement/Page Elements/ContentElements/Images/PartialSvgImage.swift @@ -26,16 +26,3 @@ struct PartialSvgImage: HtmlProducer { result += "" } } - -struct SvgImage: HtmlProducer { - - let imagePath: String - - let altText: String - - func populate(_ result: inout String) { - result += "
" - result += "\(altText)" - result += "
" - } -} diff --git a/CHDataManagement/Page Elements/ContentElements/Images/SimpleImage.swift b/CHDataManagement/Page Elements/ContentElements/Images/SimpleImage.swift new file mode 100644 index 0000000..20c48a2 --- /dev/null +++ b/CHDataManagement/Page Elements/ContentElements/Images/SimpleImage.swift @@ -0,0 +1,14 @@ + + +struct SimpleImage: HtmlProducer { + + let imagePath: String + + let altText: String + + func populate(_ result: inout String) { + result += "
" + result += "\(altText)" + result += "
" + } +}