Skip to content

Commit 70a4450

Browse files
authored
fix(rules): avoid processing strings with case-less Letter category symbols in subject-case (#3586)
* feat(rules): expand Latin-only characters limitation for `subject-case` with Unicode support * fix(rules): avoid processing strings with case-less Letter category symbols in `subject-case` Fixes #3585
1 parent 28bc4c7 commit 70a4450

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

@commitlint/rules/src/subject-case.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const messages = {
77
lowercase: 'test: subject',
88
lowercase_unicode: 'test: тема', // Bulgarian for `subject`
99
mixedcase: 'test: sUbJeCt',
10+
caseless: 'test: 这是一次提交', // Chinese for `this is a commit`
1011
uppercase: 'test: SUBJECT',
1112
uppercase_unicode: 'test: ÛNDERWERP', // Frisian for `SUBJECT`
1213
camelcase: 'test: subJect',
@@ -29,6 +30,7 @@ const parsed = {
2930
lowercase: parse(messages.lowercase),
3031
lowercase_unicode: parse(messages.lowercase_unicode),
3132
mixedcase: parse(messages.mixedcase),
33+
caseless: parse(messages.caseless),
3234
uppercase: parse(messages.uppercase),
3335
uppercase_unicode: parse(messages.uppercase_unicode),
3436
camelcase: parse(messages.camelcase),
@@ -115,6 +117,24 @@ test('with mixedcase subject should fail for "always uppercase"', async () => {
115117
expect(actual).toEqual(expected);
116118
});
117119

120+
test('with caseless subject should succeed for "never sentensecase"', async () => {
121+
const [actual] = subjectCase(await parsed.caseless, 'never', 'sentense-case');
122+
const expected = true;
123+
expect(actual).toEqual(expected);
124+
});
125+
126+
test('with caseless subject should succeed for "never uppercase"', async () => {
127+
const [actual] = subjectCase(await parsed.caseless, 'never', 'upper-case');
128+
const expected = true;
129+
expect(actual).toEqual(expected);
130+
});
131+
132+
test('with caseless subject should succeed for "always uppercase"', async () => {
133+
const [actual] = subjectCase(await parsed.caseless, 'always', 'upper-case');
134+
const expected = true;
135+
expect(actual).toEqual(expected);
136+
});
137+
118138
test('with uppercase subject should fail for "never uppercase"', async () => {
119139
const [actual] = subjectCase(await parsed.uppercase, 'never', 'uppercase');
120140
const expected = false;

@commitlint/rules/src/subject-case.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import {TargetCaseType, SyncRule} from '@commitlint/types';
44

55
/**
66
* Since the rule requires first symbol of a subject to be a letter, use
7-
* combination of Unicode `Cased_Letter` and `Other_Letter` categories now to
8-
* allow non-Latin alphabets as well.
7+
* Unicode `Cased_Letter` category now to allow non-Latin alphabets as well.
98
*
109
* Do not use `Letter` category directly to avoid capturing `Modifier_Letter`
11-
* (which just modifiers letters, so we probably shouldn't anyway) and to stay
12-
* close to previous implementation.
10+
* (which just modifiers letters, so we probably shouldn't anyway) and
11+
* `Other_Letter` (they actually are case-less, so they can't be validated)
12+
* categories, and to stay close to previous implementation.
1313
*
1414
* Also, typescript does not seem to support almost any longhand category name
1515
* (and even short for `Cased_Letter` too) so list all required letter
1616
* categories manually just to prevent it from complaining about unknown stuff.
1717
*
1818
* @see [Unicode Categories]{@link https://www.regular-expressions.info/unicode.html}
1919
*/
20-
const startsWithLetterRegex = /^[\p{Ll}\p{Lu}\p{Lt}\p{Lo}]/iu;
20+
const startsWithLetterRegex = /^[\p{Ll}\p{Lu}\p{Lt}]/iu;
2121

2222
const negated = (when?: string) => when === 'never';
2323

0 commit comments

Comments
 (0)