Support GIFs
This commit is contained in:
parent
ac7fbdd638
commit
c78c359819
@ -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 = "<group>"; };
|
||||
E29D318D2D0B2E640051B7F4 /* PageSettingsContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageSettingsContentView.swift; sourceTree = "<group>"; };
|
||||
E29D318F2D0B34870051B7F4 /* GenerationAnomaly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerationAnomaly.swift; sourceTree = "<group>"; };
|
||||
E29D31932D0B7D250051B7F4 /* SvgImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SvgImage.swift; sourceTree = "<group>"; };
|
||||
E29D31932D0B7D250051B7F4 /* SimpleImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleImage.swift; sourceTree = "<group>"; };
|
||||
E29D31952D0C18690051B7F4 /* PathSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathSettings.swift; sourceTree = "<group>"; };
|
||||
E29D31972D0C19300051B7F4 /* PathSettingsFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathSettingsFile.swift; sourceTree = "<group>"; };
|
||||
E29D319A2D0C452B0051B7F4 /* PageIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageIssue.swift; sourceTree = "<group>"; };
|
||||
@ -425,6 +427,8 @@
|
||||
E2FE0F252D2AF9AA002963B7 /* ImageCompareCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompareCommand.swift; sourceTree = "<group>"; };
|
||||
E2FE0F272D2AFB0A002963B7 /* ImageCompare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompare.swift; sourceTree = "<group>"; };
|
||||
E2FE0F292D2AFBE3002963B7 /* ImageCompareIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompareIcons.swift; sourceTree = "<group>"; };
|
||||
E2FE0F2B2D2B1196002963B7 /* ImageCommandProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCommandProcessor.swift; sourceTree = "<group>"; };
|
||||
E2FE0F302D2B1952002963B7 /* PartialSvgImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialSvgImage.swift; sourceTree = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
E2FE0F2F2D2B18B0002963B7 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2FE0F302D2B1952002963B7 /* PartialSvgImage.swift */,
|
||||
E2B85F442C429ED60047CD0C /* ImageGallery.swift */,
|
||||
E25DA58A2D020C9200AEF16D /* PageImage.swift */,
|
||||
E29D31932D0B7D250051B7F4 /* SimpleImage.swift */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* 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 */,
|
||||
|
@ -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: ` -> 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
|
||||
}
|
||||
}
|
@ -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: ` -> 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: ``
|
||||
*/
|
||||
@ -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)
|
||||
}
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -26,16 +26,3 @@ struct PartialSvgImage: HtmlProducer {
|
||||
result += "</span>"
|
||||
}
|
||||
}
|
||||
|
||||
struct SvgImage: HtmlProducer {
|
||||
|
||||
let imagePath: String
|
||||
|
||||
let altText: String
|
||||
|
||||
func populate(_ result: inout String) {
|
||||
result += "<div class='content-image svg-image'>"
|
||||
result += "<img src='\(imagePath)' loading='lazy' alt='\(altText)'/>"
|
||||
result += "</div>"
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
struct SimpleImage: HtmlProducer {
|
||||
|
||||
let imagePath: String
|
||||
|
||||
let altText: String
|
||||
|
||||
func populate(_ result: inout String) {
|
||||
result += "<div class='content-image svg-image'>"
|
||||
result += "<img src='\(imagePath)' loading='lazy' alt='\(altText)'/>"
|
||||
result += "</div>"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user