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

This commit is contained in:
upstream-mirror
2026-09-18 01:22:23 +05:00
commit 7e385fc126
8391 changed files with 1766236 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
package sass
import (
"bufio"
"encoding/json"
"fmt"
"io"
"path"
"regexp"
"strings"
"github.com/bep/godartsass/v2"
"github.com/cortezaproject/corteza/server/assets"
"github.com/cortezaproject/corteza/server/pkg/logger"
"go.uber.org/zap"
)
const (
GeneralTheme = "general"
LightTheme = "light"
DarkTheme = "dark"
SectionRoot = "root"
SectionMain = "main"
SectionTheme = "theme"
)
var (
StylesheetCache = newStylesheetCache()
sassVariablesPattern = regexp.MustCompile(`(\$[a-zA-Z_-]+):\s*([^;]+);`)
)
// DefaultCSS contains css contents from minified-custom.css and custom-css editor content
func DefaultCSS(log *zap.Logger, customCSS string) string {
var strBuilder strings.Builder
//read css contents from minified-custom.css
minifiedCSSFile, err := assets.Files(logger.Default(), "").Open(path.Join("css", "minified-custom.css"))
if err != nil {
log.Error("failed to open minified-custom.css file", zap.Error(err))
}
reader := bufio.NewReader(minifiedCSSFile)
_, err = io.Copy(&strBuilder, reader)
if err != nil {
log.Error("failed to read css content from minified-custom.css", zap.Error(err))
}
if customCSS != "" {
strBuilder.WriteString(customCSS)
}
processedCSS := strBuilder.String()
StylesheetCache.Set("default-theme", processedCSS)
return processedCSS
}
func Transpile(transpiler *godartsass.Transpiler, log *zap.Logger, themeID, themeSASS, customCSS, sassDirPath string) (err error) {
// process root section
err = processSass(transpiler, log, SectionRoot, themeID, themeSASS, "", sassDirPath)
if err != nil {
return err
}
// process main section
if themeID == LightTheme {
err = processSass(transpiler, log, SectionMain, themeID, themeSASS, customCSS, sassDirPath)
if err != nil {
return err
}
}
//process theme section
err = processSass(transpiler, log, SectionTheme, themeID, themeSASS, customCSS, sassDirPath)
if err != nil {
return err
}
return nil
}
func processSass(transpiler *godartsass.Transpiler, log *zap.Logger, section, themeID, themeSASS, customCSS, sassDirPath string) (err error) {
var (
stringsBuilder strings.Builder
isCustomCssSyntaxValid bool
)
// add theme-mode variable to the top of the section
stringsBuilder.WriteString(fmt.Sprintf("$theme-mode: %s;\n", themeID))
if themeSASS != "" {
err = jsonToSass(themeSASS, &stringsBuilder)
if err != nil {
log.Error("failed to unmarshal branding sass variables", zap.Error(err))
return err
}
}
if customCSS != "" {
_, err = transpileSass(transpiler, customCSS)
if err != nil {
log.Error("sass compilation for custom css failed", zap.Error(err))
} else {
isCustomCssSyntaxValid = true
// Get SASS variables from the custom CSS editor and give them precedence over branding variables
customVariables := sassVariablesPattern.FindAllString(customCSS, -1)
for _, customVariable := range customVariables {
stringsBuilder.WriteString(fmt.Sprintf("%s \n", customVariable))
}
}
}
//Save branding sass variables to cache
sassVariables, err := readSassFiles(log, "scss/variables")
if err != nil {
return err
}
stringsBuilder.WriteString(sassVariables)
StylesheetCache.Set("sass", stringsBuilder.String())
// start processing a section
sassSection, err := readSassFiles(log, path.Join("scss", section))
if err != nil {
return err
}
stringsBuilder.WriteString(StylesheetCache.Get("sass"))
stringsBuilder.WriteString(sassSection)
// when a user provides sets WEBAPP_SCSS_DIR_PATH environment variable
if sassDirPath != "" {
customSass, err := readSassFiles(log, sassDirPath)
if err != nil {
return err
}
stringsBuilder.WriteString(customSass)
}
if customCSS != "" && isCustomCssSyntaxValid {
//Custom CSS editor selector block
selectorBlock := sassVariablesPattern.ReplaceAllString(customCSS, "")
stringsBuilder.WriteString(selectorBlock)
}
transpiledCss, err := transpileSass(transpiler, stringsBuilder.String())
if err != nil {
log.Error("sass compilation failure", zap.Error(err))
}
// in case of sass error in custom css sass compilation,
// use compiled css from branding sass and append custom css value to it
if !isCustomCssSyntaxValid {
stringsBuilder.Reset()
stringsBuilder.WriteString(transpiledCss)
stringsBuilder.WriteString(customCSS)
// append un-compiled custom css content to transpiled css
transpiledCss = stringsBuilder.String()
}
//save the transpiled css to stylesheet cache
sectionKey := fmt.Sprintf("%s-%s", section, themeID)
StylesheetCache.Set(sectionKey, transpiledCss)
return nil
}
// transpileSass computes sass to css by the transpiler
func transpileSass(transpiler *godartsass.Transpiler, sass string) (string, error) {
args := godartsass.Args{
Source: sass,
}
execute, err := transpiler.Execute(args)
if err != nil {
return "", err
}
return execute.CSS, nil
}
func DartSassTranspiler(log *zap.Logger) *godartsass.Transpiler {
transpiler, err := godartsass.Start(godartsass.Options{
DartSassEmbeddedFilename: "sass",
})
if err != nil {
log.Warn("dart sass is not installed in your system", zap.Error(err))
return nil
}
return transpiler
}
// readSassFiles reads SASS contents from provided embedded directory and subdirectories then converts them to a string
func readSassFiles(log *zap.Logger, dirPath string) (string, error) {
var stringsBuilder strings.Builder
filenames, subDirs, err := assets.DirEntries(dirPath)
if err != nil {
log.Error(fmt.Sprintf("failed to read assets/src/%s entries", dirPath), zap.Error(err))
return "", err
}
if len(filenames) > 0 {
err := readSassContents(log, dirPath, filenames, &stringsBuilder)
if err != nil {
return "", err
}
}
if len(subDirs) > 0 {
for _, subDir := range subDirs {
sassContents, err := readSassFiles(log, path.Join(dirPath, subDir))
if err != nil {
return "", err
}
stringsBuilder.WriteString(sassContents)
}
}
return stringsBuilder.String(), nil
}
func readSassContents(log *zap.Logger, dirPath string, filenames []string, stringsBuilder *strings.Builder) error {
assetFiles := assets.Files(logger.Default(), "")
for _, fileName := range filenames {
open, err := assetFiles.Open(path.Join(dirPath, fileName))
if err != nil {
log.Error(fmt.Sprintf("failed to open asset %s file", fileName), zap.Error(err))
return err
}
reader := bufio.NewReader(open)
_, err = io.Copy(stringsBuilder, reader)
if err != nil {
log.Error(fmt.Sprintf("failed to copy sass content from %s", fileName), zap.Error(err))
return err
}
}
return nil
}
// jsonToSass converts JSON string to SASS variable assignment string
func jsonToSass(jsonStr string, strBuilder *strings.Builder) error {
var colorMap map[string]string
err := json.Unmarshal([]byte(jsonStr), &colorMap)
if err != nil {
return err
}
for key, value := range colorMap {
strBuilder.WriteString(fmt.Sprintf("$%s: %s;\n", key, value))
}
return nil
}