///|
/// Named render artifacts allow integrations to consume one deterministic bundle.
pub struct RenderArtifact {
name : String
format : String
content : String
} derive(Debug, Eq)
///|
pub fn RenderArtifact::new(
name : String,
format : String,
content : String,
) -> RenderArtifact {
{ name, format, content }
}
///|
pub fn RenderArtifact::bytes(self : RenderArtifact) -> Int {
self.content.length()
}
///|
pub fn RenderArtifact::file_name(self : RenderArtifact) -> String {
self.name + "." + self.format
}
///|
pub fn RenderArtifact::is_empty(self : RenderArtifact) -> Bool {
self.content == ""
}
///|
pub fn RenderArtifact::header(self : RenderArtifact) -> String {
""
}
///|
pub struct RenderBundle {
name : String
artifacts : Array[RenderArtifact]
} derive(Debug, Eq)
///|
pub fn RenderBundle::empty(name : String) -> RenderBundle {
{ name, artifacts: [] }
}
///|
pub fn RenderBundle::add(
self : RenderBundle,
artifact : RenderArtifact,
) -> RenderBundle {
let artifacts = self.artifacts
artifacts.push(artifact)
{ ..self, artifacts, }
}
///|
pub fn RenderBundle::for_brand_book(book : BrandBook) -> RenderBundle {
let bundle = RenderBundle::empty(normalize_identifier(book.name))
bundle
.add(RenderArtifact::new("brandbook", "md", book.to_markdown()))
.add(RenderArtifact::new("brandbook", "html", book.to_html()))
.add(RenderArtifact::new("theme", "json", book.to_theme_json()))
.add(RenderArtifact::new("theme", "yaml", book.to_theme_yaml()))
.add(RenderArtifact::new("theme", "css", book.to_css()))
.add(
RenderArtifact::new("tailwind", "js", book.theme_document().to_tailwind()),
)
}
///|
pub fn RenderBundle::len(self : RenderBundle) -> Int {
self.artifacts.length()
}
///|
pub fn RenderBundle::is_empty(self : RenderBundle) -> Bool {
self.artifacts.length() == 0
}
///|
pub fn RenderBundle::total_bytes(self : RenderBundle) -> Int {
self.artifacts.fold(init=0, fn(total, artifact) { total + artifact.bytes() })
}
///|
pub fn RenderBundle::formats(self : RenderBundle) -> Array[String] {
let result : Array[String] = []
for artifact in self.artifacts {
if !result.contains(artifact.format) {
result.push(artifact.format)
}
}
result
}
///|
pub fn RenderBundle::artifact(
self : RenderBundle,
name : String,
format : String,
) -> RenderArtifact? {
for artifact in self.artifacts {
if artifact.name == name && artifact.format == format {
return Some(artifact)
}
}
None
}
///|
pub fn RenderBundle::artifact_names(self : RenderBundle) -> Array[String] {
self.artifacts.map(fn(artifact) { artifact.file_name() })
}
///|
pub fn RenderBundle::manifest_markdown(self : RenderBundle) -> String {
let lines : Array[String] = [
"# Render bundle",
"",
"Name: `" + self.name + "`",
"",
"| File | Format | Bytes |",
"| --- | --- | ---: |",
]
for artifact in self.artifacts {
lines.push(
"| `" +
artifact.file_name() +
"` | " +
artifact.format +
" | " +
artifact.bytes().to_string() +
" |",
)
}
lines.push("")
lines.push("Total: " + self.total_bytes().to_string() + " bytes")
lines.join("\n")
}
///|
pub fn RenderBundle::manifest_json(self : RenderBundle) -> String {
"{\"name\":\"" +
json_escape(self.name) +
"\",\"artifacts\":[" +
self.artifacts
.map(fn(artifact) {
"{\"file\":\"" +
json_escape(artifact.file_name()) +
"\",\"format\":\"" +
json_escape(artifact.format) +
"\",\"bytes\":" +
artifact.bytes().to_string() +
"}"
})
.join(",") +
"]}"
}
///|
pub fn RenderBundle::non_empty(self : RenderBundle) -> Array[RenderArtifact] {
self.artifacts.filter(fn(artifact) { !artifact.is_empty() })
}
///|
pub fn BrandBook::render_bundle(self : BrandBook) -> RenderBundle {
RenderBundle::for_brand_book(self)
}