Warn for sources in included html

This commit is contained in:
Christoph Hagen 2024-12-14 19:23:12 +01:00
parent 657f8c4ef4
commit 8a3a0f1797
6 changed files with 46 additions and 13 deletions

View File

@ -5,6 +5,7 @@ enum PageContentAnomaly {
case missingPage(page: String, markdown: String) case missingPage(page: String, markdown: String)
case missingTag(tag: String, markdown: String) case missingTag(tag: String, markdown: String)
case invalidCommand(command: ShorthandMarkdownKey?, markdown: String) case invalidCommand(command: ShorthandMarkdownKey?, markdown: String)
case warning(String)
} }
extension PageContentAnomaly: Identifiable { extension PageContentAnomaly: Identifiable {
@ -21,6 +22,8 @@ extension PageContentAnomaly: Identifiable {
return "missing-tag-\(string)" return "missing-tag-\(string)"
case .invalidCommand(_, let markdown): case .invalidCommand(_, let markdown):
return "invalid-command-\(markdown)" return "invalid-command-\(markdown)"
case .warning(let string):
return "warning-\(string)"
} }
} }
} }
@ -50,7 +53,7 @@ extension PageContentAnomaly {
switch self { switch self {
case .failedToLoadContent: case .failedToLoadContent:
return .error return .error
case .missingFile, .missingPage, .missingTag, .invalidCommand: case .missingFile, .missingPage, .missingTag, .invalidCommand, .warning:
return .warning return .warning
} }
} }
@ -70,6 +73,8 @@ extension PageContentAnomaly: CustomStringConvertible {
return "Missing tag: \(string)" return "Missing tag: \(string)"
case .invalidCommand(_, let markdown): case .invalidCommand(_, let markdown):
return "Invalid command: \(markdown)" return "Invalid command: \(markdown)"
case .warning(let string):
return "Warning: \(string)"
} }
} }
} }

View File

@ -121,11 +121,9 @@ final class PageContentParser {
private func handleHTML(_: String, markdown: Substring) -> String { private func handleHTML(_: String, markdown: Substring) -> String {
let result = String(markdown) let result = String(markdown)
#warning("Check HTML code in markdown for required resources")
findImages(in: result) findImages(in: result)
findLinks(in: result) findLinks(in: result)
findSourceSets(in: result) findSourceSets(in: result)
// Things to check: <img src= <a href= <source>
return result return result
} }
@ -138,10 +136,12 @@ final class PageContentParser {
let imgElements = try document.select("img") let imgElements = try document.select("img")
// Extract the 'src' attributes from each 'img' element // Extract the 'src' attributes from each 'img' element
let srcAttributes = try imgElements.array().compactMap { try $0.attr("src") } let srcAttributes = try imgElements.array()
.compactMap { try $0.attr("src") }
.filter { !$0.trimmed.isEmpty }
for src in srcAttributes { for src in srcAttributes {
print("Found image in html: \(src)") results.issues.insert(.warning("Found image in html: \(src)"))
} }
} catch { } catch {
print("Error parsing HTML: \(error)") print("Error parsing HTML: \(error)")
@ -157,10 +157,16 @@ final class PageContentParser {
let linkElements = try document.select("a") let linkElements = try document.select("a")
// Extract the 'src' attributes from each 'img' element // Extract the 'src' attributes from each 'img' element
let srcAttributes = try linkElements.array().compactMap { try $0.attr("href") } let srcAttributes = try linkElements.array()
.compactMap { try $0.attr("href").trimmed }
.filter { !$0.isEmpty }
for src in srcAttributes { for url in srcAttributes {
print("Found link in html: \(src)") if url.hasPrefix("http://") || url.hasPrefix("https://") {
results.externalLinks.insert(url)
} else {
results.issues.insert(.warning("Relative link in HTML: \(url)"))
}
} }
} catch { } catch {
print("Error parsing HTML: \(error)") print("Error parsing HTML: \(error)")
@ -176,10 +182,28 @@ final class PageContentParser {
let linkElements = try document.select("source") let linkElements = try document.select("source")
// Extract the 'src' attributes from each 'img' element // Extract the 'src' attributes from each 'img' element
let srcAttributes = try linkElements.array().compactMap { try $0.attr("srcset") } let srcsetAttributes = try linkElements.array()
.compactMap { try $0.attr("srcset") }
.filter { !$0.trimmed.isEmpty }
for src in srcsetAttributes {
results.issues.insert(.warning("Found source set in html: \(src)"))
}
let srcAttributes = try linkElements.array()
.compactMap { try $0.attr("src") }
.filter { !$0.trimmed.isEmpty }
for src in srcAttributes { for src in srcAttributes {
print("Found source set in html: \(src)") guard content.isValidIdForFile(src) else {
results.issues.insert(.warning("Found source in html: \(src)"))
continue
}
guard let file = content.file(src) else {
results.issues.insert(.warning("Found source in html: \(src)"))
continue
}
results.files.insert(file)
} }
} catch { } catch {
print("Error parsing HTML: \(error)") print("Error parsing HTML: \(error)")

View File

@ -1,9 +1,10 @@
import SwiftUI import SwiftUI
import SFSafeSymbols import SFSafeSymbols
#warning("Allow selection of pages as navigation bar items")
#warning("Show all warnings on page content")
#warning("Button to delete file") #warning("Button to delete file")
#warning("Fix podcast") #warning("Fix podcast")
#warning("Allow selection of pages as navigation bar items")
#warning("Add link to other language") #warning("Add link to other language")
#warning("Transfer images of posts to other language") #warning("Transfer images of posts to other language")
#warning("Show tag selection view for pages") #warning("Show tag selection view for pages")

View File

@ -32,5 +32,6 @@ struct IconButton: View {
.fill(background) .fill(background)
.padding(1)) .padding(1))
} }
.buttonStyle(.plain)
} }
} }

View File

@ -19,7 +19,7 @@ struct LocalizedPostDetailView: View {
.font(.headline) .font(.headline)
OptionalTextField("", text: $item.linkPreviewTitle, OptionalTextField("", text: $item.linkPreviewTitle,
prompt: item.title) prompt: item.title)
.textFieldStyle(.roundedBorder) .textFieldStyle(.roundedBorder)
.padding(.bottom) .padding(.bottom)
HStack { HStack {
@ -29,7 +29,7 @@ struct LocalizedPostDetailView: View {
size: 22, size: 22,
color: .blue) { color: .blue) {
showImagePicker = true showImagePicker = true
} }.padding(.bottom)
IconButton(symbol: .trashCircleFill, IconButton(symbol: .trashCircleFill,
size: 22, size: 22,

View File

@ -86,6 +86,8 @@ struct PageIssueView: View {
private var buttons: [ButtonAction] { private var buttons: [ButtonAction] {
switch issue.message { switch issue.message {
case .warning:
return [.init(name: "Retry", action: retryPageCheck)]
case .failedToLoadContent: case .failedToLoadContent:
return [.init(name: "Retry", action: retryPageCheck)] return [.init(name: "Retry", action: retryPageCheck)]
case .missingFile(let missing, _): case .missingFile(let missing, _):