{"id":13621787,"url":"https://github.com/jsverse/variabless","last_synced_at":"2025-04-12T21:24:05.473Z","repository":{"id":49048468,"uuid":"316807711","full_name":"jsverse/variabless","owner":"jsverse","description":"JS \u0026 CSS - A Match Made in Heaven 💎","archived":false,"fork":false,"pushed_at":"2024-05-10T10:38:16.000Z","size":2546,"stargazers_count":79,"open_issues_count":2,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-12T07:21:52.245Z","etag":null,"topics":["css","cssvariables","javascript","webpack"],"latest_commit_sha":null,"homepage":"https://ngneat.github.io/variabless/","language":"HTML","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/jsverse.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-28T19:32:27.000Z","updated_at":"2024-11-15T09:14:37.000Z","dependencies_parsed_at":"2024-11-07T01:00:30.735Z","dependency_job_id":null,"html_url":"https://github.com/jsverse/variabless","commit_stats":{"total_commits":35,"total_committers":3,"mean_commits":"11.666666666666666","dds":"0.11428571428571432","last_synced_commit":"0826fd3ff049704c9fc6f3423f991c3833c0baef"},"previous_names":["ngneat/variabless"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsverse%2Fvariabless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsverse%2Fvariabless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsverse%2Fvariabless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsverse%2Fvariabless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsverse","download_url":"https://codeload.github.com/jsverse/variabless/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248633079,"owners_count":21136799,"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","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":["css","cssvariables","javascript","webpack"],"created_at":"2024-08-01T21:01:10.540Z","updated_at":"2025-04-12T21:24:05.451Z","avatar_url":"https://github.com/jsverse.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n \u003cimg width=\"70%\" height=\"50%\" src=\"./logo.svg\"\u003e\n\u003c/p\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/codeof-conduct-ff69b4.svg?style=flat-square\"\u003e\n    \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\u003cimg src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e5079.svg?style=flat-square\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/prettier/prettier\"\u003e\u003cimg src=\"https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nVariabless allows you to manage application-wide CSS styles and variables in a single source of truth manner. \nVariabless will convert a JS definitions file to CSS variables or classes, allowing you to use those values in JS and CSS files.\n\n## Why Variabless?\nSince introducing CSS variables, supporting themes in your app, and customizing styles became much more convenient. \nWhile developing several apps, we noticed a reoccurring need. We need to refer to the theme and variables in our TS files for various reasons. For example, we are passing colors and fonts to libraries such as highcharts and grid. \n\nAt that point, it was either managing two sets of theme definitions, one in CSS and one in TS, or found a solution to centralize our theme and make it accessible for both; thus, Variabless was born. \n\n## Features\n\n✅ \u0026nbsp;Convert JS to CSS variables  \n✅ \u0026nbsp;Single Source of Styling Across the App  \n✅ \u0026nbsp;Supports JS, TS and JSON file formats  \n✅ \u0026nbsp;Webpack Plugin  \n✅ \u0026nbsp;Easy CSS Rules Creation  \n\n👉 \u0026nbsp;Try it in our [playground](https://ngneat.github.io/variabless/).\n\n## Table of content\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [CLI](#cli)\n  - [Webpack Plugin](#webpack-plugin)\n- [Rules Definition](#rules-definition)\n  - [value](#value---string--number--object)\n  - [variableName](#variablename---string--resolver)\n    - [Tokenized string](#tokenized-string)\n    - [Resolver function](#resolver-function)\n  - [appendVariablesTo](#appendvariablesto---string)\n  - [properties](#properties---propertyconfig--propertyconfig)\n- [Generate Independent Properties](#generate-independent-properties)  \n\n## Installation\nInstall the Variabless package via yarn or npm by running:\n\n```bash\nnpm i -D @ngneat/variabless\nyarn add -D @ngneat/variabless\n```\n\n## Usage\nThere are two ways you can use Variabless:\n\n### CLI\nAdd the following script to your `package.json` file:\n\n```json\n{\n  \"variabless\": \"variabless -s src/theme.ts -o src/assets/styles/theme.css\"\n}\n```\nRun `npm run variabless` to generate the css file.\n\n### Webpack plugin\nThe `VariablessWebpackPlugin` provides you with the ability to add/remove variables during development, while you're working on the project.\nJust add the `VariablessWebpackPlugin` in your plugins list:\n\n```javascript\n// webpack.config.js\nconst { VariablessWebpackPlugin } = require('variabless/webpack-plugin');\n\nmodule.exports = {\n  plugins: [\n    new VariablessWebpackPlugin({\n        watch?: boolean, // listen to changes\n        srcPath: 'src/theme.ts', // the variables rules file\n        outputPath: 'src/theme.css', // generated css file path\n    }),\n  ]\n};\n```\n\n\u003chr\u003e\n\nInclude the generated file by Variabless in your styles:\n```css\n@import 'assets/styles/theme.css';\n```\n\nAdd the generated file to your `.gitignore` file, there is no need to track it.\n\n## Rules Definition\nThe Variabless source file exports a map of rules which defines how to create the variables:\n \n```typescript\n// src/theme.ts\nexport const coreStyles: Record\u003cstring, Rule\u003e = {\n  myVariable: {\n    value: string | object,\n    variableName?: string | Resolver,\n    appendVariablesTo?: string,\n    properties?: PropertyConfig[],\n  },\n  ...\n};\n```\n\nWhere each rule has the following options:\n\n#### `value` - string | number | object\nThe css variable value, can be either string, number or a map:\n\n```javascript\n{\n  fontFamily: {\n    value: 'Roboto'\n  },\n  blueColors: {\n    value: {\n      b1: 'lightblue',\n      b2: 'blue',\n    }   \n  }\n}\n```\n\nWhen passing a map, a variable will be created for each value.\n\n#### `variableName` - string | Resolver\nThe css variable name.  \nWhen the rule has a primitive value the `variableName` should be a `string`:\n\n```javascript\n{\n  fontFamily: {\n    value: 'Roboto',\n    variableName: 'font-family'\n  },\n}\n``` \n\nWill produce:\n\n```css\n--font-family: 'Roboto';\n```\n\n\nWhen the rule's `value` is a map, we need to avoid name collisions, the `variableName` must be one of these two options:\n\n#### Tokenized string\nWe can pass a string containing unique tokens which are replaced during the variable's creation:\n\n* `:valueKey`\n* `:property`\n\nThe following rule: \n```javascript\n{\n  blueColors: {\n    value: {\n      b1: 'lightblue',\n      b2: 'blue',\n    },\n    variableName: ':valueKey-color'\n  },\n}\n``` \n\nWill produce the following variables:\n\n```css\n--b1-color: 'lightblue';\n--b2-color: 'blue';\n```\n\n#### Resolver function\nThe resolver function is similar to the tokenized string but gives you more flexibility:\n\n```typescript\ntype Resolver = (params: ResolverParams) =\u003e string;\n\ninterface ResolverParams {\n  valueKey?: string; \n  property?: string;\n} \n```\n\nThe following rule: \n\n```javascript\n{\n  blueColors: {\n    value: {\n      b1: 'lightblue',\n      b2: 'blue',\n    },\n    variableName: ({valueKey}) =\u003e valueKey.toUpperCase() + '-color'\n  },\n}\n``` \n\nWill produce the following variables:\n\n```css\n--B1-color: 'lightblue';\n--B2-color: 'blue';\n```\n\n#### `appendVariablesTo` - string\nThe selector hosting the generated variables, defaults to `:root`:\n\n```css\n:root {\n  --font-family: 'Roboto'\n  ...\n}\n```\n\n#### `properties` - PropertyConfig[]\nIt's a common practice to put frequently used styles in shared class or attribute.   \nVaribless easily allows you to create css selectors for those frequently used variables.  \n\nProperties are defined as following:\n```typescript\nexport interface PropertyConfig {\n  prop: string | string[];\n  selector: string | Resolver;\n} \n```\n\n* `prop` - The css properties to assign the variable's value to.\n* `selector` - The selector that will hold the css properties.\n\nSimilar to the [variableName](#variablename---string--resolver), if the rule's value is a primitive, the selector's value \nshould be a `string`. If the rule's value is a map, or the selector used for several css properties than the selector \nshould be a [tokenized string](#tokenized-string) or a [resolver function](#resolver-function) to prevent collisions.\n\nThe following rule: \n```typescript\n{\n  fontFamily: {\n    value: 'Roboto',\n    variableName: 'font-family',\n    properties: [{\n      prop: 'font-family', \n      selector: '.font-family'\n    }],\n  },\n  blueColors: {\n    value: {\n      b1: 'lightblue',\n      b2: 'blue'\n    },\n    variableName: ':valueKey-color',\n    properties: [{\n      prop: 'color',\n      selector: '.:valueKey-:property'\n    }, {\n      prop: 'background-color',\n      selector: '.:valueKey-bg'\n    }],\n  }\n}\n```\n\nWill produce the following css:\n\n```css\n:root {\n --font-family: 'Roboto';\n --b1-color: 'lightblue';\n --b2-color: 'blue';\n}\n\nbody {\n\n  .font-family {\n    font-family: var(--font-family);  \n  }  \n  \n  .b1-color {\n    color: var(--b1-color);  \n  }\n  \n  .b2-color {\n    color: var(--b2-color);  \n  } \n  \n  .b1-bg{\n    background-color: var(--b1-color);  \n  }\n  \n  .b2-bg {\n    background-color: var(--b2-color);  \n  }\n   \n}\n``` \n\n### Generate Independent Properties\nYou can also generate properties that don't relay on variables by not providing the `variableName` property.  \nThe following rule:\n\n```typescript\n{\n  fontWeight: {\n    properties: [\n      {\n        prop: 'font-weight',\n        selector: '.font-weight-:valueKey'\n      }\n    ], \n    value: {\n      regular: 'normal',\n      medium: 500,\n      bold: 'bold',\n      custom: 'var(--foo)'\n    }\n  }\n}\n```\n\nWill produce the following css:\n\n```css\nbody {\n\n  .font-weight-regular {\n    font-weight: normal;  \n  }\n  \n  .font-weight-medium {\n    font-weight: 500;\n  }\n  \n  .font-weight-bold {\n    font-weight: bold;\n  }\n  \n  .font-weight-custom {\n    font-weight: var(--foo);\n  }\n  \n}\n``` \n\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/shaharkazaz\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/17194830?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eShahar Kazaz\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ngneat/variabless/commits?author=shaharkazaz\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#content-shaharkazaz\" title=\"Content\"\u003e🖋\u003c/a\u003e \u003ca href=\"#design-shaharkazaz\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"https://github.com/ngneat/variabless/commits?author=shaharkazaz\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#example-shaharkazaz\" title=\"Examples\"\u003e💡\u003c/a\u003e \u003ca href=\"#ideas-shaharkazaz\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#infra-shaharkazaz\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"https://github.com/ngneat/variabless/commits?author=shaharkazaz\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://www.netbasal.com/\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/6745730?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eNetanel Basal\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/ngneat/variabless/commits?author=NetanelBasal\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#ideas-NetanelBasal\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#mentoring-NetanelBasal\" title=\"Mentoring\"\u003e🧑‍🏫\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsverse%2Fvariabless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsverse%2Fvariabless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsverse%2Fvariabless/lists"}