Determine required files from custom HTML
This commit is contained in:
@@ -156,15 +156,18 @@ struct HtmlCommand: CommandProcessor {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if findFile(withAbsolutePath: path) {
|
if findFile(withAbsolutePath: path) {
|
||||||
|
// File marked as required
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileId = path.dropBeforeLast("/")
|
results.requiredOutput(path.withLeadingSlashRemoved, source: "HTML: \(source)")
|
||||||
if content.isValidIdForFile(fileId) {
|
|
||||||
results.missing(file: fileId, source: "HTML: \(source)")
|
// let fileId = path.dropBeforeLast("/")
|
||||||
} else {
|
// if content.isValidIdForFile(fileId) {
|
||||||
results.warning("Could not find file '\(path)' for \(source)")
|
// results.missing(file: fileId, source: "HTML: \(source)")
|
||||||
}
|
// } else {
|
||||||
|
// results.warning("Could not find file '\(path)' for \(source)")
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private func findFile(withAbsolutePath absolutePath: String) -> Bool {
|
private func findFile(withAbsolutePath absolutePath: String) -> Bool {
|
||||||
|
|||||||
@@ -49,12 +49,17 @@ final class GenerationResults: ObservableObject {
|
|||||||
@Published
|
@Published
|
||||||
var emptyPages: Set<LocalizedPageId> = []
|
var emptyPages: Set<LocalizedPageId> = []
|
||||||
|
|
||||||
|
/// The paths to the files in the output folder, without leading slashes
|
||||||
@Published
|
@Published
|
||||||
var outputFiles: Set<String> = []
|
var outputFiles: Set<String> = []
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var unusedFilesInOutput: Set<String> = []
|
var unusedFilesInOutput: Set<String> = []
|
||||||
|
|
||||||
|
/// The paths to files required to be in the output folder, without leading slashes
|
||||||
|
@Published
|
||||||
|
var requiredOutputFiles: Set<String> = []
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The url redirects to install to prevent broken links.
|
The url redirects to install to prevent broken links.
|
||||||
|
|
||||||
@@ -126,6 +131,7 @@ final class GenerationResults: ObservableObject {
|
|||||||
self.redirects = [:]
|
self.redirects = [:]
|
||||||
self.outputFiles = []
|
self.outputFiles = []
|
||||||
self.unusedFilesInOutput = []
|
self.unusedFilesInOutput = []
|
||||||
|
self.requiredOutputFiles = []
|
||||||
}
|
}
|
||||||
for result in cache.values {
|
for result in cache.values {
|
||||||
result.reset()
|
result.reset()
|
||||||
@@ -257,10 +263,26 @@ final class GenerationResults: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func determineFiles(unusedIn existingFiles: Set<String>) {
|
func determineFiles(unusedIn existingFiles: Set<String>) {
|
||||||
let unused = existingFiles.subtracting(outputFiles)
|
// All paths with leading without leading slashes
|
||||||
|
let unused = existingFiles.subtracting(outputFiles).subtracting(requiredOutputFiles)
|
||||||
update { self.unusedFilesInOutput = unused }
|
update { self.unusedFilesInOutput = unused }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func determineMissingRequiredFiles(existingFiles: Set<String>) {
|
||||||
|
// All paths with leading without leading slashes
|
||||||
|
|
||||||
|
// Check the files required in the output against the existing files,
|
||||||
|
// and flag missing ones
|
||||||
|
let externalFilePaths = self.externalFiles.map { $0.absoluteUrl.withLeadingSlashRemoved }
|
||||||
|
let fullFiles = existingFiles.union(externalFilePaths)
|
||||||
|
let missing = requiredOutputFiles.filter { path in
|
||||||
|
!fullFiles.contains(path) &&
|
||||||
|
!fullFiles.contains(path + ".html") &&
|
||||||
|
!fullFiles.contains(path + "/1.html")
|
||||||
|
}
|
||||||
|
update { self.requiredOutputFiles = missing }
|
||||||
|
}
|
||||||
|
|
||||||
func sources(forMissingPage page: String) -> [(page: LocalizedItemId, source: String)] {
|
func sources(forMissingPage page: String) -> [(page: LocalizedItemId, source: String)] {
|
||||||
var all = [(page: LocalizedItemId, source: String)]()
|
var all = [(page: LocalizedItemId, source: String)]()
|
||||||
for (id, results) in cache {
|
for (id, results) in cache {
|
||||||
@@ -272,6 +294,10 @@ final class GenerationResults: ObservableObject {
|
|||||||
}
|
}
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func requiredOutputFile(_ path: String) {
|
||||||
|
update { self.requiredOutputFiles.insert(path) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Dictionary where Value == Set<LocalizedItemId> {
|
private extension Dictionary where Value == Set<LocalizedItemId> {
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ final class PageGenerationResults: ObservableObject {
|
|||||||
@Published
|
@Published
|
||||||
private(set) var unsavedOutputFiles: [String: Set<ItemReference>] = [:]
|
private(set) var unsavedOutputFiles: [String: Set<ItemReference>] = [:]
|
||||||
|
|
||||||
|
/// The files that need to be present in the output folder
|
||||||
|
@Published
|
||||||
|
private(set) var requiredOutputFiles: [String: Set<String>] = [:]
|
||||||
|
|
||||||
private(set) var pageIsEmpty: Bool
|
private(set) var pageIsEmpty: Bool
|
||||||
|
|
||||||
private(set) var redirect: (originalUrl: String, newUrl: String)?
|
private(set) var redirect: (originalUrl: String, newUrl: String)?
|
||||||
@@ -120,6 +124,7 @@ final class PageGenerationResults: ObservableObject {
|
|||||||
invalidBlocks = []
|
invalidBlocks = []
|
||||||
warnings = []
|
warnings = []
|
||||||
unsavedOutputFiles = [:]
|
unsavedOutputFiles = [:]
|
||||||
|
requiredOutputFiles = [:]
|
||||||
pageIsEmpty = false
|
pageIsEmpty = false
|
||||||
redirect = nil
|
redirect = nil
|
||||||
}
|
}
|
||||||
@@ -151,6 +156,7 @@ final class PageGenerationResults: ObservableObject {
|
|||||||
self.invalidBlocks = []
|
self.invalidBlocks = []
|
||||||
self.warnings = []
|
self.warnings = []
|
||||||
self.unsavedOutputFiles = [:]
|
self.unsavedOutputFiles = [:]
|
||||||
|
self.requiredOutputFiles = [:]
|
||||||
self.pageIsEmpty = false
|
self.pageIsEmpty = false
|
||||||
self.redirect = nil
|
self.redirect = nil
|
||||||
}
|
}
|
||||||
@@ -258,6 +264,11 @@ final class PageGenerationResults: ObservableObject {
|
|||||||
onMain { self.requiredIcons.formUnion(icons) }
|
onMain { self.requiredIcons.formUnion(icons) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func requiredOutput(_ path: String, source: String) {
|
||||||
|
onMain { self.requiredOutputFiles[path, default: []].insert(source) }
|
||||||
|
delegate.requiredOutputFile(path)
|
||||||
|
}
|
||||||
|
|
||||||
func linked(to page: Page) {
|
func linked(to page: Page) {
|
||||||
onMain { self.linkedPages.insert(page) }
|
onMain { self.linkedPages.insert(page) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,7 +387,9 @@ extension Content {
|
|||||||
private func updateUnusedFiles() {
|
private func updateUnusedFiles() {
|
||||||
let existing = storage.getAllOutputFiles()
|
let existing = storage.getAllOutputFiles()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
self.results.determineMissingRequiredFiles(existingFiles: existing)
|
||||||
self.results.determineFiles(unusedIn: existing)
|
self.results.determineFiles(unusedIn: existing)
|
||||||
|
self.results.objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,10 @@ struct GenerationContentView: View {
|
|||||||
Button("Delete", action: { delete(unusedFile: filePath) })
|
Button("Delete", action: { delete(unusedFile: filePath) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenerationStringIssuesView(
|
||||||
|
text: "missing output files",
|
||||||
|
statusWhenNonEmpty: .warning,
|
||||||
|
items: content.results.requiredOutputFiles)
|
||||||
GenerationStringIssuesView(
|
GenerationStringIssuesView(
|
||||||
text: "inaccessible files",
|
text: "inaccessible files",
|
||||||
items: content.results.inaccessibleFiles) { $0.identifier }
|
items: content.results.inaccessibleFiles) { $0.identifier }
|
||||||
|
|||||||
Reference in New Issue
Block a user