How to webpack sass inline variables #{$i} - sass

I'm trying something like:
#for $i from 0 through 5 {
.foo-#{$i} {
padding-left: 16px * $i;
}
}
I get the following error:
CssSyntaxError: app/styles.scss:41:11:
Unknown word You tried to parse SCSS with the standard CSS parser;
try again with the postcss-scss parser
39 |
40 | #for $i from 0 through 5 {
> 41 | .foo-#{$i} {
| ^
42 | padding-left: 16px * $i;
43 | }
And this is the relevant excerpt from my webpack.config.js:
{
test: /\.scss$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract([
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]--[hash:base64:6]'
}
},
{
loader: 'sass-loader'
}
])
}
What would it be the correct webpack configuration to be able to use #{$i} for selector names?
I've tried postcss-loader and some other things, but no clue yet. Any help will be very very appreciated. Thanks!

The problem was in runtime compilation process. Nothing to do with webpack or sass-loader.
require('css-modules-require-hook')({
generateScopedName: '[local]--[hash:base64:6]',
extensions: ['.scss'],
preprocessCss: function (data, filename) {
var result = sass.renderSync({
data: data,
file: filename
}).css;
return result;
}
});
The above worked.

Related

CKEditor5 v.32 on Laravel 8 / Laravel Mix 6

