Add page id feature
This commit is contained in:
parent
ee1ad60b77
commit
268ab205b5
@ -255,6 +255,20 @@ struct Element {
|
||||
|
||||
extension Element {
|
||||
|
||||
/**
|
||||
The localized html file name for a language, including a leading slash.
|
||||
*/
|
||||
static func htmlPagePathAddition(for language: String) -> String {
|
||||
"/" + htmlPageName(for: language)
|
||||
}
|
||||
|
||||
/**
|
||||
The localized html file name for a language, without the leading slash.
|
||||
*/
|
||||
static func htmlPageName(for language: String) -> String {
|
||||
"\(language).html"
|
||||
}
|
||||
|
||||
var containsElements: Bool {
|
||||
!elements.isEmpty
|
||||
}
|
||||
@ -286,7 +300,30 @@ extension Element {
|
||||
The url of the top-level section of the element.
|
||||
*/
|
||||
func sectionUrl(for language: String) -> String {
|
||||
path.components(separatedBy: "/").first! + "/\(language).html"
|
||||
path.components(separatedBy: "/").first! + Element.htmlPagePathAddition(for: language)
|
||||
}
|
||||
|
||||
/**
|
||||
Create a relative link to another page in the tree.
|
||||
- Parameter pageUrl: The full page url of the target page, including localization
|
||||
- Returns: The relative url from a localized page of the element to the target page.
|
||||
*/
|
||||
func relativePathToOtherSiteElement(pageUrl: String) -> String {
|
||||
// Note: The element `path` is missing the last component
|
||||
// i.e. travel/alps instead of travel/alps/en.html
|
||||
let ownParts = path.components(separatedBy: "/")
|
||||
let pageParts = pageUrl.components(separatedBy: "/")
|
||||
|
||||
// Find the common elements of the path, which can be discarded
|
||||
var index = 0
|
||||
while pageParts[index] == ownParts[index] {
|
||||
index += 1
|
||||
}
|
||||
// The relative path needs to go down to the first common folder,
|
||||
// before going up to the target page
|
||||
let allParts = [String](repeating: "..", count: ownParts.count-index)
|
||||
+ pageParts.dropFirst(index)
|
||||
return allParts.joined(separator: "/")
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,7 +418,10 @@ extension Element {
|
||||
Returns the full path (relative to the site root for a page of the element in the given language.
|
||||
*/
|
||||
func localizedPath(for language: String) -> String {
|
||||
path != "" ? "\(path)/\(language).html" : "\(language).html"
|
||||
guard path != "" else {
|
||||
return Element.htmlPageName(for: language)
|
||||
}
|
||||
return path + Element.htmlPagePathAddition(for: language)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -440,6 +440,10 @@ final class FileSystem {
|
||||
pagePaths[id] = page
|
||||
}
|
||||
|
||||
func getPage(for id: String) -> String? {
|
||||
pagePaths[id]
|
||||
}
|
||||
|
||||
|
||||
// MARK: Writing files
|
||||
|
||||
|
@ -12,11 +12,11 @@ struct HTMLElementsGenerator {
|
||||
|
||||
// - TODO: Make link relative
|
||||
func topBarWebsiteTitle(language: String) -> String {
|
||||
"/\(language).html"
|
||||
Element.htmlPagePathAddition(for: language)
|
||||
}
|
||||
|
||||
func topBarLanguageButton(_ language: String) -> String {
|
||||
"<a href=\"\(language).html\">\(language)</a>"
|
||||
"<a href=\"\(Element.htmlPageName(for: language))\">\(language)</a>"
|
||||
}
|
||||
|
||||
func topBarNavigationLink(url: String, text: String, isActive: Bool) -> String {
|
||||
@ -46,7 +46,7 @@ struct HTMLElementsGenerator {
|
||||
func svgImage(file: String, x: Int, y: Int, width: Int, height: Int) -> String {
|
||||
"""
|
||||
<span class="image">
|
||||
<img src="\(file)#svgView(viewBox(\(x), \(y), \(width), \(height))" style="aspect-ratio:\(Float(width)/Float(height))"/>
|
||||
<img src="\(file)#svgView(viewBox(\(x), \(y), \(width), \(height)))" style="aspect-ratio:\(Float(width)/Float(height))"/>
|
||||
</span>
|
||||
"""
|
||||
}
|
||||
|
@ -27,27 +27,49 @@ struct PageContentGenerator {
|
||||
return html
|
||||
}
|
||||
let linkModifier = Modifier(target: .links) { html, markdown in
|
||||
let file = markdown.between("(", and: ")")
|
||||
if let filePath = page.nonAbsolutePathRelativeToRootForContainedInputFile(file) {
|
||||
// The target of the page link must be present after generation is complete
|
||||
files.expect(file: filePath, source: page.path)
|
||||
}
|
||||
return html
|
||||
handleLink(page: page, language: language, html: html, markdown: markdown)
|
||||
}
|
||||
let htmlModifier = Modifier(target: .html) { html, markdown in
|
||||
//print("[HTML] Found in page \(page.path):")
|
||||
//print(markdown)
|
||||
// Thinks to check
|
||||
// <img src=
|
||||
// <a href=
|
||||
//
|
||||
return html
|
||||
handleHTML(page: page, language: language, html: html, markdown: markdown)
|
||||
}
|
||||
|
||||
let parser = MarkdownParser(modifiers: [imageModifier, codeModifier, linkModifier, htmlModifier])
|
||||
return (parser.html(from: content), hasCodeContent)
|
||||
}
|
||||
|
||||
private func handleLink(page: Element, language: String, html: String, markdown: Substring) -> String {
|
||||
let file = markdown.between("(", and: ")")
|
||||
if file.hasPrefix("page:") {
|
||||
let pageId = file.replacingOccurrences(of: "page:", with: "")
|
||||
guard let pagePath = files.getPage(for: pageId) else {
|
||||
log.add(warning: "Page id '\(pageId)' not found", source: page.path)
|
||||
// Remove link since the page can't be found
|
||||
return markdown.between("[", and: "]")
|
||||
}
|
||||
let fullPath = pagePath + Element.htmlPagePathAddition(for: language)
|
||||
// Adjust file path to get the page url
|
||||
let url = page.relativePathToOtherSiteElement(pageUrl: fullPath)
|
||||
return html.replacingOccurrences(of: file, with: url)
|
||||
}
|
||||
|
||||
if let filePath = page.nonAbsolutePathRelativeToRootForContainedInputFile(file) {
|
||||
// The target of the page link must be present after generation is complete
|
||||
files.expect(file: filePath, source: page.path)
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
private func handleHTML(page: Element, language: String, html: String, markdown: Substring) -> String {
|
||||
#warning("Check HTML code in markdown for required resources")
|
||||
//print("[HTML] Found in page \(page.path):")
|
||||
//print(markdown)
|
||||
// Things to check:
|
||||
// <img src=
|
||||
// <a href=
|
||||
//
|
||||
return html
|
||||
}
|
||||
|
||||
private func processMarkdownImage(markdown: Substring, html: String, page: Element) -> String {
|
||||
// Split the markdown ![alt](file title)
|
||||
// For images: ![left_title](file right_title)
|
||||
@ -127,7 +149,7 @@ struct PageContentGenerator {
|
||||
guard let area = area else {
|
||||
return factory.html.svgImage(file: file)
|
||||
}
|
||||
let parts = area.components(separatedBy: ",")
|
||||
let parts = area.components(separatedBy: ",").map { $0.trimmed }
|
||||
guard parts.count == 4,
|
||||
let x = Int(parts[0]),
|
||||
let y = Int(parts[1]),
|
||||
|
@ -58,7 +58,7 @@ struct LocalizedSiteTemplate {
|
||||
let sections = site.sortedItems.map {
|
||||
PrefilledTopBarTemplate.SectionInfo(
|
||||
name: $0.title(for: language),
|
||||
url: "\($0.path)/\(language).html")
|
||||
url: $0.path + Element.htmlPagePathAddition(for: language))
|
||||
}
|
||||
|
||||
self.topBar = try .init(
|
||||
@ -83,7 +83,7 @@ struct LocalizedSiteTemplate {
|
||||
func makeBackLink(text: String, language: String) -> String {
|
||||
let content: [BackNavigationTemplate.Key : String] = [
|
||||
.text: text,
|
||||
.url: "../\(language).html"
|
||||
.url: ".." + Element.htmlPagePathAddition(for: language)
|
||||
]
|
||||
return backNavigation.generate(content)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user