Skip to content

Commit 0a407bb

Browse files
committed
feat: add useCurrentYearIfMissing option to support dates without year
1 parent e7dd817 commit 0a407bb

File tree

3 files changed

+100
-3
lines changed

3 files changed

+100
-3
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ But, You can specify `2016-12-30` is `ja-JP` text by options
8787
}
8888
```
8989

90+
- `useCurrentYearIfMissing`: boolean
91+
- Default: false
92+
- If true, when the year is missing in the date string (e.g. `4月23日(月)`), the current year will be automatically added for validation.
93+
- This is useful for documents that often omit the year in dates.
94+
95+
```json
96+
{
97+
"rules": {
98+
"date-weekday-mismatch": {
99+
"useCurrentYearIfMissing": true
100+
}
101+
}
102+
}
103+
```
104+
90105
language format following ISO 639-1.
91106

92107
e.g.) `en-US`, `en`, `ja` etc..

src/textlint-rule-date-weekday-mismatch.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,38 @@ const detectLang = (tags, preferLang) => {
5050
const selectedLang = targetLangs[0];
5151
return selectedLang[1];
5252
};
53+
54+
/**
55+
* Add current year to date string if missing.
56+
* @param {string} dateText
57+
* @param {number} year
58+
* @param {string} lang
59+
* @returns {string}
60+
*/
61+
function addYearToDateText(dateText, year, lang) {
62+
// Japanese: 4月23日(月) → 2024年4月23日(月)
63+
if (lang === "ja") {
64+
return `${year}${dateText}`;
65+
}
66+
// Slash: 4/23(月) → 2024/4/23(月)
67+
if (/^[0-9]{1,2}\/[0-9]{1,2}/.test(dateText)) {
68+
return `${year}/${dateText}`;
69+
}
70+
// Dash: 4-23(Mon) → 2024-4-23(Mon)
71+
if (/^[0-9]{1,2}-[0-9]{1,2}/.test(dateText)) {
72+
return `${year}-${dateText}`;
73+
}
74+
// Default: prepend year and a space
75+
return `${year} ${dateText}`;
76+
}
5377
/**
5478
*
5579
* @param context
5680
* @param {Object} [config]
5781
*/
5882
function reporter(context, config = {}) {
5983
const preferLang = config.lang;
84+
const useCurrentYearIfMissing = config.useCurrentYearIfMissing;
6085
const {Syntax, RuleError, report, fixer, getSource} = context;
6186
if (typeof Intl === "undefined") {
6287
throw new Error("Not support your Node.js/browser. should be use latest version.");
@@ -65,7 +90,29 @@ function reporter(context, config = {}) {
6590
return {
6691
[Syntax.Str](node){
6792
const text = getSource(node);
68-
const chronoDates = chrono.parse(text);
93+
let chronoDates = chrono.parse(text);
94+
// Add current year if missing and option is enabled
95+
if (useCurrentYearIfMissing) {
96+
const currentYear = (new Date()).getFullYear();
97+
chronoDates.forEach(chronoDate => {
98+
// If year is not specified in the parsed result
99+
if (
100+
chronoDate.start &&
101+
chronoDate.start.knownValues.year === undefined
102+
) {
103+
// Detect language for the date string
104+
const lang = detectLang(Object.keys(chronoDate.tags), preferLang);
105+
if (!lang) return;
106+
// Re-parse the text with the year added
107+
const newText = addYearToDateText(chronoDate.text, currentYear, lang);
108+
const reparsed = chrono.parse(newText, undefined, {forwardDate: true});
109+
// If reparsed successfully, update knownValues with year/month/day
110+
if (reparsed && reparsed[0] && reparsed[0].start && reparsed[0].start.knownValues) {
111+
Object.assign(chronoDate.start.knownValues, reparsed[0].start.knownValues);
112+
}
113+
}
114+
});
115+
}
69116
// ignore "今日" text
70117
// ignore not valid data
71118
const filteredChronoDates = chronoDates.filter(textIncludesNumber).filter(yearMonthDayShouldKnownValues);

test/textlint-rule-date-weekday-mismatch-test.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@ tester.run("rule", rule, {
1818
// invalid date should be ignored
1919
"11月 25日 (火曜日) ",
2020
// ignore relative word
21-
"今日(火曜日)はどうしよう"
21+
"今日(火曜日)はどうしよう",
22+
// useCurrentYearIfMissing option: valid
23+
{
24+
text: "4月23日(水)",
25+
options: { useCurrentYearIfMissing: true, lang: "ja" },
26+
// 2025年4月23日は水曜日
27+
},
28+
{
29+
text: "4/23(Wed)",
30+
options: { useCurrentYearIfMissing: true, lang: "en" },
31+
// 2025-04-23 is Wednesday
32+
},
2233
],
2334
invalid: [
2435
// single match
@@ -122,6 +133,30 @@ tester.run("rule", rule, {
122133
}
123134
]
124135
},
125-
136+
// useCurrentYearIfMissing option: invalid
137+
{
138+
text: "4月23日(金)",
139+
output: "4月23日(水)",
140+
options: { useCurrentYearIfMissing: true, lang: "ja" },
141+
errors: [
142+
{
143+
message: "4月23日(金) mismatch weekday.\n4月23日(金) => 4月23日(水)",
144+
line: 1,
145+
column: 7
146+
}
147+
]
148+
},
149+
{
150+
text: "4/23(Fri)",
151+
output: "4/23(Wed)",
152+
options: { useCurrentYearIfMissing: true, lang: "en" },
153+
errors: [
154+
{
155+
message: "4/23(Fri) mismatch weekday.\n4/23(Fri) => 4/23(Wed)",
156+
line: 1,
157+
column: 6
158+
}
159+
]
160+
},
126161
]
127162
});

0 commit comments

Comments
 (0)