Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize type definitions #6510

Merged
merged 5 commits into from Dec 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sharp-papayas-grab.md
@@ -0,0 +1,5 @@
---
"stylelint": major
---

Changed: type definitions to reorganize
10 changes: 3 additions & 7 deletions lib/augmentConfig.js
Expand Up @@ -8,10 +8,6 @@ const normalizeAllRuleSettings = require('./normalizeAllRuleSettings');
const normalizePath = require('normalize-path');
const path = require('path');

/** @typedef {import('stylelint').ConfigExtends} StyleLintConfigExtends */
/** @typedef {import('stylelint').ConfigPlugins} StylelintConfigPlugins */
/** @typedef {import('stylelint').ConfigRules} StylelintConfigRules */
/** @typedef {import('stylelint').ConfigOverride} StylelintConfigOverride */
/** @typedef {import('stylelint').InternalApi} StylelintInternalApi */
/** @typedef {import('stylelint').Config} StylelintConfig */
/** @typedef {import('stylelint').CosmiconfigResult} StylelintCosmiconfigResult */
Expand Down Expand Up @@ -220,7 +216,7 @@ function loadExtendedConfig(stylelint, configDir, extendLookup) {
* @returns {StylelintConfig}
*/
function mergeConfigs(a, b) {
/** @type {{plugins: StylelintConfigPlugins}} */
/** @type {Pick<StylelintConfig, 'plugins'>} */
const pluginMerger = {};

if (a.plugins || b.plugins) {
Expand All @@ -235,7 +231,7 @@ function mergeConfigs(a, b) {
}
}

/** @type {{overrides: StylelintConfigOverride[]}} */
/** @type {Pick<StylelintConfig, 'overrides'>} */
const overridesMerger = {};

if (a.overrides || b.overrides) {
Expand All @@ -250,7 +246,7 @@ function mergeConfigs(a, b) {
}
}

/** @type {{extends: StyleLintConfigExtends}} */
/** @type {Pick<StylelintConfig, 'extends'>} */
const extendsMerger = {};

if (a.extends || b.extends) {
Expand Down
2 changes: 1 addition & 1 deletion lib/createPlugin.js
@@ -1,7 +1,7 @@
'use strict';

/**
* @type {typeof import('stylelint').createPlugin}
* @type {import('stylelint').default['createPlugin']}
*/
module.exports = function createPlugin(ruleName, rule) {
return {
Expand Down
8 changes: 1 addition & 7 deletions lib/createStylelint.js
Expand Up @@ -8,14 +8,8 @@ const FileCache = require('./utils/FileCache');
const IS_TEST = process.env.NODE_ENV === 'test';
const STOP_DIR = IS_TEST ? process.cwd() : undefined;

/** @typedef {import('stylelint').InternalApi} StylelintInternalApi */

/**
* The stylelint "internal API" is passed among functions
* so that methods on a stylelint instance can invoke
* each other while sharing options and caches.
*
* @type {import('stylelint')['createLinter']}
* @type {import('stylelint').default['_createLinter']}
*/
module.exports = function createStylelint(options = {}) {
const cwd = options.cwd || process.cwd();
Expand Down
1 change: 0 additions & 1 deletion lib/descriptionlessDisables.js
Expand Up @@ -4,7 +4,6 @@ const optionsMatches = require('./utils/optionsMatches');
const validateDisableSettings = require('./validateDisableSettings');

/** @typedef {import('postcss').Comment} PostcssComment */
/** @typedef {import('stylelint').RangeType} RangeType */
/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */
/** @typedef {import('stylelint').DisableOptionsReport} StylelintDisableOptionsReport */

Expand Down
2 changes: 1 addition & 1 deletion lib/formatters/index.js
Expand Up @@ -2,7 +2,7 @@

const importLazy = require('import-lazy');

/** @type {typeof import('stylelint').formatters} */
/** @type {import('stylelint').default['formatters']} */
const formatters = {
compact: importLazy(() => require('./compactFormatter'))(),
github: importLazy(() => require('./githubFormatter'))(),
Expand Down
4 changes: 2 additions & 2 deletions lib/index.js
Expand Up @@ -13,14 +13,14 @@ const { longhandSubPropertiesOfShorthandProperties } = require('./reference/prop
const standalone = require('./standalone');
const validateOptions = require('./utils/validateOptions');

/** @type {import('stylelint').PublicApi} */
/** @type {import('stylelint').default} */
const stylelint = Object.assign(postcssPlugin, {
lint: standalone,
rules,
formatters,
createPlugin,
resolveConfig,
createLinter: createStylelint,
_createLinter: createStylelint,
utils: {
report,
ruleMessages,
Expand Down
2 changes: 0 additions & 2 deletions lib/invalidScopeDisables.js
Expand Up @@ -3,8 +3,6 @@
const optionsMatches = require('./utils/optionsMatches');
const validateDisableSettings = require('./validateDisableSettings');

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

/**
* @param {import('stylelint').LintResult[]} results
*/
Expand Down
3 changes: 1 addition & 2 deletions lib/needlessDisables.js
Expand Up @@ -6,7 +6,6 @@ const validateDisableSettings = require('./validateDisableSettings');

/** @typedef {import('postcss').Comment} PostcssComment */
/** @typedef {import('stylelint').DisabledRange} DisabledRange */
/** @typedef {import('stylelint').RangeType} RangeType */
/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */

/**
Expand Down Expand Up @@ -88,7 +87,7 @@ module.exports = function needlessDisables(results) {

/**
* @param {import('stylelint').DisabledWarning} warning
* @param {RangeType} range
* @param {DisabledRange} range
* @return {boolean}
*/
function isWarningInRange(warning, range) {
Expand Down
3 changes: 1 addition & 2 deletions lib/normalizeAllRuleSettings.js
Expand Up @@ -3,7 +3,6 @@
const normalizeRuleSettings = require('./normalizeRuleSettings');
const getStylelintRule = require('./utils/getStylelintRule');

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

/**
Expand All @@ -13,7 +12,7 @@ const getStylelintRule = require('./utils/getStylelintRule');
function normalizeAllRuleSettings(config) {
if (!config.rules) return config;

/** @type {StylelintConfigRules} */
/** @type {StylelintConfig['rules']} */
const normalizedRules = {};

for (const [ruleName, rawRuleSettings] of Object.entries(config.rules)) {
Expand Down
2 changes: 0 additions & 2 deletions lib/reportDisables.js
@@ -1,6 +1,5 @@
'use strict';

/** @typedef {import('stylelint').RangeType} RangeType */
/** @typedef {import('stylelint').DisableReportRange} DisabledRange */
/** @typedef {import('stylelint').LintResult} StylelintResult */
/** @typedef {import('stylelint').ConfigRuleSettings<any, Object>} StylelintConfigRuleSettings */
Expand All @@ -18,7 +17,6 @@ module.exports = function reportDisables(results) {
continue;
}

/** @type {{[ruleName: string]: Array<RangeType>}} */
const rangeData = result._postcssResult.stylelint.disabledRanges;

if (!rangeData) continue;
Expand Down
12 changes: 1 addition & 11 deletions lib/resolveConfig.js
Expand Up @@ -6,17 +6,7 @@ const createStylelint = require('./createStylelint');
const getConfigForFile = require('./getConfigForFile');

/**
* Resolves the effective configuration for a given file. Resolves to `undefined`
* if no config is found.
* @param {string} filePath - The path to the file to get the config for.
* @param {Pick<
* import('stylelint').LinterOptions,
* | 'cwd'
* | 'config'
* | 'configBasedir'
* | 'configFile'
* >} options - The options to use when creating the Stylelint instance.
* @returns {Promise<import('stylelint').Config | undefined>}
* @type {import('stylelint').default['resolveConfig']}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[note] To reduce duplication, I've moved the description in JSDoc to the .d.ts file.

*/
module.exports = async function resolveConfig(
filePath,
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/index.js
Expand Up @@ -2,7 +2,7 @@

const importLazy = require('import-lazy');

/** @type {typeof import('stylelint').rules} */
/** @type {import('stylelint').default['rules']} */
const rules = {
'alpha-value-notation': importLazy(() => require('./alpha-value-notation'))(),
'annotation-no-unknown': importLazy(() => require('./annotation-no-unknown'))(),
Expand Down
11 changes: 3 additions & 8 deletions lib/standalone.js
Expand Up @@ -22,16 +22,11 @@ const prepareReturnValue = require('./prepareReturnValue');
const ALWAYS_IGNORED_GLOBS = ['**/node_modules/**'];
const writeFileAtomic = require('write-file-atomic');

/** @typedef {import('stylelint').LinterOptions} LinterOptions */
/** @typedef {import('stylelint').LinterResult} LinterResult */
/** @typedef {import('stylelint').LintResult} StylelintResult */
/** @typedef {import('stylelint').Formatter} Formatter */
/** @typedef {import('stylelint').FormatterType} FormatterType */

/**
*
* @param {LinterOptions} options
* @returns {Promise<LinterResult>}
* @type {import('stylelint').default['lint']}
*/
async function standalone({
allowEmptyInput = false,
Expand Down Expand Up @@ -304,7 +299,7 @@ function getFormatterFunction(selected) {
* @typedef {import('stylelint').CssSyntaxError} CssSyntaxError
*
* @param {unknown} error
* @return {StylelintResult}
* @return {import('stylelint').LintResult}
*/
function handleError(error) {
if (error instanceof Error && error.name === 'CssSyntaxError') {
Expand All @@ -314,4 +309,4 @@ function handleError(error) {
throw error;
}

module.exports = /** @type {typeof import('stylelint').lint} */ (standalone);
module.exports = standalone;
5 changes: 1 addition & 4 deletions lib/utils/checkAgainstRule.js
Expand Up @@ -6,10 +6,7 @@ const { isPlainObject } = require('./validateTypes');
const getStylelintRule = require('./getStylelintRule');

/**
* Useful for third-party code (e.g. plugins) to run a PostCSS Root
* against a specific rule and do something with the warnings
*
* @type {typeof import('stylelint').utils.checkAgainstRule}
* @type {import('stylelint').Utils['checkAgainstRule']}
*/
function checkAgainstRule(options, callback) {
if (!isPlainObject(options)) throw new Error('Expected an options object');
Expand Down
5 changes: 3 additions & 2 deletions lib/utils/configurationError.js
@@ -1,9 +1,10 @@
'use strict';

/** @typedef {import('stylelint').ConfigurationError} ConfigurationError */
/** @typedef {Error & { code: number }} ConfigurationError */

/**
* Create configurationError from text and set CLI exit code
* Create configurationError from text and set CLI exit code.
*
* @param {string} text
* @returns {ConfigurationError}
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/report.js
Expand Up @@ -12,7 +12,7 @@
*
* You *must* pass *either* a node or a line number.
*
* @type {typeof import('stylelint').utils.report}
* @type {import('stylelint').Utils['report']}
*/
module.exports = function report(problem) {
const { ruleName, result, message, messageArgs, line, node, index, endIndex, word, severity } =
Expand Down
30 changes: 9 additions & 21 deletions lib/utils/ruleMessages.js
@@ -1,32 +1,20 @@
'use strict';

/**
* Given an object of problem messages, return another
* that provides the same messages postfixed with the rule
* that has been violated.
*
* @template {import('stylelint').RuleMessages} T
* @template {{[K in keyof T]: T[K]}} R
* @param {string} ruleName
* @param {T} messages - Object whose keys are message identifiers
* and values are either message strings or functions that return message strings
* @returns {R} New message object, whose messages will be marked with the rule name
* @type {import('stylelint').Utils['ruleMessages']}
*/
function ruleMessages(ruleName, messages) {
/** @typedef {keyof T} K */
const newMessages = /** @type {R} */ ({});
module.exports = function ruleMessages(ruleName, messages) {
/** @type {import('stylelint').RuleMessages} */
const newMessages = {};

for (const [messageId, messageText] of /** @type {[K, T[K]][]} */ (Object.entries(messages))) {
for (const [messageId, messageText] of Object.entries(messages)) {
if (typeof messageText === 'string') {
newMessages[messageId] = /** @type {R[K]} */ (`${messageText} (${ruleName})`);
newMessages[messageId] = `${messageText} (${ruleName})`;
} else {
newMessages[messageId] = /** @type {R[K]} */ (
(...args) => `${messageText(...args)} (${ruleName})`
);
newMessages[messageId] = (...args) => `${messageText(...args)} (${ruleName})`;
}
}

// @ts-expect-error -- TS2322: Type 'RuleMessages' is not assignable to type 'R'.
return newMessages;
}

module.exports = /** @type {typeof import('stylelint').utils.ruleMessages} */ (ruleMessages);
};
30 changes: 5 additions & 25 deletions lib/utils/validateOptions.js
Expand Up @@ -6,30 +6,12 @@ const { isPlainObject } = require('./validateTypes');
const IGNORED_OPTIONS = new Set(['severity', 'message', 'reportDisables', 'disableFix']);

/** @typedef {import('stylelint').RuleOptions} RuleOptions */
/** @typedef {import('stylelint').RuleOptionsPossible} Possible */
/** @typedef {import('stylelint').RuleOptionsPossibleFunc} PossibleFunc */
/** @typedef {import('stylelint').RuleOptionsPossible} RuleOptionsPossible */

/**
* Validate a rule's options.
*
* See existing rules for examples.
*
* @param {import('stylelint').PostcssResult} result - postcss result
* @param {string} ruleName
* @param {...RuleOptions} optionDescriptions - Each optionDescription can
* have the following properties:
* - `actual` (required): the actual passed option value or object.
* - `possible` (required): a schema representation of what values are
* valid for those options. `possible` should be an object if the
* options are an object, with corresponding keys; if the options are not an
* object, `possible` isn't, either. All `possible` value representations
* should be **arrays of either values or functions**. Values are === checked
* against `actual`. Functions are fed `actual` as an argument and their
* return value is interpreted: truthy = valid, falsy = invalid.
* - `optional` (optional): If this is `true`, `actual` can be undefined.
* @return {boolean} Whether or not the options are valid (true = valid)
* @type {import('stylelint').Utils['validateOptions']}
*/
function validateOptions(result, ruleName, ...optionDescriptions) {
module.exports = function validateOptions(result, ruleName, ...optionDescriptions) {
let noErrors = true;

for (const optionDescription of optionDescriptions) {
Expand All @@ -54,7 +36,7 @@ function validateOptions(result, ruleName, ...optionDescriptions) {
}

return noErrors;
}
};

/**
* @param {RuleOptions} opts
Expand Down Expand Up @@ -161,7 +143,7 @@ function validate(opts, ruleName, complain) {
}

/**
* @param {Possible | Possible[]} possible
* @param {RuleOptionsPossible | RuleOptionsPossible[]} possible
* @param {unknown} actual
* @returns {boolean}
*/
Expand Down Expand Up @@ -190,5 +172,3 @@ function stringify(value) {

return `"${JSON.stringify(value)}"`;
}

module.exports = /** @type {typeof import('stylelint').utils.validateOptions} */ (validateOptions);