{"id":17122620,"url":"https://github.com/gmac/sass-thematic","last_synced_at":"2025-10-25T06:44:33.000Z","repository":{"id":32929199,"uuid":"36524997","full_name":"gmac/sass-thematic","owner":"gmac","description":"A parser for generating dynamic theme stylesheets from Sass.","archived":false,"fork":false,"pushed_at":"2017-03-14T17:58:11.000Z","size":168,"stargazers_count":118,"open_issues_count":6,"forks_count":13,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-11T03:27:50.004Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gmac.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-29T19:35:00.000Z","updated_at":"2023-12-21T08:49:07.000Z","dependencies_parsed_at":"2022-08-02T00:59:33.666Z","dependency_job_id":null,"html_url":"https://github.com/gmac/sass-thematic","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/gmac/sass-thematic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmac%2Fsass-thematic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmac%2Fsass-thematic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmac%2Fsass-thematic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmac%2Fsass-thematic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gmac","download_url":"https://codeload.github.com/gmac/sass-thematic/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gmac%2Fsass-thematic/sbom","scorecard":{"id":430568,"data":{"date":"2025-08-11","repo":{"name":"github.com/gmac/sass-thematic","commit":"a887c15b98ec2c45452340a9bc26c5321add034a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T03:14:11.359Z","repository_id":32929199,"created_at":"2025-08-19T03:14:11.359Z","updated_at":"2025-08-19T03:14:11.359Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280917405,"owners_count":26413206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-25T02:00:06.499Z","response_time":81,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T18:23:22.940Z","updated_at":"2025-10-25T06:44:32.965Z","avatar_url":"https://github.com/gmac.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![SassThematic](title.png)\n\n**A parser for generating dynamic theme stylesheets from Sass.**\n\n* [Workflows](#workflows)\n* [Installation, Upgrade, and API](#install)\n* [Full API options](#full-api-options)\n* [Webpack integration](#webpack-builders)\n* [Gulp integration](#gulp-pipe)\n* [Credits](#credit)\n\n## The Problem:\n\nWe're building a site that gets themed with customizable colors, fonts, sizes, etc. So, we set up a base stylesheet for the site, and then maintain a separate theme stylesheet for custom style overrides.\n\n![](https://cdn2.vox-cdn.com/thumbor/URBw1hzRV7J438s5EUDF8wNszyg=/0x0:1803x1014/1400x788/filters:format(webp)/cdn0.vox-cdn.com/uploads/chorus_image/image/46706550/themes.0.0.jpg)\n\nThis works, but makes updates difficult. All changes in the base stylesheet must be mirrored in the theme-specific overrides. Keeping these stylesheets synchronized is tedious and error-prone. It would be great if we could just _automate_ the generation of these theme overrides from the base source... or, just generate a CSS template to be rendered by our application with theme variables at runtime.\n\nThis is SassThematic.\n\n## Workflows\n\nSassThematic accomodates two unique workflows for generating CSS themes – each takes a different approach to the problem. A process overview for each workflow is available on the wiki:\n\n* [Theme Override Workflow](https://github.com/gmac/sass-thematic/wiki/Theme-Override-Workflow)\n* [Theme Template Workflow](https://github.com/gmac/sass-thematic/wiki/Theme-Template-Workflow)\n\n## Install\n\nInstall the NPM package:\n\n```\nnpm install sass-thematic --save-dev\n```\n\n## Upgrading to v2.x\n\nThe v2.x API has changed significantly to better support selecting a workflow. Breaking changes:\n\n - Smaller API, tailored via options. Tree pruning no longer happens by default.\n - Webpack integration removed. Webpack plugins should independently wrap this module.\n\n## API\n\nSassThematic provides the following API. All methods take similar options, which are fully [outlined below](#full-api-options).\n\n### parseAST\n- **thematic.parseAST( options, callback )**\n- **thematic.parseASTSync( options )**\n\nParses and returns a raw abstract syntax tree of your deeply-nested Sass source. The returned object is a [gonzales-pe](https://github.com/tonyganch/gonzales-pe) node tree with all `@import` statements replaced by the imported stylesheet nodes. Use this complete source tree to make your own modifications.\n\n```javascript\nvar thematic = require('sass-thematic');\n\n// Async\nthematic.parseAST({\n  file: './styles/main.scss',\n  includePaths: ['./lib/']\n}, function(err, ast) {\n   console.log(ast);\n});\n\n// Sync\nvar ast = thematic.parseASTSync({ ...options... });\n```\n\n### parseSass\n- **thematic.parseSass( options, callback )**\n- **thematic.parseSassSync( options )**\n\nParses and returns a raw Sass string of your deeply-nested Sass source with optional transformations applied. This raw Sass may be run through the Sass compiler. Options:\n\n* `varsFile` or `varsData`: required to identify relevant theme variables.\n* `treeRemoval`: optionally removes Sass rules that do not implement theme variables.\n* `varsRemoval`: optionally removes theme variable imports.\n* `template`: optionally transforms theme variables into template identifiers.\n\n```javascript\nvar thematic = require('sass-thematic');\n\n// Async\nthematic.parseSass({\n  file: './styles/main.scss',\n  varsFile: './styles/_theme.scss',\n  includePaths: ['./lib/'],\n  treeRemoval: true,\n  varsRemoval: true,\n  template: true\n}, function(err, sassString) {\n   console.log(sassString);\n});\n\n// Sync\nvar sassString = thematic.parseSassSync({ ...options... });\n```\n\n### renderCSS\n- **thematic.renderCSS( options, callback )**\n- **thematic.renderCSSSync( options )**\n\nRenders a CSS string from your Sass source. Sass is parsed with optional transformations applied, then custom theme variables are prepended, and lastly this custom themed Sass is run through the Sass compiler. Options:\n\n* `varsFile` or `varsData`: required to identify relevant theme variables.\n* `themeFile` or `themeData`: required to provide variables for the themed CSS rendering.\n* `treeRemoval`: optionally removes Sass rules that do not implement theme variables.\n* `varsRemoval`: optionally removes theme variable imports.\n* `sassOptions`: options object passed to the Node-Sass compiler.\n\n```javascript\nvar thematic = require('sass-thematic');\n\n// Async\nthematic.renderCSS({\n  file: './styles/main.scss',\n  varsFile: './styles/_theme.scss',\n  themeData: '$color1: red; $color2: green;',\n  includePaths: ['./lib/']\n}, function(err, cssString) {\n   console.log(cssString);\n});\n\n// Sync\nvar cssString = thematic.renderCSSSync({ ...options... });\n```\n\n### renderTemplate\n- **thematic.renderTemplate( options, callback )**\n- **thematic.renderTemplateSync( options )**\n\nRenders a CSS template string from your Sass source. Sass is parsed with theme variables preserved as identifiers (and other optional transformations applied), then CSS is compiled from the transformed source, and lastly field identifiers are filled back in with template interpolation fields. Options:\n\n* `varsFile` or `varsData`: required to identify relevant theme variables.\n* `treeRemoval`: optionally removes Sass rules that do not implement theme variables.\n* `varsRemoval`: optionally removes theme variable imports.\n* `templateOpen`: token used to open template interpolation fields (ie: `\u003c%=`).\n* `templateClose`: token used to close template interpolation fields (ie: `%\u003e`).\n* `templateSnakeCase`: formats all variable names as `snake_case` (lowercase with underscores).\n* `sassOptions`: options object passed to the Node-Sass compiler.\n\nNote: theme variable names must pass through the Sass compiler as literal string identifiers, therefore [restrictions apply](https://github.com/gmac/sass-thematic/wiki/Theme-Template-Workflow#restrictions) on how theme variables may be used in pre-rendered Sass contexts.\n\n```javascript\nvar thematic = require('sass-thematic');\n\n// Async\nthematic.renderTemplate({\n  file: './styles/main.scss',\n  varsFile: './styles/_theme.scss',\n  includePaths: ['./lib/'],\n  templateOpen: '\u003c%=',\n  templateClose: '%\u003e'\n}, function(err, templateString) {\n   console.log(templateString);\n});\n\n// Sync\nvar templateString = thematic.renderTemplateSync({ ...options... });\n```\n\n## Parser API\n\nThe primary API above is designed to accomodate common use-cases. However, custom build tools may want to take advantage of the underlying [parser API](https://github.com/gmac/sass-thematic/wiki/Parser-API), documented on the wiki.\n\n## Full API Options\n\n#### Required for all methods, one or both:\n\n* **`file`**: String. Path to the main Sass file to load and parse. This may be an absolute path, or else a relative path from `cwd`.\n\n* **`data`**: String. A raw Sass string to parse. You may still provide a `file` option as filepath context for mapping imports.\n\n#### Required for Sass parsing methods, one of:\n\n* **`varsFile`**: String. Path to a file containing all theme variables. This may be an absolute path, or else a relative path from `cwd`. This file must contain all theme variable definitions, and nothing else. Variables may be formatted as Sass or JSON.\n\n* **`varsData`**: String. Data containing variable definitions for all theme variables. Should be formatted as Sass (`$color1: red; $color2: black;`) or JSON (`{\"color1\": \"red\", \"color2\": \"black\"}`).\n\n#### Required for CSS rendering methods, one of:\n\n* **`themeFile`**: String. Path to a file containing all theme variables to render CSS with. This may be an absolute path, or else a relative path from `cwd`.\n\n* **`themeData`**: String. Data containing Sass variable definitions for all theme variables rendered into CSS. Should be formatted as Sass (`$color1: red; $color2: black;`) or JSON (`{\"color1\": \"red\", \"color2\": \"black\"}`).\n\n#### Optional options:\n\n* **`includePaths`**: Array. List of base paths to search while performing file lookups. These should be absolute directory paths, or else relative to `cwd`. This operates just like the `node-sass` option of the same name.\n\n* **`cwd`**: String. Path of the directory to resolve `file`, `varsFile`, `themeFile`,  and `includePaths` references from. Uses `process.cwd()` by default.\n\n* **`treeRemoval`**: Boolean. Enables the removal of tree nodes that do not implement theme variables.\n\n* **`varsRemoval`**: Boolean. Enables the removal of theme variable imports. Be sure to use the Sass `!default` flag when leaving theme variable imports in the source tree.\n\n* **`templateOpen`**: String. The opening token for template interpolation fields. Uses ERB-style `\u003c%=` by default.\n\n* **`templateClose`**: String. The closing token for template interpolation fields. Uses ERB-style `%\u003e` by default.\n\n* **`templateSnakeCase`**: Boolean. Enables the transformation of template variable names into `snake_case` (lowercase with underscores).\n\n* **`fieldOpen`**: String. The opening token wrapping field literals that get sent through the Sass compiler. Uses `____` (four underscores) by default.\n\n* **`fieldClose`**: String. The closing token wrapping field literals that get sent through the Sass compiler. Uses `____` (four underscores) by default.\n\n* **`sassOptions`**: Object. For rendering methods, this options object is passed through to the Sass compiler. See [node-sass](https://www.npmjs.com/package/node-sass) docs for possible values.\n\n## Webpack Builders\n\nAs of v2.x, Webpack integration has been broken out into wrapper modules. Build objectives vary, therefore SassThematic remains unopinionated about how it hooks into a build pipeline. The following Webpack wrappers exist:\n\n- [sass-theme-template-loader](https://github.com/gmac/sass-theme-template-loader): compiles CSS templates with theme variables as interpolation fields.\n- [sass-thematic-override-plugin](https://github.com/gmac/sass-thematic/blob/v1.3.0/lib/webpack-plugin.js): a live-compiler for theme overrides included in SassThematic v1.3. No longer supported, but available if anyone wants to spin it into a community project.\n\n## Gulp Pipe\n\nIt's pretty simple to setup a Gulp pipe that hooks multiple Sass entry point files into SassThematic. Use the following as a basic template:\n\n```javascript\nvar gulp = require('gulp');\nvar vinyl = require('vinyl');\nvar through2 = require('through2');\nvar thematic = require('sass-thematic');\n\n// SassThematic Gulp pipe:\nfunction sassTheme(opts) {\n  var output = '';\n  return through2.obj(function(file, enc, done) {\n      opts.file = file.path;\n      opts.data = file.contents.toString('utf-8');\n\n      thematic.parseSass(opts, function(err, result) {\n        output += result;\n        done();\n      });\n    },\n    function(done) {\n      this.push(new vinyl({\n        path: 'theme.scss',\n        contents: new Buffer(output)\n      }));\n      done();\n    });\n}\n\n// Then use it...\ngulp.task('theme', function() {\n  return gulp.src('components/**/index.scss')\n    .pipe(sassTheme({ ... opts ...}))\n    .pipe(gulp.dest('/path/to/output/dir'));\n});\n```\n\n## Credit\n\nThis toolkit would be impossible without the hard work of [@tonyganch](https://github.com/tonyganch) on the [gonzales-pe](https://github.com/tonyganch/gonzales-pe) lexer, which provides the framework for intelligently dismantling Sass. Serious kudos.\n\nBrought to you by [Vox Media](http://voxmedia.com). \u003cimg src=\"http://fonts.voxmedia.com/emoji/voxmedia.png\" alt=\"\" width=\"15\" height=\"15\" style=\"width:15px;\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmac%2Fsass-thematic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgmac%2Fsass-thematic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgmac%2Fsass-thematic/lists"}