snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
181
server/system/service/stylesheet.go
Normal file
181
server/system/service/stylesheet.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bep/godartsass/v2"
|
||||
"github.com/cespare/xxhash/v2"
|
||||
"github.com/cortezaproject/corteza/server/pkg/sass"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"go.uber.org/zap"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
stylesheet struct {
|
||||
transpiler *godartsass.Transpiler
|
||||
logger *zap.Logger
|
||||
}
|
||||
)
|
||||
|
||||
func Stylesheet(transpiler *godartsass.Transpiler, logger *zap.Logger) *stylesheet {
|
||||
return &stylesheet{
|
||||
transpiler: transpiler,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateCSS takes care of creating CSS for webapps by reading SASS content from embedded assets,
|
||||
// combining it with different themeSASS and customCSS themes, and then transpiling it using the dart-sass compiler.
|
||||
//
|
||||
// If dart sass isn't installed on the host machine, it will default to css content from the minified-custom.css which is
|
||||
// generated from [Boostrap, bootstrap-vue and custom variables sass content].
|
||||
// If dart isn't installed on the host machine, customCustom css will continue to function, but without sass support.
|
||||
//
|
||||
// In case of an error, it will return default css and log out the error
|
||||
func (svc *stylesheet) GenerateCSS(settings *types.AppSettings, sassDirPath string, log *zap.Logger) (err error) {
|
||||
var (
|
||||
studio = settings.UI.Studio
|
||||
customCSSMap = make(map[string]string)
|
||||
)
|
||||
|
||||
for _, customCSS := range studio.CustomCSS {
|
||||
customCSSMap[customCSS.ID] = customCSS.Values
|
||||
}
|
||||
|
||||
sass.DefaultCSS(log, customCSSMap[sass.GeneralTheme])
|
||||
|
||||
if studio.Themes == nil && studio.CustomCSS == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if dart sass is not installed, or when the sass transpiler creation and startup process fails.
|
||||
if !studio.SassInstalled {
|
||||
return
|
||||
}
|
||||
|
||||
// transpile sass to css for each theme
|
||||
for _, theme := range studio.Themes {
|
||||
if studio.CustomCSS == nil {
|
||||
err := sass.Transpile(svc.transpiler, log, theme.ID, theme.Values, "", sassDirPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
customCSS := processCustomCSS(theme.ID, customCSSMap)
|
||||
// transpile sass to css
|
||||
err := sass.Transpile(svc.transpiler, log, theme.ID, theme.Values, customCSS, sassDirPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (svc *stylesheet) SassInstalled() bool {
|
||||
return svc.transpiler != nil
|
||||
}
|
||||
// processCustomCSS, processes CustomCSS input and gives priority to theme specific customCSS
|
||||
func processCustomCSS(themeID string, customCSSMap map[string]string) (customCSS string) {
|
||||
var stringsBuilder strings.Builder
|
||||
|
||||
// add theme mode on customCSS
|
||||
if themeID == sass.DarkTheme {
|
||||
stringsBuilder.WriteString(fmt.Sprintf("\n[data-color-mode=\"%s\"] {\n", themeID))
|
||||
}
|
||||
|
||||
stringsBuilder.WriteString(customCSSMap[sass.GeneralTheme])
|
||||
stringsBuilder.WriteString("\n")
|
||||
stringsBuilder.WriteString(customCSSMap[themeID])
|
||||
|
||||
if themeID == sass.DarkTheme {
|
||||
stringsBuilder.WriteString("}\n")
|
||||
}
|
||||
|
||||
return stringsBuilder.String()
|
||||
}
|
||||
|
||||
// updateCSS, updates theme css when ui.studio.themes or ui.studio.custom-css settings are updated
|
||||
func (svc *stylesheet) updateCSS(current, old, compStyles *types.SettingValue, name, sassDirPath string, log *zap.Logger) {
|
||||
complimentaryStylesMap := themeMap(compStyles)
|
||||
oldThemesMap := themeMap(old)
|
||||
currentThemesMap := themeMap(current)
|
||||
|
||||
transpileSASS := func(themeID, themeSASS string, themeCustomCSS map[string]string) {
|
||||
customCSS := processCustomCSS(themeID, themeCustomCSS)
|
||||
err := sass.Transpile(svc.transpiler, log, themeID, themeSASS, customCSS, sassDirPath)
|
||||
if err != nil {
|
||||
log.Error("failed to transpile sass to css", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
for key := range currentThemesMap {
|
||||
if xxhash.Sum64String(oldThemesMap[key]) == xxhash.Sum64String(currentThemesMap[key]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if name == "ui.studio.themes" {
|
||||
transpileSASS(key, currentThemesMap[key], complimentaryStylesMap)
|
||||
continue
|
||||
}
|
||||
|
||||
if key == sass.GeneralTheme {
|
||||
if complimentaryStylesMap == nil {
|
||||
transpileSASS(sass.LightTheme, complimentaryStylesMap[sass.LightTheme], currentThemesMap)
|
||||
continue
|
||||
}
|
||||
|
||||
for themeID := range complimentaryStylesMap {
|
||||
transpileSASS(themeID, complimentaryStylesMap[themeID], currentThemesMap)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
transpileSASS(key, complimentaryStylesMap[key], currentThemesMap)
|
||||
}
|
||||
}
|
||||
|
||||
func themeMap(settingsValue *types.SettingValue) (themeMap map[string]string) {
|
||||
var themes []types.Theme
|
||||
|
||||
if settingsValue == nil {
|
||||
return themeMap
|
||||
}
|
||||
|
||||
_ = settingsValue.Value.Unmarshal(&themes)
|
||||
|
||||
themeMap = make(map[string]string)
|
||||
for _, theme := range themes {
|
||||
themeMap[theme.ID] = theme.Values
|
||||
}
|
||||
|
||||
return themeMap
|
||||
}
|
||||
|
||||
func FetchCSS() string {
|
||||
var (
|
||||
stringsBuilder strings.Builder
|
||||
rootLight = sass.StylesheetCache.Get(fmt.Sprintf("%s-%s", sass.SectionRoot, sass.LightTheme))
|
||||
)
|
||||
|
||||
if rootLight == "" {
|
||||
return sass.StylesheetCache.Get("default-theme")
|
||||
}
|
||||
|
||||
// root css section
|
||||
stringsBuilder.WriteString(rootLight)
|
||||
stringsBuilder.WriteString("\n")
|
||||
stringsBuilder.WriteString(sass.StylesheetCache.Get(fmt.Sprintf("%s-%s", sass.SectionRoot, sass.DarkTheme)))
|
||||
stringsBuilder.WriteString("\n")
|
||||
|
||||
//theme css section
|
||||
stringsBuilder.WriteString(sass.StylesheetCache.Get(fmt.Sprintf("%s-%s", sass.SectionTheme, sass.DarkTheme)))
|
||||
stringsBuilder.WriteString("\n")
|
||||
|
||||
// body css section
|
||||
stringsBuilder.WriteString(sass.StylesheetCache.Get(fmt.Sprintf("%s-%s", sass.SectionMain, sass.LightTheme)))
|
||||
stringsBuilder.WriteString("\n")
|
||||
|
||||
return stringsBuilder.String()
|
||||
}
|
||||
Reference in New Issue
Block a user