Does anybody have a working webpack.mix.js config for CKEditor5 32 on Laravel 8 (Laravel Mix 6 and Webpack 5) already? I have been banging my head to the wall for the past 8 hours and still could not manage to make it work.
Here is the console error I receive.
Before, when I was using Laravel Mix 5 and Webpack 4, this config solution seemed to be working.
But now all I get are a bunch of the same errors during npm compilation.
Config's snipped that worked for me
const CKEditorWebpackPlugin = require('#ckeditor/ckeditor5-dev-webpack-plugin');
const CKEditorStyles = require('#ckeditor/ckeditor5-dev-utils').styles;
//Includes SVGs and CSS files from "node_modules/ckeditor5-*" and any other custom directories
const CKEditorRegex = {
svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, //If you have any custom plugins in your project with SVG icons, include their path in this regex as well.
css: /ckeditor5-[^/\\]+[/\\].+\.css$/,
};
//Exclude CKEditor regex from mix's default rules
Mix.listen('configReady', config => {
const rules = config.module.rules;
const targetSVG = (/(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/).toString();
const targetFont = (/(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/).toString();
const targetCSS = (/\.p?css$/).toString();
rules.forEach(rule => {
let test = rule.test.toString();
if ([targetSVG, targetFont].includes(rule.test.toString())) {
rule.exclude = CKEditorRegex.svg;
} else if (test === targetCSS) {
rule.exclude = CKEditorRegex.css;
}
});
});
mix.webpackConfig({
plugins: [
new CKEditorWebpackPlugin({
language: 'en',
addMainLanguageTranslationsToAllAssets: true
}),
],
module: {
rules: [
{
test: CKEditorRegex.svg,
use: ['raw-loader']
},
{
test: CKEditorRegex.css,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: CKEditorStyles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark')
},
minify: true
})
}
}
]
}
]
}
});
Specs:
node v.16.11.1
npm v.8.0.0
Laravel v.8.77.1
package.json
"laravel-mix": "6.0.40",
"postcss-loader": "^6.2.1",
"raw-loader": "^4.0.1",
"sass": "^1.49.4",
"sass-loader": "^12.4.0",
"style-loader": "^2.0.0"
The Mix.listen() was deprecated and will go away in a future release. should replaced by mix.override().
Thanks #bakis.
This is the only working version after hours of searching. Exclude CKEditor regex from mix's default rules is the key neglected.
/** ckeditor 5 webpack config ****/
const CKEditorWebpackPlugin = require('#ckeditor/ckeditor5-dev-webpack-plugin');
const CKEditorStyles = require('#ckeditor/ckeditor5-dev-utils').styles;
//Includes SVGs and CSS files from "node_modules/ckeditor5-*" and any other custom directories
const CKEditorRegex = {
svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, //If you have any custom plugins in your project with SVG icons, include their path in this regex as well.
css: /ckeditor5-[^/\\]+[/\\].+\.css$/,
};
mix.webpackConfig({
plugins: [
new CKEditorWebpackPlugin({
language: 'en',
addMainLanguageTranslationsToAllAssets: true
}),
],
module: {
rules: [
{
test: CKEditorRegex.svg,
use: ['raw-loader']
},
{
test: CKEditorRegex.css,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: CKEditorStyles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark')
},
minify: true
})
}
}
]
}
]
}
});
//Exclude CKEditor regex from mix's default rules
mix.override(config => {
const rules = config.module.rules;
const targetSVG = (/(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/).toString();
const targetFont = (/(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/).toString();
const targetCSS = (/\.p?css$/).toString();
rules.forEach(rule => {
let test = rule.test.toString();
if ([targetSVG, targetFont].includes(rule.test.toString())) {
rule.exclude = CKEditorRegex.svg;
} else if (test === targetCSS) {
rule.exclude = CKEditorRegex.css;
}
});
});

Transpile CKEditor to ES5 using Webpack/Laravel mix

CKEditor does not work in iOS 10 (Safari).
I have found a guide that describes how to transpile it to ES5 which should get it working. I try to make it work with Laravel. The guide is here: https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/advanced-setup.html#option-building-to-es5-target
I try to make it work using Laravel Mix, but it is not my strongest skill, though I have tried. From Laravels doc, the problem may be solved with something like:
mix.webpackConfig({
resolve: {
module: {
rules: [
{
test: /ckeditor5-[^\/\\]+[\/\\].*\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [ require( '#babel/preset-env' ) ]
}
}
]
},
]
}
}
});
but I cannot get it to work.
I have also considered making a copy of webpack.config.js like explained here: https://laravel.com/docs/5.8/mix#custom-webpack-configuration
But again I get in doubt when I try to solve the issue (it's most related to the syntax). Have anyone tried to get CKEditor to work in Safari iOS 10 using Laravel?
In advance, thank you.
i know you asked for this long ago, but i stumbled into the same problem today.
i solved following the docs with a little trick, in your webpack.mix.js
const CKEditorWebpackPlugin = require( '#ckeditor/ckeditor5-dev-webpack-plugin' );
const CKEStyles = require('#ckeditor/ckeditor5-dev-utils').styles;
const CKERegex = {
svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
};
Mix.listen('configReady', webpackConfig => {
const rules = webpackConfig.module.rules;
const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
const targetCSS = /\.css$/;
// exclude CKE regex from mix's default rules
for (let rule of rules) {
if (rule.test.toString() === targetSVG.toString()) {
rule.exclude = CKERegex.svg;
}
else if (rule.test.toString() === targetFont.toString()) {
rule.exclude = CKERegex.svg;
}
else if (rule.test.toString() === targetCSS.toString()) {
rule.exclude = CKERegex.css;
}
}
});
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.webpackConfig({
plugins: [
new CKEditorWebpackPlugin({
language: 'it'
})
],
module: {
rules: [
{
test: /ckeditor5-[^\/\\]+[\/\\].+\.js$/,
use: [
{
loader: 'babel-loader',
options: Config.babel()
}
]
},
{
test: CKERegex.svg,
use: [ 'raw-loader' ]
},
{
test: CKERegex.css,
use: [
{
loader: 'style-loader',
options: {
singleton: true
}
},
{
loader: 'postcss-loader',
options: CKEStyles.getPostCssConfig({
themeImporter: {
themePath: require.resolve('#ckeditor/ckeditor5-theme-lark')
},
minify: true
})
},
]
}
]
}
});
be sure to follow the documentation for installing the correct packages!

Webpack4 with sass-loader, MiniCssExtractPlugin and uikit

I´m trying to setup a uitkit template with
webpack 4
sass loader
MiniCssExtractPlugin
uikit
What I would like to achieve is that a build automatically converts sass to css and that resulting css is injected into src/index.html.
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
sourceMap: true,
importLoader: 4
}
},
"sass-loader"
]}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
index.js
import UIkit from 'uikit';
import Icons from 'uikit/dist/js/uikit-icons';
import style from "uikit/src/scss/uikit.scss"
UIkit.use(Icons);
Unfortunately a build fails with
ERROR in ./node_modules/uikit/src/scss/uikit.scss (./node_modules/css-loader??ref--6-1!./node_modules/sass-loader/lib/loader.js!./node_modules/uikit/src/scss/uikit.scss)
Module build failed (from ./node_modules/sass-loader/lib/loader.js):
$inverse-base-color: $inverse-global-color !default;
Undefined variable: "$inverse-global-color".
in new_proj/node_modules/uikit/src/scss/components/base.scss (line 607, column 49)
I would be thankful if one could explain What I´m doing wrong and why sass loader cannot find the variable $inverse-global-color.
I´ve found the answer. It´s working like this:
index.js
...
import style from "./main.scss"
...
main.scss
// 1. Your custom variables and variable overwrites.
$global-link-color: #DA7D02;
// 2. Import default variables and available mixins.
#import "uikit/src/scss/variables-theme.scss";
#import "uikit/src/scss/mixins-theme.scss";
// 3. Your custom mixin overwrites.
#mixin hook-card() { color: #000; }
// 4. Import UIkit.
#import "uikit/src/scss/uikit-theme.scss";

