Full generation, file type cleanup

This commit is contained in:
Christoph Hagen
2024-12-25 18:06:05 +01:00
parent 41887a1401
commit 1e4682dad1
56 changed files with 1577 additions and 1103 deletions

View File

@ -27,18 +27,18 @@ struct AudioPlayerCommandProcessor: CommandProcessor {
}
guard let file = content.file(fileId) else {
results.missingFiles.insert(fileId)
results.missing(file: fileId, source: "Audio player song list")
return ""
}
guard let data = file.dataContent() else {
results.issues.insert(.failedToLoadContent)
results.inaccessibleContent(file: file)
return ""
}
let songs: [Song]
do {
songs = try JSONDecoder().decode([Song].self, from: data)
} catch {
results.issues.insert(.failedToParseContent)
results.invalidFormat(file: file, error: "Not valid JSON containing [Song]: \(error)")
return ""
}
@ -47,12 +47,12 @@ struct AudioPlayerCommandProcessor: CommandProcessor {
for song in songs {
guard let image = content.image(song.cover) else {
results.missing(file: song.cover, markdown: "Missing cover image \(song.cover) in \(file.id)")
results.missing(file: song.cover, containedIn: file)
continue
}
guard let audioFile = content.file(song.file) else {
results.missing(file: song.file, markdown: "Missing audio file \(song.file) in \(file.id)")
results.missing(file: song.cover, containedIn: file)
continue
}
#warning("Check if file is audio")
@ -79,18 +79,17 @@ struct AudioPlayerCommandProcessor: CommandProcessor {
}
let footerScript = AudioPlayerScript(items: amplitude).content
results.requiredFooters.insert(footerScript)
results.requiredHeaders.insert(.audioPlayerCss)
results.requiredHeaders.insert(.audioPlayerJs)
results.require(footer: footerScript)
results.require(headers: .audioPlayerCss, .audioPlayerJs)
results.requiredIcons.formUnion([
results.require(icons:
.audioPlayerClose,
.audioPlayerPlaylist,
.audioPlayerNext,
.audioPlayerPrevious,
.audioPlayerPlay,
.audioPlayerPause
])
)
return AudioPlayer(playingText: titleText, items: playlist).content
}

View File

@ -57,11 +57,11 @@ struct ButtonCommandProcessor: CommandProcessor {
let downloadName = arguments.count > 2 ? arguments[2].trimmed : nil
guard let file = content.file(fileId) else {
results.missing(file: fileId, markdown: markdown)
results.missing(file: fileId, source: "Download button")
return nil
}
results.files.insert(file)
results.requiredIcons.insert(.buttonDownload)
results.require(file: file)
results.require(icon: .buttonDownload)
return ContentButtons.Item(
icon: .buttonDownload,
filePath: file.absoluteUrl,
@ -80,8 +80,8 @@ struct ButtonCommandProcessor: CommandProcessor {
return nil
}
results.externalLinks.insert(rawUrl)
results.requiredIcons.insert(icon)
results.externalLink(to: rawUrl)
results.require(icon: icon)
let title = arguments[1].trimmed
@ -96,7 +96,7 @@ struct ButtonCommandProcessor: CommandProcessor {
let text = arguments[0].trimmed
let event = arguments[1].trimmed
results.requiredIcons.insert(.buttonPlay)
results.require(icon: .buttonPlay)
return .init(icon: .buttonPlay, filePath: nil, text: text, onClickText: event)
}

View File

@ -0,0 +1,75 @@
struct InlineLinkProcessor {
private let pageLinkMarker = "page:"
private let tagLinkMarker = "tag:"
private let fileLinkMarker = "file:"
let content: Content
let results: PageGenerationResults
let language: ContentLanguage
func handleLink(html: String, markdown: Substring) -> String {
let url = markdown.between("(", and: ")")
if url.hasPrefix(pageLinkMarker) {
return handleInlinePageLink(url: url, html: html, markdown: markdown)
}
if url.hasPrefix(tagLinkMarker) {
return handleInlineTagLink(url: url, html: html, markdown: markdown)
}
if url.hasPrefix(fileLinkMarker) {
return handleInlineFileLink(url: url, html: html, markdown: markdown)
}
results.externalLink(to: url)
return html
}
private func handleInlinePageLink(url: String, html: String, markdown: Substring) -> String {
// Retain links pointing to elements within a page
let textToChange = url.dropAfterFirst("#")
let pageId = textToChange.replacingOccurrences(of: pageLinkMarker, with: "")
guard let page = content.page(pageId) else {
results.missing(page: pageId, source: "Inline page link")
// Remove link since the page can't be found
return markdown.between("[", and: "]")
}
guard !page.isDraft else {
return markdown.between("[", and: "]")
}
results.linked(to: page)
let pagePath = page.absoluteUrl(in: language)
return html.replacingOccurrences(of: textToChange, with: pagePath)
}
private func handleInlineTagLink(url: String, html: String, markdown: Substring) -> String {
// Retain links pointing to elements within a page
let textToChange = url.dropAfterFirst("#")
let tagId = textToChange.replacingOccurrences(of: tagLinkMarker, with: "")
guard let tag = content.tag(tagId) else {
results.missing(tag: tagId, source: "Inline tag link")
// Remove link since the tag can't be found
return markdown.between("[", and: "]")
}
results.linked(to: tag)
let tagPath = content.absoluteUrlToTag(tag, language: language)
return html.replacingOccurrences(of: textToChange, with: tagPath)
}
private func handleInlineFileLink(url: String, html: String, markdown: Substring) -> String {
// Retain links pointing to elements within a page
let fileId = url.replacingOccurrences(of: fileLinkMarker, with: "")
guard let file = content.file(fileId) else {
results.missing(file: fileId, source: "Inline file link")
// Remove link since the file can't be found
return markdown.between("[", and: "]")
}
results.require(file: file)
let filePath = file.absoluteUrl
return html.replacingOccurrences(of: url, with: filePath)
}
}

View File

@ -23,7 +23,7 @@ struct LabelsCommandProcessor: CommandProcessor {
results.invalid(command: .labels, markdown)
return nil
}
results.requiredIcons.insert(icon)
results.require(icon: icon)
return .init(icon: icon, value: parts[1])
}
return ContentLabels(labels: labels).content