stylelint - Where are there examples to create your own plugin? - css

I have gone to the stylelint website, github and downloaded locally via npm. The stylelint website advises that to create my own plugin I should use this format:
var myPluginRule = stylelint.createPlugin(ruleName, function(primaryOption, secondaryOptionObject) {
return function(postcssRoot, postcssResult) {
var validOptions = stylelint.utils.validateOptions(postcssResult, ruleName, { .. })
if (!validOptions) { return }
// ... some logic ...
stylelint.utils.report({ .. })
}
})
When I do a 'find' inside the npm folder for stylelint, I cannot find any examples that use this format. Can anyone advise a really good tutorial on creating your own plugin?
thanks

ok after playing around with it I have literally found a way.
1) prerequisites:
$ npm init
$ npm install gulp stylelint gulp-style-lint --save-dev
2) Create some scss files at ./scss/myfile.scss
body{background:red;}
3) create ./gulpfile.js
var gulp = require('gulp');
var gulpStylelint = require('gulp-stylelint');
gulp.task('stylelint',function(){
return gulp
.src('./scss/*.scss')
.pipe(
gulpStylelint({
reporters: [
{formatter: 'string', console: true}
]
})
);
})
4) create ./stylelintCustom/index.js
var stylelint = require("stylelint");
var ruleName = "steves/steve1";
var messages = stylelint.utils.ruleMessages(ruleName, {
rejected: 'steve rejects this',
});
module.exports = stylelint.createPlugin(ruleName, function(max, options) {
return function(root, result) {
// to access the variable for the whole of this file scss =
console.log(root.source.input);
// apply rules now...
// run reporter to output
}
});
module.exports.ruleName = ruleName;
module.exports.messages = messages;
Being sure to name ruleName: "plugins/plugin". ie steves/steverule1 etc.
5) Be sure to create stylelintCustom/package.json
{
"name": "stylelint-steves-steve1",
"version": "0.0.1",
"main": "index.js",
"devDependencies": {
"stylelint": "~2.6.0"
},
"engines": {
"node": ">=0.10.0"
}
}
6) create: stylelint.rc
{
"plugins": [
"./stylelintCustom/index.js"
],
"rules": {
"steves/steve1": true
}
}
7) run gulp
$ gulp stylelint
Will output the scss, so you can run whatever js, regex you need here.

