Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions __tests__/typography.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ testRule({
description: 'CSS > Accepts font size variables',
},
// Font weights
{
code: '.x { font-weight: var(--base-text-weight-semibold); }',
description: 'CSS > Accepts base font weight variables',
},
{
code: '.x { font-weight: var(--text-title-weight-medium); }',
description: 'CSS > Accepts functional font weight variables',
Expand All @@ -49,6 +45,34 @@ testRule({
},
],
reject: [
// Base token warnings
{
code: '.x { font-weight: var(--base-text-weight-semibold); }',
unfixable: true,
message: messages.baseToken('var(--base-text-weight-semibold)'),
line: 1,
column: 19,
endColumn: 51,
description: 'CSS > Warns on base font weight variable',
},
{
code: '.x { font-size: var(--base-text-size-2xl); }',
unfixable: true,
message: messages.baseToken('var(--base-text-size-2xl)'),
line: 1,
column: 17,
endColumn: 42,
description: 'CSS > Warns on base font size variable',
},
{
code: '.x { line-height: var(--base-text-lineHeight-normal); }',
unfixable: true,
message: messages.baseToken('var(--base-text-lineHeight-normal)'),
line: 1,
column: 19,
endColumn: 53,
description: 'CSS > Warns on base line height variable',
},
// Font sizes
{
code: '.x { font-size: 42px; }',
Expand Down
31 changes: 31 additions & 0 deletions plugins/typography.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const messages = ruleMessages(ruleName, {
// one possible replacement
return `Please replace '${value}' with Primer typography variable '${replacement['name']}'. https://primer.style/foundations/primitives/typography`
},
baseToken: value =>
`'${value}' is a base token. Consider using a functional Primer typography variable instead. https://primer.style/foundations/primitives/typography`,
})

const fontWeightKeywordMap = {
Expand Down Expand Up @@ -118,6 +120,18 @@ const ruleFunction = primary => {
}

if (checkForVariable(validValues, value)) {
// Warn when using base tokens (e.g. --base-text-weight-*) instead of functional tokens
if (/var\(--base-/.test(value)) {
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The regex /var\(--base-/ doesn't account for optional whitespace inside var(). While uncommon, a declaration like font-weight: var( --base-text-weight-semibold ) would pass checkForVariable (matching the variable name) but not trigger the warning (the regex expects var(--base- with no space). Consider using a more lenient pattern such as /var\(\s*--base-/ for robustness.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

While this would make the code stronger, I think we have formatting rules that wouldn't allow you to include whitespace inside the var declaration. I'm fine shipping as is

report({
index: declarationValueIndex(declNode),
endIndex: declarationValueIndex(declNode) + value.length,
message: messages.baseToken(value),
node: declNode,
result,
ruleName,
severity: 'warning',
})
}
Comment on lines +124 to +134
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The __tests__/__fixtures__/good/ fixture files still contain base typography tokens that will now trigger warnings:

  • example.pcss:19font-weight: var(--base-text-weight-medium)
  • example.scss:19font-weight: var(--base-text-weight-semibold)
  • example.scss:23font-weight: var(--base-text-weight-normal)

While warnings won't cause npm run test:stylelint to exit with a non-zero code, the "good" fixtures are conceptually the reference for clean/passing code. These files should be updated to use functional tokens (e.g., --text-title-weight-medium) or have /* stylelint-disable primer/typography */ comments to suppress the warning, keeping the fixtures truly warning-free.

Copilot uses AI. Check for mistakes.
return
}

Expand All @@ -144,10 +158,13 @@ const ruleFunction = primary => {
}
const replacement = getReplacements()
const fixable = replacement && !replacement.length
const isBaseTokenFix = fixable && replacement['name'].startsWith('--base-')
let didFix = false
let fix = undefined
if (fixable) {
fix = () => {
declNode.value = value.replace(value, `var(${replacement['name']})`)
didFix = true
}
}

Expand All @@ -160,6 +177,20 @@ const ruleFunction = primary => {
ruleName,
fix,
})

// When auto-fix replaces a value with a base token, also report the base token warning
if (didFix && isBaseTokenFix) {
const newValue = declNode.value
report({
index: declarationValueIndex(declNode),
endIndex: declarationValueIndex(declNode) + newValue.length,
message: messages.baseToken(newValue),
node: declNode,
result,
ruleName,
severity: 'warning',
})
}
Comment on lines +182 to +193
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The didFix && isBaseTokenFix code path (lines 182–193) only fires in Stylelint's fix mode, and none of the test cases verify that the baseToken warning is actually emitted after a fix. The existing fixable test cases (e.g., font-weight: 500) only assert the rejected message, which is evaluated in non-fix mode. Consider adding a test that validates the baseToken warning is emitted post-fix — for instance, by using warnings (plural) with two entries for a fixable case, or by adding a dedicated test that runs in fix mode and checks for the warning on the fixed output.

Copilot uses AI. Check for mistakes.
})
}
}
Expand Down
Loading