├── .editorconfig ├── .github └── workflows │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README.ru.md ├── index.js ├── package-lock.json └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | defaults: 8 | run: 9 | shell: bash 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-node@v3 17 | with: 18 | node-version: '18.15.0' 19 | registry-url: 'https://registry.npmjs.org' 20 | scope: '@funboxteam' 21 | - run: npm ci 22 | - run: npm publish 23 | env: 24 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # -- Node.js -- 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Dependency directory 9 | /node_modules 10 | 11 | # Optional npm cache directory 12 | .npm 13 | 14 | 15 | # -- VSCode -- 16 | /.vscode 17 | jsconfig.json 18 | 19 | 20 | # -- IDEA -- 21 | /.idea 22 | 23 | ## File-based project format: 24 | *.ipr 25 | *.iws 26 | *.iml 27 | 28 | 29 | # -- Vim -- 30 | 31 | # swap 32 | [._]*.s[a-w][a-z] 33 | [._]s[a-w][a-z] 34 | 35 | # session 36 | Session.vim 37 | 38 | # temporary 39 | .netrwhist 40 | *~ 41 | /tmp 42 | 43 | 44 | # -- Eclipse -- 45 | *.swp 46 | 47 | 48 | # -- OS X -- 49 | .DS_Store 50 | 51 | 52 | # -- Public -- 53 | /public 54 | /public-sandbox 55 | 56 | 57 | # -- Tests -- 58 | /test-reports 59 | /test-logs 60 | /gemini-* 61 | /screenshots 62 | 63 | 64 | # -- Sass -- 65 | .sass-cache 66 | 67 | 68 | # -- ESLint -- 69 | .eslintcache 70 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2.2.0 (23.10.2020) 4 | 5 | Improved performance. Now the loader works at least two times faster! 6 | 7 | Also the license defined & README improved. 8 | 9 | 10 | ## 2.1.0 (08.05.2019) 11 | 12 | Fixed the package name in README. 13 | 14 | 15 | ## 2.0.0 (06.07.2018) 16 | 17 | The package was moved into the @funboxteam scope. 18 | 19 | 20 | ## 1.0.0 (30.08.2017) 21 | 22 | Initial release. 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Igor Adamenko and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @funboxteam/scss-vars-loader 2 | 3 | [![npm](https://img.shields.io/npm/v/@funboxteam/scss-vars-loader.svg)](https://www.npmjs.com/package/@funboxteam/scss-vars-loader) 4 | 5 | Webpack loader that injects `$b` variable declaration to the processed files with the name of the current BEM block 6 | as a value. 7 | 8 | [По-русски](./README.ru.md) 9 | 10 | ## Rationale 11 | 12 | When we develop web apps we use BEM on filesystem. Sometimes blocks become too huge to handle them easily, 13 | and when you suddenly need to rename one, you have to rewrite the name in every file. To make it a bit easier 14 | we decided to unify block name in SCSS files by `$b` variable. 15 | 16 | At the same time it allows us to generate SCSS files using templates and not to care about the proper name 17 | of the selector there. 18 | 19 | ## Getting Started 20 | 21 | Install the loader in your project: 22 | 23 | ```bash 24 | npm install --save-dev @funboxteam/scss-vars-loader 25 | ``` 26 | 27 | Add it into the project's Webpack config so that it is called before sass-loader: 28 | 29 | ```js 30 | module.exports = { 31 | // ... 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.scss$/, 36 | use: [ 37 | // ... 38 | 'sass-loader', 39 | '@funboxteam/scss-vars-loader', 40 | // ... 41 | ], 42 | }, 43 | ], 44 | }, 45 | }; 46 | ``` 47 | 48 | ## Usage 49 | 50 | Use `$b` to construct SCSS selectors: 51 | 52 | ```scss 53 | .#{$b}__elem_mod_value { 54 | color: red; 55 | } 56 | ``` 57 | 58 | ## Implementation details 59 | 60 | At the build stage this line is added into the each processed file: 61 | 62 | ```scss 63 | $b: 'blockname'; 64 | ``` 65 | 66 | To find out the name of the current BEM block properly, the loader goes though the path of the processed file 67 | from right to left and searches the first directory name which does not start with `_` and uses such directory 68 | as a value for `$b`. 69 | 70 | [![Sponsored by FunBox](https://funbox.ru/badges/sponsored_by_funbox_centered.svg)](https://funbox.ru) 71 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | # @funboxteam/scss-vars-loader 2 | 3 | [![npm](https://img.shields.io/npm/v/@funboxteam/scss-vars-loader.svg)](https://www.npmjs.com/package/@funboxteam/scss-vars-loader) 4 | 5 | Лоадер для Вебпака, добавляющий в обрабатываемые файлы переменную `$b` с именем текущего БЭМ-блока в качестве значения. 6 | 7 | ## Мотивация 8 | 9 | При разработке веб-приложений мы используем БЭМ, в том числе и на файловой системе. 10 | Иногда блоки получаются довольно-таки развесистыми, и вдруг всплывает необходимость их переименования. Чтобы не грепать 11 | по всем файлам и не заменять имя блока, мы решили унифицировать его в SCSS-файлах, используя везде переменную `$b`. 12 | 13 | Помимо прочего такой подход позволяет генерировать SCSS-файлы по шаблону, не заботясь о правильном имени селектора в них. 14 | 15 | ## Установка 16 | 17 | Установить лоадер в проекте: 18 | 19 | ```bash 20 | npm install --save-dev @funboxteam/scss-vars-loader 21 | ``` 22 | 23 | Подключить в конфиге Вебпака так, чтобы он вызывался перед sass-loader: 24 | 25 | ```js 26 | module.exports = { 27 | // ... 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.scss$/, 32 | use: [ 33 | // ... 34 | 'sass-loader', 35 | '@funboxteam/scss-vars-loader', 36 | // ... 37 | ], 38 | }, 39 | ], 40 | }, 41 | }; 42 | ``` 43 | 44 | ## Использование 45 | 46 | После настройки переменную `$b` можно использовать при описании стилей: 47 | 48 | ```scss 49 | .#{$b}__elem_mod_value { 50 | color: red; 51 | } 52 | ``` 53 | 54 | ## Детали реализации 55 | 56 | Во время сборки в начало каждого обрабатываемого файла добавляется подобная строка: 57 | 58 | ```scss 59 | $b: 'blockname'; 60 | ``` 61 | 62 | Чтобы правильно определить имя блока, лоадер проходит по пути до обрабатываемого файла справа навлево 63 | в поисках первой папки, имя которой не начинается с `_`. Найдя такую папку он и использует её имя 64 | в качестве значения для `$b`. 65 | 66 | [![Sponsored by FunBox](https://funbox.ru/badges/sponsored_by_funbox_centered.svg)](https://funbox.ru) 67 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function(source) { 4 | const pathParts = path.dirname(this.resourcePath).split(path.sep); 5 | 6 | let i = pathParts.length - 1; 7 | while (true) { 8 | if (pathParts[i][0] !== '_') return `$b: ${pathParts[i]};\n\n${source}`; 9 | i--; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@funboxteam/scss-vars-loader", 3 | "version": "2.2.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@funboxteam/scss-vars-loader", 9 | "version": "2.2.0", 10 | "license": "MIT" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@funboxteam/scss-vars-loader", 3 | "version": "2.2.0", 4 | "description": "SCSS variables for BEM blocks", 5 | "license": "MIT", 6 | "author": "Igor Adamenko (https://igoradamenko.com)", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/funbox/scss-vars-loader" 10 | }, 11 | "main": "index.js", 12 | "files": [ 13 | "index.js" 14 | ], 15 | "scripts": { 16 | "prepublishOnly": "if [ -z \"$CI\" ]; then lawyer; fi" 17 | } 18 | } 19 | --------------------------------------------------------------------------------