For reference of how the existing rules work in stylelint you can go to:
yourproject/node_modules/stylelint/dist/rules/*

Related

How to configure cypress-sql-server with no cypress.json? (updated)

I'm trying to setup cypress-sql-server, but I'm using version 10.8.0, which does not use cypress.json to configure the environment. All of the setup instructions I've found refer to using cypress.json to configure the plug-in. With the help of u/Fody, I'm closer, but I'm still running into an error:
tasksqlServer:execute, SELECT 'Bob'
CypressError
cy.task('sqlServer:execute') failed with the following error:
The 'task' event has not been registered in the setupNodeEvents method. You must register it before using cy.task()
Fix this in your setupNodeEvents method here:
D:\git\mcare.automation\client\cypress\cypress.config.jsLearn more
node_modules/cypress-sql-server/src/commands/db.js:7:1
5 | }
6 |
> 7 | cy.task('sqlServer:execute', query).then(response => {
| ^
8 | let result = [];
9 |
cypress.config.js
const { defineConfig } = require("cypress");
const sqlServer = require("cypress-sql-server");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// allows db data to be accessed in tests
config.db = {
"userName": "user",
"password": "pass",
"server": "myserver",
"options": {
"database": "mydb",
"encrypt": true,
"rowCollectionOnRequestCompletion": true
}
}
// code from /plugins/index.js
const tasks = sqlServer.loadDBPlugin(config.db);
on('task', tasks);
return config
// implement node event listeners here
},
},
});
testSQL.spec.js
describe('Testing SQL queries', () => {
it("It should return Bob", () => {
cy.sqlServer("SELECT 'Bob'").should('eq', 'Bob');
});
})
My versions:
\cypress> npx cypress --version
Cypress package version: 10.8.0
Cypress binary version: 10.8.0
Electron version: 19.0.8
Bundled Node version:
16.14.2
Suggestions? Is there any more info I can provide to help?
This is the install instruction currently given by cypress-sql-server for Cypress v9
Plugin file
The plug-in can be initialised in your cypress/plugins/index.js file as below.
const sqlServer = require('cypress-sql-server');
module.exports = (on, config) => {
tasks = sqlServer.loadDBPlugin(config.db);
on('task', tasks);
}
Translating that into Cypress v10+
const { defineConfig } = require('cypress')
const sqlServer = require('cypress-sql-server');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// allows db data to be accessed in tests
config.db = {
"userName": "user",
"password": "pass",
"server": "myserver",
"options": {
"database": "mydb",
"encrypt": true,
"rowCollectionOnRequestCompletion": true
}
}
// code from /plugins/index.js
const tasks = sqlServer.loadDBPlugin(config.db);
on('task', tasks);
return config
},
},
})
Other variations work, such as putting the "db": {...} section below the "e2e: {...}" section, but not in the "env": {...} section.
Custom commands
Instructions for Cypress v9
Commands file
The extension provides multiple sets of commands. You can import the ones you need.
Example support/index.js file.
import sqlServer from 'cypress-sql-server';
sqlServer.loadDBCommands();
For Cypress v10+
Just move this code to support/e2e.js
cypress.json is a way to specify Cypress environment variables. Instead of using a cypress.json file, you can use any of the strategies in that link.
If you just wanted to include them in your cypress.config.js, it would look something like this:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:1234',
env: {
db: {
// your db values here
}
}
}
})

TypeError: Cannot read property 'forEach' of undefined after upgrade to Nextjs 11

Have upgraded my project to nextjs 11 and unfortunately some of my code is erroring out.
I have equally upgraded React from 16.0.0 version to 17.0.0 so I could then upgrade to next.js.
This is the code snippet that is erroring out and its located in my next.config.js file:
config.module.rules[1].oneOf.forEach((moduleLoader, i) => {
Array.isArray(moduleLoader.use) && moduleLoader.use.forEach((l) => {
if (l.loader.includes("css-loader") && l.options.modules && l.options.modules.exportLocalsConvention) {
l.options = {
...l.options,
modules: {
...l.options.modules,
exportLocalsConvention: "camelCase",
}
}
}
});
});
If I remove the code entirely a different error pops up related to svg config on the same file :
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// svg to react component loader
config.module.rules.push({
test: /\.svg$/,
use: [{
loader: '#svgr/webpack',
options: {
"svgoConfig": {
"plugins": [{ "cleanupIDs": false }]
}
}
}],
})
Any ideas on what is happening?
I know they have new related features but not entirely sure how to go about it and ensure my project runs similarly.
Thanks
Next.js 11 now uses webpack 5 under the hood so you need to update your webpack config accordingly.
There is a small migration guide here, but it does not cover all the changes obviously.
I think you can also opt-out of webpack 5 for now, if you want to update Next.js but don't want to mess with webpack config for now:
// add this key in your next.config
module.exports = {
webpack5: false,
}

CRA + Craco + multiple CSS themes

Folder structure:
src/index.tsx
src/themes/dark.scss
src/themes/light.scss
...
craco webpack modifications:
const path = require('path');
module.exports = {
webpack: {
configure: (webpackConfig, { env, paths }) => {
webpackConfig.entry.push(
path.join(process.cwd(), "src/themes/dark.scss"),
path.join(process.cwd(), "src/themes/light.scss")
);
webpackConfig.module.rules.splice(1, 0, {
test: /\.themes\/dark.scss$/,
use: [
{ loader: require.resolve('sass-loader') },
{ loader: require.resolve('css-loader') }
]
});
webpackConfig.module.rules[3].oneOf[5].exclude = /\.(module|themes)\.(scss|sass)$/;
webpackConfig.module.rules[3].oneOf[6].exclude = /\.themes\.(scss|sass)$/;
webpackConfig.module.rules[3].oneOf[7].exclude.push(/\.themes\.(scss|sass)$/);
return webpackConfig;
}
}
};
the intent is I am hoping obvious - we are trying to generate two theme css files from src/themes directory, which will be later changed manually with unloading / loading <link in DOM directly, I was inspired by Output 2 (or more) .css files with mini-css-extract-plugin in webpack and https://github.com/terence55/themes-switch/blob/master/src/index.js.
Now comes the troubles - after build process:
Creating an optimized production build...
Compiled successfully.
File sizes after gzip:
122.24 KB build/static/css/2.2e93dcba.chunk.css
762 B build/static/js/runtime~main.a8a9905a.js
191 B build/static/css/main.d0c4fa77.chunk.css
157 B build/static/js/main.2063d3e0.chunk.js
109 B build/static/js/2.9b95e8c0.chunk.js
(CSS files are OK, there are few generic CSS files and few of them are from libraries). But no theme files... I try to combine with file-loader, but it does not work either.
I would recommend configuring webpack to pack all assets related to a particular theme into a single chunk:
const themeFileRegex = /(\w+)\.theme\.(scss|sass)$/;
// recursively searches for a theme stylesheet in parent issuers
function getIssuerTheme(module) {
const matches = themeFileRegex.exec(module.resource);
if (matches) {
return matches[1];
} else {
return module.issuer && getIssuerTheme(module.issuer);
}
}
...
webpackConfig.optimization.splitChunks.cacheGroups = {
...webpackConfig.optimization.splitChunks.cacheGroups,
themes: {
test: getIssuerTheme,
name: m => {
const name = getIssuerTheme(m);
return `theme.${name}`;
},
reuseExistingChunk: false,
},
};
With that, you should get chunks named theme.light, theme.dark, etc.

Testing babel-preset-env using package.json

Noob question here. Trying to assure myself that babel-preset-env works.
I install babel-core and babel-preset-env:
yarn add --dev babel-core
yarn add --dev babel-preset-env
My package.json has:
"babel": {
"presets": [
[
"env",
{
"targets": {
"browsers": [
"IE >= 8"
]
}
}
]
]
},
I create a JS script to test:
fs.readFile('my.js', 'utf8', (err, data) => {
if (err) throw err;
let babel = require("babel-core");
let result = babel.transform(data).code;
});
I test with arrow functions in my.js:
new Promise((resolve, reject) => {
console.log('whatever');
});
No matter how I tweak targets.browsers, the arrow function does not get converted.
Tested this with babel-cli. Works.
It's clear that babel-core (the Javascript API of Babel) does not pick up anything from package.json.
Filed an issue here too: https://github.com/babel/babel/issues/7647
The JS API docs probably needs to be updated.
In order to use babel-preset-env in JS API:
const { execFile } = require('child_process');
const ug = require('uglify-es');
const { execFile } = require('child_process');
execFile('npx', ['babel', 'my.js'], (err, data, stderr) => {
if (err) throw err; // U get the idea
let result = ug.minify(data, { mangle: { toplevel: true } }).code;
});

registerMultiTask.js in grunt-horde

I'm trying to configure grunt-horde so that I can have multiple builds all using a centrally managed task configuration.
The documentation provides the following example of a registerMultiTasks.js file, but I can't get it to work
module.exports = function(grunt) {
var myMultiTask = require('./multi-tasks/secret-sauce.js');
return {
myMultiTask: ['some description', myMultiTask]
};
};
Even if I replace their example with something more simple:
module.exports = function(grunt) {
return {
demo: ['Demo', function() {
console.info('hello');
}]
};
};
When I run grunt demo:test the output is:
Running "demo:test" (demo) task
Verifying property demo.test exists in config...ERROR
>> Unable to process task.
Warning: Required config property "demo.test" missing. Use --force to continue.
Aborted due to warnings.
When I run grunt --help the demo task shows up in the list. Thinking about the warning message I've also tried the following, but again with no luck.
module.exports = function(grunt) {
return {
demo: ['Demo', function(){
return {test: function(){console.info('hello');}};
}]
};
};
...what am I doing wrong?
I figured it out - you need to define the configuration for each target of the multitasks:
initConfig/demo.js
module.exports = function() {
'use strict';
return {
test: {
foo: 'bar'
}
};
};
You can then access this configuration data and the target from within the multitask function:
registerMultiTask.js
module.exports = function(grunt) {
return {
demo: ['Demo', function() {
grunt.log.writeln('target: ' + this.target);
grunt.log.writeln('foo: ' + this.data.foo);
}]
};
};

Resources