Skip to content

Commit

Permalink
Merge branch 'master' into fix-4683
Browse files Browse the repository at this point in the history
# By Mike Allanson (6) and others
# Via GitHub
* master:
  Bump @types/lodash from 4.14.152 to 4.14.154 (#4817)
  Update CHANGELOG.md
  Fix with workaround a TypeError thrown for "html" (#4797)
  Update CHANGELOG.md
  Fix false positives for variables in font-family-no-missing-generic-family-keyword (#4806)
  Update CHANGELOG.md
  Add ignoreSelectors option to block-opening-brace-space-before (#4640)
  Update CHANGELOG.md
  Fix error message percentage/number precision for alpha-value-notation (#4802)
  Create new 'createPartialStylelintResult' module (#4815)
  Move function normalizeAllRuleSettings() out to a separate module (#4810)
  • Loading branch information
m-allanson committed Jun 3, 2020
2 parents 9e8e9c6 + 01743ae commit 336a4f0
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 159 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ All notable changes to this project are documented in this file.

## Head

- Added: `ignoreSelectors[]` to `block-opening-brace-space-before` ([#4640](https://github.com/stylelint/stylelint/pull/4640)).
- Fixed: workaround CSS-in-JS syntax throws a TypeError in the following conditions: 1. encounter a call or template expression named 'html' and 2. syntax loads via `autoSyntax()`.
- Fixed: specify minimum node version in `package.json`'s `engine` field ([#4790](https://github.com/stylelint/stylelint/pull/4790)).
- Fixed: `alpha-value-notation` number precision errors ([#4802](https://github.com/stylelint/stylelint/pull/4802)).
- Fixed: `font-family-no-missing-generic-family-keyword` false positives for variables ([#4806](https://github.com/stylelint/stylelint/pull/4806)).

## 13.5.0

Expand Down
5 changes: 5 additions & 0 deletions lib/__tests__/fixtures/html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

let html;

html.replace();
13 changes: 13 additions & 0 deletions lib/__tests__/standalone-syntax.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,19 @@ it('standalone with automatic syntax inference', () => {
});
});

it('standalone with js file contains html', () => {
return standalone({
files: `${fixturesPath}/html.js`,
config: {
rules: {
'block-no-empty': true,
},
},
}).then((data) => {
expect(data.results[0].errored).toBe(false);
});
});

it('standalone with postcss-safe-parser', () => {
return standalone({
files: `${fixturesPath}/syntax_error.*`,
Expand Down
34 changes: 1 addition & 33 deletions lib/augmentConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ const _ = require('lodash');
const configurationError = require('./utils/configurationError');
const getModulePath = require('./utils/getModulePath');
const globjoin = require('globjoin');
const normalizeRuleSettings = require('./normalizeRuleSettings');
const normalizeAllRuleSettings = require('./normalizeAllRuleSettings');
const path = require('path');
const rules = require('./rules');

/** @typedef {import('stylelint').StylelintConfigPlugins} StylelintConfigPlugins */
/** @typedef {import('stylelint').StylelintConfigProcessor} StylelintConfigProcessor */
Expand Down Expand Up @@ -294,37 +293,6 @@ function addPluginFunctions(config) {
return config;
}

/**
* @param {StylelintConfig} config
* @return {StylelintConfig}
*/
function normalizeAllRuleSettings(config) {
/** @type {StylelintConfigRules} */
const normalizedRules = {};

if (!config.rules) return config;

Object.keys(config.rules).forEach((ruleName) => {
const rawRuleSettings = _.get(config, ['rules', ruleName]);

const rule = rules[ruleName] || _.get(config, ['pluginFunctions', ruleName]);

if (!rule) {
normalizedRules[ruleName] = [];
} else {
normalizedRules[ruleName] = normalizeRuleSettings(
rawRuleSettings,
ruleName,
_.get(rule, 'primaryOptionArray'),
);
}
});

config.rules = normalizedRules;

return config;
}

/**
* Given an array of processors strings, we want to add two
* properties to the augmented config:
Expand Down
103 changes: 103 additions & 0 deletions lib/createPartialStylelintResult.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use strict';

const _ = require('lodash');

/** @typedef {import('stylelint').PostcssResult} PostcssResult */
/** @typedef {import('postcss').NodeSource} NodeSource */
/** @typedef {import('stylelint').StylelintResult} StylelintResult */

/**
* @param {PostcssResult} [postcssResult]
* @param {import('stylelint').StylelintCssSyntaxError} [cssSyntaxError]
* @return {StylelintResult}
*/
module.exports = function (postcssResult, cssSyntaxError) {
/** @type {StylelintResult} */
let stylelintResult;
/** @type {string | undefined} */
let source;

if (postcssResult && postcssResult.root) {
if (postcssResult.root.source) {
source = postcssResult.root.source.input.file;

if (!source && 'id' in postcssResult.root.source.input) {
source = postcssResult.root.source.input.id;
}
}

// Strip out deprecation warnings from the messages
const deprecationMessages = _.remove(postcssResult.messages, {
stylelintType: 'deprecation',
});
const deprecations = deprecationMessages.map((deprecationMessage) => {
return {
text: deprecationMessage.text,
reference: deprecationMessage.stylelintReference,
};
});

// Also strip out invalid options
const invalidOptionMessages = _.remove(postcssResult.messages, {
stylelintType: 'invalidOption',
});
const invalidOptionWarnings = invalidOptionMessages.map((invalidOptionMessage) => {
return {
text: invalidOptionMessage.text,
};
});

const parseErrors = _.remove(postcssResult.messages, {
stylelintType: 'parseError',
});

// This defines the stylelint result object that formatters receive
stylelintResult = {
source,
deprecations,
invalidOptionWarnings,
// TODO TYPES check which types are valid? postcss? stylelint?
/* eslint-disable-next-line */
parseErrors: /** @type {any} */ (parseErrors),
errored: postcssResult.stylelint.stylelintError,
warnings: postcssResult.messages.map((message) => {
return {
line: message.line,
column: message.column,
rule: message.rule,
severity: message.severity,
text: message.text,
};
}),
ignored: postcssResult.stylelint.ignored,
_postcssResult: postcssResult,
};
} else if (cssSyntaxError) {
if (cssSyntaxError.name !== 'CssSyntaxError') {
throw cssSyntaxError;
}

stylelintResult = {
source: cssSyntaxError.file || '<input css 1>',
deprecations: [],
invalidOptionWarnings: [],
parseErrors: [],
errored: true,
warnings: [
{
line: cssSyntaxError.line,
column: cssSyntaxError.column,
rule: cssSyntaxError.name,
severity: 'error',
text: `${cssSyntaxError.reason} (${cssSyntaxError.name})`,
},
],
};
} else {
throw new Error(
'createPartialStylelintResult must be called with either postcssResult or CssSyntaxError',
);
}

return stylelintResult;
};
91 changes: 3 additions & 88 deletions lib/createStylelintResult.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const _ = require('lodash');
const createPartialStylelintResult = require('./createPartialStylelintResult');

/** @typedef {import('stylelint').PostcssResult} PostcssResult */
/** @typedef {import('postcss').NodeSource} NodeSource */
Expand All @@ -14,98 +14,13 @@ const _ = require('lodash');
* @return {Promise<StylelintResult>}
*/
module.exports = function (stylelint, postcssResult, filePath, cssSyntaxError) {
/** @type {StylelintResult} */
let stylelintResult;
/** @type {string | undefined} */
let source;

if (postcssResult && postcssResult.root) {
if (postcssResult.root.source) {
source = postcssResult.root.source.input.file;

if (!source && 'id' in postcssResult.root.source.input) {
source = postcssResult.root.source.input.id;
}
}

// Strip out deprecation warnings from the messages
const deprecationMessages = _.remove(postcssResult.messages, {
stylelintType: 'deprecation',
});
const deprecations = deprecationMessages.map((deprecationMessage) => {
return {
text: deprecationMessage.text,
reference: deprecationMessage.stylelintReference,
};
});

// Also strip out invalid options
const invalidOptionMessages = _.remove(postcssResult.messages, {
stylelintType: 'invalidOption',
});
const invalidOptionWarnings = invalidOptionMessages.map((invalidOptionMessage) => {
return {
text: invalidOptionMessage.text,
};
});

const parseErrors = _.remove(postcssResult.messages, {
stylelintType: 'parseError',
});

// This defines the stylelint result object that formatters receive
stylelintResult = {
source,
deprecations,
invalidOptionWarnings,
// TODO TYPES check which types are valid? postcss? stylelint?
/* eslint-disable-next-line */
parseErrors: /** @type {any} */ (parseErrors),
errored: postcssResult.stylelint.stylelintError,
warnings: postcssResult.messages.map((message) => {
return {
line: message.line,
column: message.column,
rule: message.rule,
severity: message.severity,
text: message.text,
};
}),
ignored: postcssResult.stylelint.ignored,
_postcssResult: postcssResult,
};
} else if (cssSyntaxError) {
if (cssSyntaxError.name !== 'CssSyntaxError') {
throw cssSyntaxError;
}

stylelintResult = {
source: cssSyntaxError.file || '<input css 1>',
deprecations: [],
invalidOptionWarnings: [],
parseErrors: [],
errored: true,
warnings: [
{
line: cssSyntaxError.line,
column: cssSyntaxError.column,
rule: cssSyntaxError.name,
severity: 'error',
text: `${cssSyntaxError.reason} (${cssSyntaxError.name})`,
},
],
};
} else {
throw new Error(
'createStylelintResult must be called with either postcssResult or CssSyntaxError',
);
}
let stylelintResult = createPartialStylelintResult(postcssResult, cssSyntaxError);

return stylelint.getConfigForFile(filePath).then((configForFile) => {
// TODO TYPES handle possible null here
const config = /** @type {{ config: import('stylelint').StylelintConfig, filepath: string }} */ (configForFile)
.config;
const file = source || (cssSyntaxError && cssSyntaxError.file);
const file = stylelintResult.source || (cssSyntaxError && cssSyntaxError.file);

if (config.resultProcessors) {
config.resultProcessors.forEach((resultProcessor) => {
Expand Down
7 changes: 6 additions & 1 deletion lib/getPostcssResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,15 @@ module.exports = function (stylelint, options = {}) {
} else if (!(options.codeProcessors && options.codeProcessors.length)) {
const autoSyntax = require('postcss-syntax');

// TODO: investigate why lazy import HTML syntax causes
// JS files with the word "html" to throw TypeError
// https://github.com/stylelint/stylelint/issues/4793
const { html, ...rest } = syntaxes;

syntax = autoSyntax({
css: cssSyntax(stylelint),
jsx: syntaxes['css-in-js'],
...syntaxes,
...rest,
});
}

Expand Down
41 changes: 41 additions & 0 deletions lib/normalizeAllRuleSettings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';

const _ = require('lodash');
const normalizeRuleSettings = require('./normalizeRuleSettings');
const rules = require('./rules');

/** @typedef {import('stylelint').StylelintConfigRules} StylelintConfigRules */
/** @typedef {import('stylelint').StylelintConfig} StylelintConfig */

/**
* @param {StylelintConfig} config
* @return {StylelintConfig}
*/
function normalizeAllRuleSettings(config) {
/** @type {StylelintConfigRules} */
const normalizedRules = {};

if (!config.rules) return config;

Object.keys(config.rules).forEach((ruleName) => {
const rawRuleSettings = _.get(config, ['rules', ruleName]);

const rule = rules[ruleName] || _.get(config, ['pluginFunctions', ruleName]);

if (!rule) {
normalizedRules[ruleName] = [];
} else {
normalizedRules[ruleName] = normalizeRuleSettings(
rawRuleSettings,
ruleName,
_.get(rule, 'primaryOptionArray'),
);
}
});

config.rules = normalizedRules;

return config;
}

module.exports = normalizeAllRuleSettings;
Loading

0 comments on commit 336a4f0

Please sign in to comment.