Skip to content

Commit 5afa2a0

Browse files
authoredJul 27, 2020
Check and enforce quotes with punctuations (#101)
1 parent 4e0aead commit 5afa2a0

File tree

5 files changed

+324
-16
lines changed

5 files changed

+324
-16
lines changed
 

‎rules/list-item.js

+30-3
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,39 @@ function validateListItemPrefix(descriptionText, prefixText) {
276276
}
277277

278278
function validateListItemSuffix(descriptionText, suffixText) {
279-
if (/[.!?]\s*$/.test(suffixText)) {
280-
// Description ends with '.', '!', '?' or '…'
279+
// Punctuation rules are available at: https://www.thepunctuationguide.com
280+
281+
// Descriptions are not allowed to be fully backticked quotes, whatever the
282+
// ending punctuation and its position.
283+
if (/^`.*[.!?]*`[.!?]*$/.test(descriptionText)) {
284+
// Still allow multiple backticks if the whole description is not fully
285+
// quoted.
286+
if (/^`.+`.+`.+$/.test(descriptionText)) {
287+
return true;
288+
}
289+
290+
return false;
291+
}
292+
293+
// Any kind of quote followed by one of our punctuaction marker is perfect,
294+
// but only if not following a punctuation itself. Uses positive lookbehind
295+
// to search for punctuation following a quote.
296+
if (/.*(?<=["])[.!?]+$/.test(descriptionText)) {
297+
// If the quote follows a regular punctuation, this is wrong.
298+
if (/.*[.!?]["][.!?]+$/.test(descriptionText)) {
299+
return false;
300+
}
301+
302+
return true;
303+
}
304+
305+
// Any of our punctuation marker eventually closed by any kind of quote is
306+
// good.
307+
if (/.*[.!?]["]?$/.test(descriptionText)) {
281308
return true;
282309
}
283310

284-
if (!/[.!?]/.test(descriptionText)) {
311+
if (!/[.!?]/.test(descriptionText)) {
285312
// Description contains no punctuation
286313
const tokens = tokenizeWords(descriptionText);
287314
if (tokens.length > 2 || !textEndsWithEmoji(tokens[tokens.length - 1])) {

‎test/fixtures/list-item/0.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@ All list-items in this document should be linted as **valid**.
33
- [foo](https://foo.com) - Valid description.
44
- [foo](https://foo.com) - A valid description.
55
- [foo](https://foo.com) - A valid description...
6+
- [foo](https://foo.com) - A valid description.......
67
- [foo](https://foo.com) - A valid description…
8+
- [foo](https://foo.com) - A valid description..….....
79
- [foo](https://foo.com) - A valid description!
810
- [foo](https://foo.com) - A valid description! ⭐
911
- [foo](https://foo.com) - A valid description!!!
1012
- [foo](https://foo.com) - A valid description?
1113
- [foo](https://foo.com) - A valid description???
1214
- [foo](https://foo.com) - A valid description????!??
15+
- [foo](https://foo.com) - A valid description..…!?…....
1316
- [foo](https://foo.com) - A valid description with [link](https://bar.org).
1417
- [foo](https://foo.com) - A valid description. ![image](image.png)
1518
- [foo](https://foo.com) - A valid description. <img src="image.png">
1619
- [foo](https://foo.com) - `valid description` here.
17-
- [foo](https://foo.com) - `valid description`.
20+
- [foo](https://foo.com) - `valid` is a word that is `great`.
21+
- [foo](https://foo.com) - `valid` is a word that is `great`!?!.
1822
- [foo](https://foo.com) - VaLid description.
1923
- [foo](https://foo.com) - anoTher valid description with pascalCase.
2024
- [foo](https://foo.com) - Valid sub-item.
@@ -44,6 +48,30 @@ These are valid list items that don't need a description.
4448
- [foo](https://foo.com) - "Catan" inspired board game.
4549
- [foo](https://foo.com) - 'About This App' window.
4650

51+
Test description's ending punctuation.
52+
- [foo](https://foo.com) - Ending with a period.
53+
- [foo](https://foo.com) - Ending with an exclamation mark!
54+
- [foo](https://foo.com) - Ending with a question mark?
55+
- [foo](https://foo.com) - Ending with an ellipsis…
56+
57+
- [foo](https://foo.com) - Ending with a "non-quoted period".
58+
- [foo](https://foo.com) - Ending with a "non-quoted exclamation point"!
59+
- [foo](https://foo.com) - Ending with a "non-quoted question mark"?
60+
- [foo](https://foo.com) - Ending with a "non-quoted ellipsis"…
61+
- [foo](https://foo.com) - Ending with another kind of “non-quoted period”.
62+
- [foo](https://foo.com) - Ending with another kind of “non-quoted exclamation point”!
63+
- [foo](https://foo.com) - Ending with another kind of “non-quoted question mark”?
64+
- [foo](https://foo.com) - Ending with another kind of “non-quoted ellipsis”…
65+
66+
- [foo](https://foo.com) - "Description is a full quote ending with a period."
67+
- [foo](https://foo.com) - "Description is a full quote ending with an exclamation point!"
68+
- [foo](https://foo.com) - "Description is a full quote ending with a question mark?"
69+
- [foo](https://foo.com) - "Description is a full quote ending with an ellipsis…"
70+
- [foo](https://foo.com) - “Description is an other king of full quote ending with a period.”
71+
- [foo](https://foo.com) - “Description is an other king of full quote ending with an exclamation point!”
72+
- [foo](https://foo.com) - “Description is an other king of full quote ending with a question mark?”
73+
- [foo](https://foo.com) - “Description is an other king of full quote ending with an ellipsis…”
74+
4775
- [foo](https://foo.com) - Ending with a parenthetical. (Japanese)
4876
- [foo](https://foo.com) - Ending with an emphasis parenthetical. *(Japanese)*
4977
- [foo](https://foo.com) - Ending with a strong parenthetical. **(Japanese)**

‎test/fixtures/list-item/1.md

+54-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ All list-items in this document should be linted as **invalid**.
33
- [foo](https://foo.com) - an invalid description.
44
- [foo](https://foo.com) - invalid description.
55
- [foo](https://foo.com) - invalid dash separator.
6-
- [foo](https://foo.com) - `invalid description.`
76
- [foo]() - Invalid url.
87
- [foo](test) - Invalid url.
98
- [](https://foo.com) - Invalid link text.
@@ -15,3 +14,57 @@ All list-items in this document should be linted as **invalid**.
1514

1615
- [sparkly](https://github.com/sindresorhus/sparkly) - Generate sparklines ▁▂▃▅▂▇
1716
- [cat-ascii-faces](https://github.com/melaniecebula/cat-ascii-faces) - ₍˄·͈༝·͈˄₎◞ ̑̑ෆ⃛ (=ↀωↀ=)✧ (^・o・^)ノ”
17+
18+
Test description's ending punctuation.
19+
- [foo](https://foo.com) - Missing ending punctuation
20+
21+
- [foo](https://foo.com) - ``
22+
- [foo](https://foo.com) - `invalid quote: too noisy`
23+
- [foo](https://foo.com) - `still invalid quote, even with a period.`
24+
- [foo](https://foo.com) - `still invalid quote, even with an exclamation mark!`
25+
- [foo](https://foo.com) - `still invalid quote, even with a question mark?`
26+
- [foo](https://foo.com) - `still invalid quote, even with an ellipsis…`
27+
- [foo](https://foo.com) - `still invalid quote, even ending with a period`.
28+
- [foo](https://foo.com) - `still invalid quote, even ending with an exclamation mark`!
29+
- [foo](https://foo.com) - `still invalid quote, even ending with a question mark`?
30+
- [foo](https://foo.com) - `still invalid quote, even ending with an ellipsis`
31+
32+
- [foo](https://foo.com) - `still invalid quote, ending with too much punctuations`…...?
33+
- [foo](https://foo.com) - `still invalid quote, ending with too much punctuations...!?`…...?
34+
35+
- [foo](https://foo.com) - Quote-inducing double punctuation "end.".
36+
- [foo](https://foo.com) - Quote-inducing double punctuation "end."!
37+
- [foo](https://foo.com) - Quote-inducing double punctuation "end."?
38+
- [foo](https://foo.com) - Quote-inducing double punctuation "end."…
39+
- [foo](https://foo.com) - Quote-inducing double punctuation "end!".
40+
- [foo](https://foo.com) - Quote-inducing double punctuation "end!"!
41+
- [foo](https://foo.com) - Quote-inducing double punctuation "end!"?
42+
- [foo](https://foo.com) - Quote-inducing double punctuation "end!"…
43+
- [foo](https://foo.com) - Quote-inducing double punctuation "end?".
44+
- [foo](https://foo.com) - Quote-inducing double punctuation "end?"!
45+
- [foo](https://foo.com) - Quote-inducing double punctuation "end?"?
46+
- [foo](https://foo.com) - Quote-inducing double punctuation "end?"…
47+
- [foo](https://foo.com) - Quote-inducing double punctuation "end…".
48+
- [foo](https://foo.com) - Quote-inducing double punctuation "end…"!
49+
- [foo](https://foo.com) - Quote-inducing double punctuation "end…"?
50+
- [foo](https://foo.com) - Quote-inducing double punctuation "end…"…
51+
52+
- [foo](https://foo.com) - Quote-inducing double punctuation “end.”.
53+
- [foo](https://foo.com) - Quote-inducing double punctuation “end.”!
54+
- [foo](https://foo.com) - Quote-inducing double punctuation “end.”?
55+
- [foo](https://foo.com) - Quote-inducing double punctuation “end.”…
56+
- [foo](https://foo.com) - Quote-inducing double punctuation “end!”.
57+
- [foo](https://foo.com) - Quote-inducing double punctuation “end!”!
58+
- [foo](https://foo.com) - Quote-inducing double punctuation “end!”?
59+
- [foo](https://foo.com) - Quote-inducing double punctuation “end!”…
60+
- [foo](https://foo.com) - Quote-inducing double punctuation “end?”.
61+
- [foo](https://foo.com) - Quote-inducing double punctuation “end?”!
62+
- [foo](https://foo.com) - Quote-inducing double punctuation “end?”?
63+
- [foo](https://foo.com) - Quote-inducing double punctuation “end?”…
64+
- [foo](https://foo.com) - Quote-inducing double punctuation “end…”.
65+
- [foo](https://foo.com) - Quote-inducing double punctuation “end…”!
66+
- [foo](https://foo.com) - Quote-inducing double punctuation “end…”?
67+
- [foo](https://foo.com) - Quote-inducing double punctuation “end…”…
68+
69+
- [foo](https://foo.com) - Quote-inducing double punctuation “end…”??!
70+
- [foo](https://foo.com) - Quote-inducing double punctuation “end?…...”…...?

0 commit comments

Comments
 (0)
Please sign in to comment.