process.env.NODE_ENV variables into scss via webpack

Is there a way to reference a process.env.NODE_ENV in a scss file by passing it to the sass-loader in web-pack. If so anyone know how to go about this ?
Here is my webpack module lodaers array.
module: {
loaders: [
{ test: /\.js?$/,
loader: 'babel-loader',
include: path.join(__dirname, '../app'),
exclude: /node_modules/
},
{ test: /\.scss?$/,
loader: 'style-loader!css-loader!sass-loader',
include: path.join(__dirname, '../app', 'styles')
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
include : path.join(__dirname, '../app', 'images'),
loader : 'file-loader?limit=30000&name=[name].[ext]'
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
include : path.join(__dirname, '../app', 'fonts'),
loader: 'file-loader?name=fonts/[name].[ext]'
}
]
I even tried
{ test: /\.scss?$/,
loader: 'style-loader!css-loader!sass-loader',
include: path.join(__dirname, '../app', 'styles'),
options: {
data: "$env: " + process.env.NODE_ENV + ";"
}
}
but the above broke the build.
I just want a way to access a url in my scss file depending on the environment.
It doesn't have to be via webpack any ideas would help without hard coding it.
for example:
.contact-transparent{
width: 100%;
height: 100%;
background: url(process.env.NODE_ENV+'/home-background.jpg') left center no-repeat;
}
I think you could get this done with a custom loader that you chain in before the others for your Sass files. In that loader you would check the value of NODE_ENV and do a find/replace in the Sass source, where the replaced value is based on the env. Not fancy but would get the job done. For example:
// url-by-env-loader.js
module.exports = (source) => {
const urlsByEnv = {
dev: "the-dev-host.com",
staging: "the-staging-host.com",
prod: "the-prod-host.com"
};
const urlToReplace = "the-url-in-your-sass-source.com";
const urlToUse = urlsByEnv[process.env.NODE_ENV];
const replaceRegex = new RegExp(urlToReplace, 'g');
return source.replace(replaceRegex, urlToUse);
}

Webpack - Module build failed: Function sprite-map doesn't support keyword arguments

I am new to webpack and I'm trying to implement it in my project. I'm also using Compass for my .scss files.
I included all my scss files in my entrypoint (see the webpack configuration down below) and I have this error:
Error line 1: Function sprite-map doesn't support keyword arguments
The scss file that causes the module build to fail:
$icons: sprite-map("icons/icons-1/k/*.png", $spacing: 10px);
#each $i in sprite_names($icons) {
.k-#{$i}{
background-position: sprite-position($icons, $i, 0, 0, true);
}
}
.k-121, .k-122, .k-123, .k-124, .k-125, .k-126, .k-127, .k-128, .k-129, .k-130, .k-131, .k-132, .k-133, {
background-image: $icons;
background-repeat: no-repeat;
}
But looking at the documentation, it is possible to use keyword arguments, isn't it ?
Here is my webpack.config.js :
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.resolve(__dirname, 'scripts/app.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.s?css$/,
loaders: 'sass-loader'
},
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(jpe?g|png|gif|svg)$/,
loader: 'file-loader?name=/dist/img/[name].[ext]'
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
loader: 'file-loader?name=dist/fonts/[name].[ext]'
}
]
},
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin()
]
};
Thanks for your help !

Resources