Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom CSS Capability #315

Merged
merged 10 commits into from
Oct 11, 2023
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,16 @@ and limitations for this exporter.
The look and feel of the generated site can be customized with several additional view properties in the C4
architecture model:

| Property name | Description | Default | Example |
|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|---------------------|
| `generatr.style.colors.primary` | Primary site color, used for header bar background and active menu background. | `#333333` | `#485fc7` |
| `generatr.style.colors.secondary` | Secondary site color, used for font color in header bar and for active menu. | `#cccccc` | `#ffffff` |
| `generatr.style.faviconPath` | Site logo location relative to the configured `assets` folder. When configured, the logo image will be place on the left side in the header bar. This requires the `--assets-dir` switch when generating the site and the corresponding file to be available in the `assets` folder. | | `site/favicon.ico` |
| `generatr.style.logoPath` | Site favicon location relative to the configured `assets` folder. When configured, the favicon will be set for all generated pages. This requires the `--assets-dir` switch when generating the site and the corresponding file to be available in the `assets` folder. | | `site/logo.png` |
| `generatr.search.language` | Indexing/stemming language for the search index. See [Lunr language support](https://github.com/olivernn/lunr-languages) | `en` | `nl` |
| `generatr.markdown.flexmark.extensions` | Additional extensions to the markdown generator to add new markdown capabilities. [More Details](https://avisi-cloud.github.io/structurizr-site-generatr/main/extended-markdown-features/) | Tables | `Tables,Admonition` |
| `generatr.svglink.target` | Specifies the link target for element links in the exported svg | `_top` | `_self` |
| Property name | Description | Default | Example |
|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|------------------------------------------------------|
| `generatr.style.colors.primary` | Primary site color, used for header bar background and active menu background. | `#333333` | `#485fc7` |
| `generatr.style.colors.secondary` | Secondary site color, used for font color in header bar and for active menu. | `#cccccc` | `#ffffff` |
| `generatr.style.faviconPath` | Site logo location relative to the configured `assets` folder. When configured, the logo image will be place on the left side in the header bar. This requires the `--assets-dir` switch when generating the site and the corresponding file to be available in the `assets` folder. | | `site/favicon.ico` |
| `generatr.style.logoPath` | Site favicon location relative to the configured `assets` folder. When configured, the favicon will be set for all generated pages. This requires the `--assets-dir` switch when generating the site and the corresponding file to be available in the `assets` folder. | | `site/logo.png` |
| `generatr.style.customStylesheet` | URL to hosted custom stylesheet or path to custom stylesheet file (location relative to the configured `assets` folder). When configured this css file will be loaded for all pages. When using a path to a file the `--assets-dir` switch must be used when generating the site and the corresponding file is available in the `assets` folder. | | `site/custom.css` or 'https://uri.example/custom.css |
| `generatr.search.language` | Indexing/stemming language for the search index. See [Lunr language support](https://github.com/olivernn/lunr-languages) | `en` | `nl` |
| `generatr.markdown.flexmark.extensions` | Additional extensions to the markdown generator to add new markdown capabilities. [More Details](https://avisi-cloud.github.io/structurizr-site-generatr/main/extended-markdown-features/) | Tables | `Tables,Admonition` |
| `generatr.svglink.target` | Specifies the link target for element links in the exported svg | `_top` | `_self` |


See the included example for usage of some those properties in the
Expand Down
12 changes: 12 additions & 0 deletions docs/example/assets/site/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
svg g g[id^="link"]:hover path {
stroke:#FF0000 !important;
stroke-width: 2.0;
}

svg g g[id^="link"]:hover polygon {
stroke:#FF0000 !important;
}

svg g g[id^="link"]:hover text {
fill:#FF0000 !important;
}
2 changes: 2 additions & 0 deletions docs/example/workspace.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
"generatr.style.colors.secondary" "#ffffff"
"generatr.style.faviconPath" "site/favicon.ico"
"generatr.style.logoPath" "site/logo.png"
"generatr.style.customStylesheet" "site/custom.css"
//"generatr.style.customStylesheet" "https://example.com/custom.css"
"generatr.svglink.target" "_self"

// full list of available "generatr.markdown.flexmark.extensions"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package nl.avisi.structurizr.site.generatr.site.model

import nl.avisi.structurizr.site.generatr.site.GeneratorContext

class CustomStylesheetViewModel(generatorContext: GeneratorContext) {
val resourceURI = getResourceURI(generatorContext)
val includeCustomStylesheet = resourceURI != null

private fun getResourceURI(generatorContext: GeneratorContext): String? {
val stylesheet = generatorContext.workspace.views.configuration.properties
.getOrDefault(
"generatr.style.customStylesheet",
null
)

if (stylesheet != null) {
return if (stylesheet.lowercase().startsWith("http")) stylesheet else "./$stylesheet"
}

return null
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ abstract class PageViewModel(protected val generatorContext: GeneratorContext) {
pageSubTitle
}
val favicon by lazy { FaviconViewModel(generatorContext, this) }
val customStylesheet by lazy { CustomStylesheetViewModel(generatorContext) }
val headerBar by lazy { HeaderBarViewModel(this, generatorContext) }
val menu by lazy { MenuViewModel(generatorContext, this) }
val includeAutoReloading = generatorContext.serving

val flexmarkConfig by lazy {
buildFlexmarkConfig(generatorContext)
}
val flexmarkConfig by lazy { buildFlexmarkConfig(generatorContext) }
val includeAdmonition = flexmarkConfig.selectedExtensionMap.containsKey("Admonition")
val includeKatex = flexmarkConfig.selectedExtensionMap.containsKey("GitLab")

val configuration = generatorContext.workspace.views.configuration.properties

abstract val url: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,10 @@ private fun HTML.headFragment(viewModel: PageViewModel) {
meta(name = "viewport", content = "width=device-width, initial-scale=1")
title { +viewModel.pageTitle }
link(rel = "stylesheet", href = "https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css")
link(
rel = "stylesheet",
href = "../" + "/style.css".asUrlToFile(viewModel.url)
)
link(
rel = "stylesheet",
href = "./" + "/style-branding.css".asUrlToFile(viewModel.url)
)
link(rel = "stylesheet", href = "../" + "/style.css".asUrlToFile(viewModel.url))
link(rel = "stylesheet", href = "./" + "/style-branding.css".asUrlToFile(viewModel.url))

if (viewModel.includeAdmonition)
if (viewModel.includeAdmonition)
markdownAdmonitionStylesheet(viewModel)

if (viewModel.includeKatex)
Expand All @@ -42,6 +36,9 @@ private fun HTML.headFragment(viewModel: PageViewModel) {

if (viewModel.includeAutoReloading)
autoReloadScript(viewModel)

if (viewModel.customStylesheet.includeCustomStylesheet)
link(rel = "stylesheet", href = viewModel.customStylesheet.resourceURI)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nl.avisi.structurizr.site.generatr.site.model

import assertk.assertThat
import assertk.assertions.isEqualTo
import org.junit.jupiter.api.Test

class CustomStylesheetViewModelTest : ViewModelTest() {
private val generatorContext = generatorContext()

@Test
fun `Configuration Property Missing`() {
val customStylesheetViewModel = CustomStylesheetViewModel(generatorContext)
assertThat(customStylesheetViewModel.resourceURI).isEqualTo(null)
}

@Test
fun `Configuration Property Set To URL`() {
generatorContext.workspace.views.configuration.addProperty("generatr.style.customStylesheet","http://example.uri/custom.css")
val customStylesheetViewModel = CustomStylesheetViewModel(generatorContext)
assertThat(customStylesheetViewModel.resourceURI).isEqualTo("http://example.uri/custom.css")
}

@Test
fun `Configuration Property Set To Local File`() {
generatorContext.workspace.views.configuration.addProperty("generatr.style.customStylesheet","custom.css")
val customStylesheetViewModel = CustomStylesheetViewModel(generatorContext)
assertThat(customStylesheetViewModel.resourceURI).isEqualTo("./custom.css")
}
}