Skip to content

Commit

Permalink
Add support for a custom stylesheet (#315)
Browse files Browse the repository at this point in the history
* Add the ability to supply your own custom css file

* Added reference to new property in readme file.

* Moved the loading of the custom CSS to be the last item in the header so you can override css for FlexMark plugins also. Also a small bit of code cleanup

* Add support for customer CSS to be either a local file or a hosted file

* Change from customCSS to customStylesheet

* Change from customCSS to customStylesheet ( readme file )

* move view logic to modal and simplify code.

* Added tests and fixed example property in the workspace.dsl

* removed obsolete './'
  • Loading branch information
qtzar committed Oct 11, 2023
1 parent fc3b8c5 commit bc3d80f
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 23 deletions.
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")
}
}

0 comments on commit bc3d80f

Please sign in to comment.