@savvy-web/changesets 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/cjs/changelog.cjs +131 -36
- package/cjs/changelog.d.cts +52 -3
- package/cjs/index.cjs +262 -42
- package/cjs/index.d.cts +1726 -175
- package/cjs/markdownlint.cjs +156 -2
- package/cjs/markdownlint.d.cts +127 -21
- package/cjs/remark.cjs +225 -9
- package/cjs/remark.d.cts +106 -37
- package/esm/160.js +45 -39
- package/esm/260.js +2 -1
- package/esm/273.js +2 -1
- package/esm/622.js +2 -2
- package/esm/{795.js → 725.js} +2 -5
- package/esm/855.js +5 -0
- package/esm/891.js +147 -0
- package/esm/bin/savvy-changesets.js +5 -3
- package/esm/changelog.d.ts +52 -3
- package/esm/index.d.ts +1726 -175
- package/esm/index.js +27 -5
- package/esm/markdownlint.d.ts +127 -21
- package/esm/markdownlint.js +152 -2
- package/esm/remark.d.ts +106 -37
- package/esm/remark.js +76 -3
- package/package.json +1 -1
- package/esm/689.js +0 -1
package/cjs/markdownlint.cjs
CHANGED
|
@@ -28,6 +28,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28
28
|
HeadingHierarchyRule: ()=>HeadingHierarchyRule,
|
|
29
29
|
UncategorizedContentRule: ()=>UncategorizedContentRule,
|
|
30
30
|
default: ()=>markdownlint,
|
|
31
|
+
DependencyTableFormatRule: ()=>DependencyTableFormatRule,
|
|
31
32
|
RequiredSectionsRule: ()=>RequiredSectionsRule
|
|
32
33
|
});
|
|
33
34
|
const DOCS_BASE = "https://github.com/savvy-web/changesets/blob/main/docs/rules";
|
|
@@ -35,7 +36,8 @@ const RULE_DOCS = {
|
|
|
35
36
|
CSH001: `${DOCS_BASE}/CSH001.md`,
|
|
36
37
|
CSH002: `${DOCS_BASE}/CSH002.md`,
|
|
37
38
|
CSH003: `${DOCS_BASE}/CSH003.md`,
|
|
38
|
-
CSH004: `${DOCS_BASE}/CSH004.md
|
|
39
|
+
CSH004: `${DOCS_BASE}/CSH004.md`,
|
|
40
|
+
CSH005: `${DOCS_BASE}/CSH005.md`
|
|
39
41
|
};
|
|
40
42
|
function getHeadingLevel(heading) {
|
|
41
43
|
const sequence = heading.children.find((c)=>"atxHeadingSequence" === c.type);
|
|
@@ -104,6 +106,155 @@ const ContentStructureRule = {
|
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
};
|
|
109
|
+
const EM_DASH = "\u2014";
|
|
110
|
+
const VALID_TYPES = new Set([
|
|
111
|
+
"dependency",
|
|
112
|
+
"devDependency",
|
|
113
|
+
"peerDependency",
|
|
114
|
+
"optionalDependency",
|
|
115
|
+
"workspace",
|
|
116
|
+
"config"
|
|
117
|
+
]);
|
|
118
|
+
const VALID_ACTIONS = new Set([
|
|
119
|
+
"added",
|
|
120
|
+
"updated",
|
|
121
|
+
"removed"
|
|
122
|
+
]);
|
|
123
|
+
const EXPECTED_HEADERS = [
|
|
124
|
+
"dependency",
|
|
125
|
+
"type",
|
|
126
|
+
"action",
|
|
127
|
+
"from",
|
|
128
|
+
"to"
|
|
129
|
+
];
|
|
130
|
+
const VERSION_RE = /^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]*)?)$/;
|
|
131
|
+
function getCellText(cell) {
|
|
132
|
+
const content = cell.children.find((c)=>"tableContent" === c.type);
|
|
133
|
+
return content ? content.text.trim() : "";
|
|
134
|
+
}
|
|
135
|
+
function getRowCells(row) {
|
|
136
|
+
return row.children.filter((c)=>"tableHeader" === c.type || "tableData" === c.type).map(getCellText);
|
|
137
|
+
}
|
|
138
|
+
const DependencyTableFormatRule = {
|
|
139
|
+
names: [
|
|
140
|
+
"changeset-dependency-table-format",
|
|
141
|
+
"CSH005"
|
|
142
|
+
],
|
|
143
|
+
description: "Dependencies section must contain a valid dependency table",
|
|
144
|
+
tags: [
|
|
145
|
+
"changeset"
|
|
146
|
+
],
|
|
147
|
+
parser: "micromark",
|
|
148
|
+
function: function(params, onError) {
|
|
149
|
+
const tokens = params.parsers.micromark.tokens;
|
|
150
|
+
for(let i = 0; i < tokens.length; i++){
|
|
151
|
+
const token = tokens[i];
|
|
152
|
+
if ("atxHeading" !== token.type) continue;
|
|
153
|
+
if (2 !== getHeadingLevel(token)) continue;
|
|
154
|
+
if ("dependencies" !== getHeadingText(token).toLowerCase()) continue;
|
|
155
|
+
const headingLine = token.startLine;
|
|
156
|
+
let tableToken = null;
|
|
157
|
+
for(let j = i + 1; j < tokens.length; j++){
|
|
158
|
+
const next = tokens[j];
|
|
159
|
+
if ("lineEnding" !== next.type && "lineEndingBlank" !== next.type) {
|
|
160
|
+
if ("atxHeading" === next.type) break;
|
|
161
|
+
if ("table" === next.type) tableToken = next;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (null === tableToken) {
|
|
166
|
+
onError({
|
|
167
|
+
lineNumber: headingLine,
|
|
168
|
+
detail: `Dependencies section must contain a table, not a list or paragraph. See: ${RULE_DOCS.CSH005}`
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const tableHead = tableToken.children.find((c)=>"tableHead" === c.type);
|
|
173
|
+
if (!tableHead) {
|
|
174
|
+
onError({
|
|
175
|
+
lineNumber: tableToken.startLine,
|
|
176
|
+
detail: `Dependencies table is missing a header row. See: ${RULE_DOCS.CSH005}`
|
|
177
|
+
});
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const headerRow = tableHead.children.find((c)=>"tableRow" === c.type);
|
|
181
|
+
if (!headerRow) {
|
|
182
|
+
onError({
|
|
183
|
+
lineNumber: tableToken.startLine,
|
|
184
|
+
detail: `Dependencies table is missing a header row. See: ${RULE_DOCS.CSH005}`
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const headers = getRowCells(headerRow).map((h)=>h.toLowerCase());
|
|
189
|
+
if (headers.length !== EXPECTED_HEADERS.length || !headers.every((h, idx)=>h === EXPECTED_HEADERS[idx])) {
|
|
190
|
+
onError({
|
|
191
|
+
lineNumber: headerRow.startLine,
|
|
192
|
+
detail: `Dependencies table must have columns: Dependency, Type, Action, From, To. Got: ${headers.join(", ")}. See: ${RULE_DOCS.CSH005}`
|
|
193
|
+
});
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const tableBody = tableToken.children.find((c)=>"tableBody" === c.type);
|
|
197
|
+
if (!tableBody) {
|
|
198
|
+
onError({
|
|
199
|
+
lineNumber: tableToken.startLine,
|
|
200
|
+
detail: `Dependencies table must have at least one data row. See: ${RULE_DOCS.CSH005}`
|
|
201
|
+
});
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const dataRows = tableBody.children.filter((c)=>"tableRow" === c.type);
|
|
205
|
+
if (0 === dataRows.length) {
|
|
206
|
+
onError({
|
|
207
|
+
lineNumber: tableToken.startLine,
|
|
208
|
+
detail: `Dependencies table must have at least one data row. See: ${RULE_DOCS.CSH005}`
|
|
209
|
+
});
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
for (const row of dataRows){
|
|
213
|
+
const cells = getRowCells(row);
|
|
214
|
+
if (cells.length < 5) {
|
|
215
|
+
onError({
|
|
216
|
+
lineNumber: row.startLine,
|
|
217
|
+
detail: `Dependencies table row has too few columns (expected 5, got ${cells.length}). See: ${RULE_DOCS.CSH005}`
|
|
218
|
+
});
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const [dependency, type, action, from, to] = cells;
|
|
222
|
+
if (!dependency) onError({
|
|
223
|
+
lineNumber: row.startLine,
|
|
224
|
+
detail: `Dependencies table row has an empty 'Dependency' cell. See: ${RULE_DOCS.CSH005}`
|
|
225
|
+
});
|
|
226
|
+
if (!VALID_TYPES.has(type)) onError({
|
|
227
|
+
lineNumber: row.startLine,
|
|
228
|
+
detail: `Invalid dependency type '${type}'. Valid types are: ${[
|
|
229
|
+
...VALID_TYPES
|
|
230
|
+
].join(", ")}. See: ${RULE_DOCS.CSH005}`
|
|
231
|
+
});
|
|
232
|
+
if (!VALID_ACTIONS.has(action)) onError({
|
|
233
|
+
lineNumber: row.startLine,
|
|
234
|
+
detail: `Invalid dependency action '${action}'. Valid actions are: ${[
|
|
235
|
+
...VALID_ACTIONS
|
|
236
|
+
].join(", ")}. See: ${RULE_DOCS.CSH005}`
|
|
237
|
+
});
|
|
238
|
+
if (from && !VERSION_RE.test(from)) onError({
|
|
239
|
+
lineNumber: row.startLine,
|
|
240
|
+
detail: `Invalid 'from' value '${from}'. Must be a semver string or em dash (\u2014). See: ${RULE_DOCS.CSH005}`
|
|
241
|
+
});
|
|
242
|
+
if (to && !VERSION_RE.test(to)) onError({
|
|
243
|
+
lineNumber: row.startLine,
|
|
244
|
+
detail: `Invalid 'to' value '${to}'. Must be a semver string or em dash (\u2014). See: ${RULE_DOCS.CSH005}`
|
|
245
|
+
});
|
|
246
|
+
if ("added" === action && from !== EM_DASH) onError({
|
|
247
|
+
lineNumber: row.startLine,
|
|
248
|
+
detail: `'from' must be '\u2014' when action is 'added' (got '${from}'). See: ${RULE_DOCS.CSH005}`
|
|
249
|
+
});
|
|
250
|
+
if ("removed" === action && to !== EM_DASH) onError({
|
|
251
|
+
lineNumber: row.startLine,
|
|
252
|
+
detail: `'to' must be '\u2014' when action is 'removed' (got '${to}'). See: ${RULE_DOCS.CSH005}`
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
};
|
|
107
258
|
const HeadingHierarchyRule = {
|
|
108
259
|
names: [
|
|
109
260
|
"changeset-heading-hierarchy",
|
|
@@ -311,16 +462,19 @@ const SilkChangesetsRules = [
|
|
|
311
462
|
HeadingHierarchyRule,
|
|
312
463
|
RequiredSectionsRule,
|
|
313
464
|
ContentStructureRule,
|
|
314
|
-
UncategorizedContentRule
|
|
465
|
+
UncategorizedContentRule,
|
|
466
|
+
DependencyTableFormatRule
|
|
315
467
|
];
|
|
316
468
|
const markdownlint = SilkChangesetsRules;
|
|
317
469
|
exports.ContentStructureRule = __webpack_exports__.ContentStructureRule;
|
|
470
|
+
exports.DependencyTableFormatRule = __webpack_exports__.DependencyTableFormatRule;
|
|
318
471
|
exports.HeadingHierarchyRule = __webpack_exports__.HeadingHierarchyRule;
|
|
319
472
|
exports.RequiredSectionsRule = __webpack_exports__.RequiredSectionsRule;
|
|
320
473
|
exports.UncategorizedContentRule = __webpack_exports__.UncategorizedContentRule;
|
|
321
474
|
exports["default"] = __webpack_exports__["default"];
|
|
322
475
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
323
476
|
"ContentStructureRule",
|
|
477
|
+
"DependencyTableFormatRule",
|
|
324
478
|
"HeadingHierarchyRule",
|
|
325
479
|
"RequiredSectionsRule",
|
|
326
480
|
"UncategorizedContentRule",
|
package/cjs/markdownlint.d.cts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* \@savvy-web/changesets/markdownlint
|
|
3
|
+
*
|
|
2
4
|
* markdownlint custom rules for validating changeset file structure.
|
|
3
5
|
*
|
|
4
6
|
* Provides the same validation as the remark-lint rules but using
|
|
5
7
|
* markdownlint's micromark token API for integration with
|
|
6
8
|
* markdownlint-cli2 and the VS Code markdownlint extension.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
10
|
+
* Rules included:
|
|
11
|
+
* - {@link HeadingHierarchyRule | changeset-heading-hierarchy} (CSH001): Enforce h2 start, no h1, no depth skips
|
|
12
|
+
* - {@link RequiredSectionsRule | changeset-required-sections} (CSH002): Validate section headings match known categories
|
|
13
|
+
* - {@link ContentStructureRule | changeset-content-structure} (CSH003): Content quality validation
|
|
14
|
+
* - {@link UncategorizedContentRule | changeset-uncategorized-content} (CSH004): Reject content before first h2 heading
|
|
15
|
+
* - {@link DependencyTableFormatRule | changeset-dependency-table-format} (CSH005): Validate dependency table structure
|
|
16
|
+
*
|
|
17
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH001.md | CSH001 docs}
|
|
18
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH002.md | CSH002 docs}
|
|
19
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH003.md | CSH003 docs}
|
|
20
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH004.md | CSH004 docs}
|
|
21
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH005.md | CSH005 docs}
|
|
12
22
|
*
|
|
13
23
|
* @packageDocumentation
|
|
14
24
|
*/
|
|
@@ -16,31 +26,103 @@
|
|
|
16
26
|
import type { Rule } from 'markdownlint';
|
|
17
27
|
|
|
18
28
|
/**
|
|
19
|
-
* markdownlint rule: changeset-content-structure (CSH003)
|
|
29
|
+
* markdownlint rule: `changeset-content-structure` (CSH003).
|
|
30
|
+
*
|
|
31
|
+
* Validates content quality inside changeset markdown files by inspecting
|
|
32
|
+
* micromark tokens for three categories of structural problems:
|
|
33
|
+
*
|
|
34
|
+
* 1. **Empty sections** -- an `atxHeading` (h2) followed immediately by another
|
|
35
|
+
* h2 or the end of the token stream with no intervening content tokens.
|
|
36
|
+
* 2. **Code blocks without a language identifier** -- a `codeFenced` token whose
|
|
37
|
+
* opening fence child lacks a `codeFencedFenceInfo` token.
|
|
38
|
+
* 3. **Empty list items** -- a `listItemPrefix` token with no subsequent
|
|
39
|
+
* `content` token before the next prefix or end of list.
|
|
20
40
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* This rule mirrors the remark-lint rule `remarkLintContentStructure` but uses
|
|
43
|
+
* markdownlint's micromark token API so it can run inside markdownlint-cli2 and
|
|
44
|
+
* the VS Code markdownlint extension.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```json
|
|
48
|
+
* {
|
|
49
|
+
* "changeset-content-structure": true
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH003.md | CSH003 rule documentation}
|
|
54
|
+
* @see `src/remark/rules/content-structure.ts` for the corresponding remark-lint rule
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
25
57
|
*/
|
|
26
58
|
export declare const ContentStructureRule: Rule;
|
|
27
59
|
|
|
28
60
|
/**
|
|
29
|
-
* markdownlint
|
|
61
|
+
* The markdownlint `Rule` object for CSH005 (`changeset-dependency-table-format`).
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export declare const DependencyTableFormatRule: Rule;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* markdownlint rule: `changeset-heading-hierarchy` (CSH001).
|
|
69
|
+
*
|
|
70
|
+
* Validates heading structure in changeset markdown files by inspecting
|
|
71
|
+
* `atxHeading` micromark tokens for three constraints:
|
|
72
|
+
*
|
|
73
|
+
* 1. **No h1 headings** -- h1 is reserved for the version title generated by
|
|
74
|
+
* the changelog formatter.
|
|
75
|
+
* 2. **Start at h2** -- the first heading in a changeset must be h2.
|
|
76
|
+
* 3. **No depth skips** -- heading levels must increase sequentially
|
|
77
|
+
* (h2 then h3, not h2 then h4).
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* This rule mirrors the remark-lint rule `remarkLintHeadingHierarchy` but uses
|
|
81
|
+
* markdownlint's micromark token API so it can run inside markdownlint-cli2 and
|
|
82
|
+
* the VS Code markdownlint extension.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```json
|
|
86
|
+
* {
|
|
87
|
+
* "changeset-heading-hierarchy": true
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH001.md | CSH001 rule documentation}
|
|
92
|
+
* @see `src/remark/rules/heading-hierarchy.ts` for the corresponding remark-lint rule
|
|
30
93
|
*
|
|
31
|
-
*
|
|
32
|
-
* - No h1 headings allowed
|
|
33
|
-
* - Headings must start at h2
|
|
34
|
-
* - No depth skips (e.g., h2 ... h4 is invalid)
|
|
94
|
+
* @public
|
|
35
95
|
*/
|
|
36
96
|
export declare const HeadingHierarchyRule: Rule;
|
|
37
97
|
|
|
38
98
|
/**
|
|
39
|
-
* markdownlint rule: changeset-required-sections (CSH002)
|
|
99
|
+
* markdownlint rule: `changeset-required-sections` (CSH002).
|
|
100
|
+
*
|
|
101
|
+
* Validates that every h2 (`atxHeading` with depth 2) in a changeset markdown
|
|
102
|
+
* file matches a known category heading from the category system. When an
|
|
103
|
+
* unrecognized heading is found, the error detail lists all valid headings.
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* Heading comparison is case-insensitive. The set of valid headings is provided
|
|
107
|
+
* by `allHeadings()` and `isValidHeading()` from the category system
|
|
108
|
+
* (`src/categories/index.ts`). This rule inspects `atxHeading` micromark
|
|
109
|
+
* tokens and extracts their text via the {@link getHeadingText} utility.
|
|
110
|
+
*
|
|
111
|
+
* This rule mirrors the remark-lint rule `remarkLintRequiredSections` but uses
|
|
112
|
+
* markdownlint's micromark token API so it can run inside markdownlint-cli2 and
|
|
113
|
+
* the VS Code markdownlint extension.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```json
|
|
117
|
+
* {
|
|
118
|
+
* "changeset-required-sections": true
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH002.md | CSH002 rule documentation}
|
|
123
|
+
* @see `src/remark/rules/required-sections.ts` for the corresponding remark-lint rule
|
|
40
124
|
*
|
|
41
|
-
*
|
|
42
|
-
* category heading from the category system. Reports unrecognized
|
|
43
|
-
* headings with the list of valid options.
|
|
125
|
+
* @public
|
|
44
126
|
*/
|
|
45
127
|
export declare const RequiredSectionsRule: Rule;
|
|
46
128
|
|
|
@@ -60,10 +142,34 @@ declare const SilkChangesetsRules: Rule[];
|
|
|
60
142
|
export default SilkChangesetsRules;
|
|
61
143
|
|
|
62
144
|
/**
|
|
63
|
-
* markdownlint rule: changeset-uncategorized-content (CSH004)
|
|
145
|
+
* markdownlint rule: `changeset-uncategorized-content` (CSH004).
|
|
146
|
+
*
|
|
147
|
+
* Detects content that appears before the first h2 heading in a changeset
|
|
148
|
+
* markdown file. All substantive content must be placed under a categorized
|
|
149
|
+
* section (`## heading`).
|
|
64
150
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
151
|
+
* @remarks
|
|
152
|
+
* The rule iterates over the top-level micromark token stream and stops at the
|
|
153
|
+
* first `atxHeading` with depth 2. Any token encountered before that heading
|
|
154
|
+
* that is not a `lineEnding`, `lineEndingBlank`, or `htmlFlow` (HTML comments)
|
|
155
|
+
* triggers an error. This ensures that changeset content is always grouped
|
|
156
|
+
* under a recognized category heading.
|
|
157
|
+
*
|
|
158
|
+
* This rule mirrors the remark-lint rule `remarkLintUncategorizedContent` but
|
|
159
|
+
* uses markdownlint's micromark token API so it can run inside
|
|
160
|
+
* markdownlint-cli2 and the VS Code markdownlint extension.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```json
|
|
164
|
+
* {
|
|
165
|
+
* "changeset-uncategorized-content": true
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @see {@link https://github.com/savvy-web/changesets/blob/main/docs/rules/CSH004.md | CSH004 rule documentation}
|
|
170
|
+
* @see `src/remark/rules/uncategorized-content.ts` for the corresponding remark-lint rule
|
|
171
|
+
*
|
|
172
|
+
* @public
|
|
67
173
|
*/
|
|
68
174
|
export declare const UncategorizedContentRule: Rule;
|
|
69
175
|
|
package/cjs/remark.cjs
CHANGED
|
@@ -24,21 +24,161 @@ var __webpack_require__ = {};
|
|
|
24
24
|
var __webpack_exports__ = {};
|
|
25
25
|
__webpack_require__.r(__webpack_exports__);
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
RequiredSectionsRule: ()=>RequiredSectionsRule,
|
|
28
|
+
SilkChangesetPreset: ()=>SilkChangesetPreset,
|
|
27
29
|
UncategorizedContentRule: ()=>UncategorizedContentRule,
|
|
28
30
|
SilkChangesetTransformPreset: ()=>SilkChangesetTransformPreset,
|
|
29
|
-
|
|
31
|
+
DependencyTableFormatRule: ()=>DependencyTableFormatRule,
|
|
30
32
|
IssueLinkRefsPlugin: ()=>IssueLinkRefsPlugin,
|
|
31
|
-
|
|
33
|
+
DeduplicateItemsPlugin: ()=>DeduplicateItemsPlugin,
|
|
32
34
|
ContentStructureRule: ()=>ContentStructureRule,
|
|
33
35
|
HeadingHierarchyRule: ()=>HeadingHierarchyRule,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
AggregateDependencyTablesPlugin: ()=>AggregateDependencyTablesPlugin,
|
|
37
|
+
MergeSectionsPlugin: ()=>MergeSectionsPlugin,
|
|
36
38
|
ContributorFootnotesPlugin: ()=>ContributorFootnotesPlugin,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
NormalizeFormatPlugin: ()=>NormalizeFormatPlugin,
|
|
40
|
+
ReorderSectionsPlugin: ()=>ReorderSectionsPlugin
|
|
39
41
|
});
|
|
40
|
-
const
|
|
42
|
+
const external_effect_namespaceObject = require("effect");
|
|
41
43
|
const external_mdast_util_to_string_namespaceObject = require("mdast-util-to-string");
|
|
44
|
+
require("remark-gfm");
|
|
45
|
+
require("remark-stringify");
|
|
46
|
+
require("unified");
|
|
47
|
+
const NonEmptyString = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.minLength(1));
|
|
48
|
+
external_effect_namespaceObject.Schema.Number.pipe(external_effect_namespaceObject.Schema.int(), external_effect_namespaceObject.Schema.positive());
|
|
49
|
+
const DependencyActionSchema = external_effect_namespaceObject.Schema.Literal("added", "updated", "removed");
|
|
50
|
+
const DependencyTableTypeSchema = external_effect_namespaceObject.Schema.Literal("dependency", "devDependency", "peerDependency", "optionalDependency", "workspace", "config");
|
|
51
|
+
const VersionOrEmptySchema = external_effect_namespaceObject.Schema.String.pipe(external_effect_namespaceObject.Schema.pattern(/^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]*)?)$/));
|
|
52
|
+
const DependencyTableRowSchema = external_effect_namespaceObject.Schema.Struct({
|
|
53
|
+
dependency: NonEmptyString,
|
|
54
|
+
type: DependencyTableTypeSchema,
|
|
55
|
+
action: DependencyActionSchema,
|
|
56
|
+
from: VersionOrEmptySchema,
|
|
57
|
+
to: VersionOrEmptySchema
|
|
58
|
+
});
|
|
59
|
+
external_effect_namespaceObject.Schema.Array(DependencyTableRowSchema).pipe(external_effect_namespaceObject.Schema.minItems(1));
|
|
60
|
+
const COLUMN_HEADERS = [
|
|
61
|
+
"Dependency",
|
|
62
|
+
"Type",
|
|
63
|
+
"Action",
|
|
64
|
+
"From",
|
|
65
|
+
"To"
|
|
66
|
+
];
|
|
67
|
+
const COLUMN_KEYS = [
|
|
68
|
+
"dependency",
|
|
69
|
+
"type",
|
|
70
|
+
"action",
|
|
71
|
+
"from",
|
|
72
|
+
"to"
|
|
73
|
+
];
|
|
74
|
+
const decode = external_effect_namespaceObject.Schema.decodeUnknownSync(DependencyTableRowSchema);
|
|
75
|
+
function parseDependencyTable(table) {
|
|
76
|
+
const rows = table.children;
|
|
77
|
+
if (rows.length < 2) throw new Error("Dependency table must have at least one data row");
|
|
78
|
+
const headerRow = rows[0];
|
|
79
|
+
const headers = headerRow.children.map((cell)=>(0, external_mdast_util_to_string_namespaceObject.toString)(cell).trim().toLowerCase());
|
|
80
|
+
const expected = COLUMN_HEADERS.map((h)=>h.toLowerCase());
|
|
81
|
+
if (headers.length !== expected.length || !headers.every((h, i)=>h === expected[i])) throw new Error(`Table must have columns: ${COLUMN_HEADERS.join(", ")}. Got: ${headers.join(", ")}`);
|
|
82
|
+
const result = [];
|
|
83
|
+
for(let i = 1; i < rows.length; i++){
|
|
84
|
+
const cells = rows[i].children;
|
|
85
|
+
const raw = {};
|
|
86
|
+
for(let c = 0; c < COLUMN_KEYS.length; c++)raw[COLUMN_KEYS[c]] = (0, external_mdast_util_to_string_namespaceObject.toString)(cells[c]).trim();
|
|
87
|
+
result.push(decode(raw));
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
function makeCell(text) {
|
|
92
|
+
return {
|
|
93
|
+
type: "tableCell",
|
|
94
|
+
children: [
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
value: text
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function makeRow(texts) {
|
|
103
|
+
return {
|
|
104
|
+
type: "tableRow",
|
|
105
|
+
children: texts.map(makeCell)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function serializeDependencyTable(rows) {
|
|
109
|
+
const headerRow = makeRow([
|
|
110
|
+
...COLUMN_HEADERS
|
|
111
|
+
]);
|
|
112
|
+
const dataRows = rows.map((row)=>makeRow(COLUMN_KEYS.map((key)=>row[key])));
|
|
113
|
+
return {
|
|
114
|
+
type: "table",
|
|
115
|
+
children: [
|
|
116
|
+
headerRow,
|
|
117
|
+
...dataRows
|
|
118
|
+
]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const ACTION_ORDER = {
|
|
122
|
+
removed: 0,
|
|
123
|
+
updated: 1,
|
|
124
|
+
added: 2
|
|
125
|
+
};
|
|
126
|
+
function collapseDependencyRows(rows) {
|
|
127
|
+
const groups = new Map();
|
|
128
|
+
for (const row of rows){
|
|
129
|
+
const key = `${row.dependency}\0${row.type}`;
|
|
130
|
+
const existing = groups.get(key);
|
|
131
|
+
if (!existing) {
|
|
132
|
+
groups.set(key, {
|
|
133
|
+
...row
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const merged = collapseTwo(existing, row);
|
|
138
|
+
if (null === merged) groups.delete(key);
|
|
139
|
+
else groups.set(key, merged);
|
|
140
|
+
}
|
|
141
|
+
return [
|
|
142
|
+
...groups.values()
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
function collapseTwo(first, second) {
|
|
146
|
+
const a = first.action;
|
|
147
|
+
const b = second.action;
|
|
148
|
+
if ("updated" === a && "updated" === b) return {
|
|
149
|
+
...first,
|
|
150
|
+
to: second.to
|
|
151
|
+
};
|
|
152
|
+
if ("added" === a && "updated" === b) return {
|
|
153
|
+
...first,
|
|
154
|
+
to: second.to
|
|
155
|
+
};
|
|
156
|
+
if ("added" === a && "removed" === b) return null;
|
|
157
|
+
if ("updated" === a && "removed" === b) return {
|
|
158
|
+
...first,
|
|
159
|
+
action: "removed",
|
|
160
|
+
to: "\u2014"
|
|
161
|
+
};
|
|
162
|
+
if ("removed" === a && "added" === b) return {
|
|
163
|
+
...first,
|
|
164
|
+
action: "updated",
|
|
165
|
+
to: second.to
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
...second
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function sortDependencyRows(rows) {
|
|
172
|
+
return [
|
|
173
|
+
...rows
|
|
174
|
+
].sort((a, b)=>{
|
|
175
|
+
const actionDiff = (ACTION_ORDER[a.action] ?? 99) - (ACTION_ORDER[b.action] ?? 99);
|
|
176
|
+
if (0 !== actionDiff) return actionDiff;
|
|
177
|
+
const typeDiff = a.type.localeCompare(b.type);
|
|
178
|
+
if (0 !== typeDiff) return typeDiff;
|
|
179
|
+
return a.dependency.localeCompare(b.dependency);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
42
182
|
function getVersionBlocks(tree) {
|
|
43
183
|
const blocks = [];
|
|
44
184
|
for(let i = 0; i < tree.children.length; i++){
|
|
@@ -68,6 +208,49 @@ function getBlockSections(tree, block) {
|
|
|
68
208
|
function getHeadingText(heading) {
|
|
69
209
|
return (0, external_mdast_util_to_string_namespaceObject.toString)(heading);
|
|
70
210
|
}
|
|
211
|
+
const AggregateDependencyTablesPlugin = ()=>(tree)=>{
|
|
212
|
+
const blocks = getVersionBlocks(tree);
|
|
213
|
+
for(let b = blocks.length - 1; b >= 0; b--){
|
|
214
|
+
const sections = getBlockSections(tree, blocks[b]);
|
|
215
|
+
const depSections = sections.filter((s)=>"dependencies" === getHeadingText(s.heading).toLowerCase());
|
|
216
|
+
if (0 === depSections.length) continue;
|
|
217
|
+
const allRows = [];
|
|
218
|
+
const legacyContent = [];
|
|
219
|
+
for (const section of depSections)for (const node of section.contentNodes)if ("table" === node.type) try {
|
|
220
|
+
const rows = parseDependencyTable(node);
|
|
221
|
+
allRows.push(...rows);
|
|
222
|
+
} catch {
|
|
223
|
+
legacyContent.push(node);
|
|
224
|
+
}
|
|
225
|
+
else legacyContent.push(node);
|
|
226
|
+
const collapsed = sortDependencyRows(collapseDependencyRows(allRows));
|
|
227
|
+
const indicesToRemove = [];
|
|
228
|
+
for (const section of depSections){
|
|
229
|
+
indicesToRemove.push(section.headingIndex);
|
|
230
|
+
for(let c = 0; c < section.contentNodes.length; c++)indicesToRemove.push(section.headingIndex + 1 + c);
|
|
231
|
+
}
|
|
232
|
+
indicesToRemove.sort((a, b)=>b - a);
|
|
233
|
+
for (const idx of indicesToRemove)tree.children.splice(idx, 1);
|
|
234
|
+
if (0 === collapsed.length && 0 === legacyContent.length) continue;
|
|
235
|
+
const insertAt = depSections[0].headingIndex;
|
|
236
|
+
const newNodes = [];
|
|
237
|
+
const heading = {
|
|
238
|
+
type: "heading",
|
|
239
|
+
depth: 3,
|
|
240
|
+
children: [
|
|
241
|
+
{
|
|
242
|
+
type: "text",
|
|
243
|
+
value: "Dependencies"
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
};
|
|
247
|
+
newNodes.push(heading);
|
|
248
|
+
if (collapsed.length > 0) newNodes.push(serializeDependencyTable(collapsed));
|
|
249
|
+
newNodes.push(...legacyContent);
|
|
250
|
+
tree.children.splice(insertAt, 0, ...newNodes);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
const external_unist_util_visit_namespaceObject = require("unist-util-visit");
|
|
71
254
|
const ATTRIBUTION_PLAIN_RE = /\s*Thanks @(\w[\w-]*)!$/;
|
|
72
255
|
function extractLinkedAttribution(children) {
|
|
73
256
|
if (children.length < 3) return;
|
|
@@ -479,7 +662,8 @@ const RULE_DOCS = {
|
|
|
479
662
|
CSH001: `${DOCS_BASE}/CSH001.md`,
|
|
480
663
|
CSH002: `${DOCS_BASE}/CSH002.md`,
|
|
481
664
|
CSH003: `${DOCS_BASE}/CSH003.md`,
|
|
482
|
-
CSH004: `${DOCS_BASE}/CSH004.md
|
|
665
|
+
CSH004: `${DOCS_BASE}/CSH004.md`,
|
|
666
|
+
CSH005: `${DOCS_BASE}/CSH005.md`
|
|
483
667
|
};
|
|
484
668
|
const ContentStructureRule = (0, external_unified_lint_rule_namespaceObject.lintRule)("remark-lint:changeset-content-structure", (tree, file)=>{
|
|
485
669
|
(0, external_unist_util_visit_namespaceObject.visit)(tree, "heading", (node, index, parent)=>{
|
|
@@ -495,6 +679,32 @@ const ContentStructureRule = (0, external_unified_lint_rule_namespaceObject.lint
|
|
|
495
679
|
if (!text) file.message(`Empty list item. Each list item must contain descriptive text (e.g., "- Fixed login timeout issue"). See: ${RULE_DOCS.CSH003}`, node);
|
|
496
680
|
});
|
|
497
681
|
});
|
|
682
|
+
const EM_DASH = "\u2014";
|
|
683
|
+
const DependencyTableFormatRule = (0, external_unified_lint_rule_namespaceObject.lintRule)("remark-lint:changeset-dependency-table-format", (tree, file)=>{
|
|
684
|
+
(0, external_unist_util_visit_namespaceObject.visit)(tree, "heading", (node, index)=>{
|
|
685
|
+
if (2 !== node.depth) return;
|
|
686
|
+
if ("dependencies" !== (0, external_mdast_util_to_string_namespaceObject.toString)(node).toLowerCase()) return;
|
|
687
|
+
if (void 0 === index) return;
|
|
688
|
+
const content = [];
|
|
689
|
+
for(let i = index + 1; i < tree.children.length; i++){
|
|
690
|
+
const child = tree.children[i];
|
|
691
|
+
if ("heading" === child.type) break;
|
|
692
|
+
content.push(child);
|
|
693
|
+
}
|
|
694
|
+
const tables = content.filter((n)=>"table" === n.type);
|
|
695
|
+
if (0 === tables.length) return void file.message(`Dependencies section must contain a table, not a list or paragraph. See: ${RULE_DOCS.CSH005}`, node);
|
|
696
|
+
const table = tables[0];
|
|
697
|
+
try {
|
|
698
|
+
const rows = parseDependencyTable(table);
|
|
699
|
+
for (const row of rows){
|
|
700
|
+
if ("added" === row.action && row.from !== EM_DASH) file.message(`'from' must be '\u2014' when action is 'added' (got '${row.from}'). See: ${RULE_DOCS.CSH005}`, table);
|
|
701
|
+
if ("removed" === row.action && row.to !== EM_DASH) file.message(`'to' must be '\u2014' when action is 'removed' (got '${row.to}'). See: ${RULE_DOCS.CSH005}`, table);
|
|
702
|
+
}
|
|
703
|
+
} catch (error) {
|
|
704
|
+
file.message(`${error instanceof Error ? error.message : String(error)}. See: ${RULE_DOCS.CSH005}`, table);
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
});
|
|
498
708
|
const HeadingHierarchyRule = (0, external_unified_lint_rule_namespaceObject.lintRule)("remark-lint:changeset-heading-hierarchy", (tree, file)=>{
|
|
499
709
|
let prevDepth = 0;
|
|
500
710
|
(0, external_unist_util_visit_namespaceObject.visit)(tree, "heading", (node)=>{
|
|
@@ -527,9 +737,11 @@ const SilkChangesetPreset = [
|
|
|
527
737
|
HeadingHierarchyRule,
|
|
528
738
|
RequiredSectionsRule,
|
|
529
739
|
ContentStructureRule,
|
|
530
|
-
UncategorizedContentRule
|
|
740
|
+
UncategorizedContentRule,
|
|
741
|
+
DependencyTableFormatRule
|
|
531
742
|
];
|
|
532
743
|
const SilkChangesetTransformPreset = [
|
|
744
|
+
AggregateDependencyTablesPlugin,
|
|
533
745
|
MergeSectionsPlugin,
|
|
534
746
|
ReorderSectionsPlugin,
|
|
535
747
|
DeduplicateItemsPlugin,
|
|
@@ -537,9 +749,11 @@ const SilkChangesetTransformPreset = [
|
|
|
537
749
|
IssueLinkRefsPlugin,
|
|
538
750
|
NormalizeFormatPlugin
|
|
539
751
|
];
|
|
752
|
+
exports.AggregateDependencyTablesPlugin = __webpack_exports__.AggregateDependencyTablesPlugin;
|
|
540
753
|
exports.ContentStructureRule = __webpack_exports__.ContentStructureRule;
|
|
541
754
|
exports.ContributorFootnotesPlugin = __webpack_exports__.ContributorFootnotesPlugin;
|
|
542
755
|
exports.DeduplicateItemsPlugin = __webpack_exports__.DeduplicateItemsPlugin;
|
|
756
|
+
exports.DependencyTableFormatRule = __webpack_exports__.DependencyTableFormatRule;
|
|
543
757
|
exports.HeadingHierarchyRule = __webpack_exports__.HeadingHierarchyRule;
|
|
544
758
|
exports.IssueLinkRefsPlugin = __webpack_exports__.IssueLinkRefsPlugin;
|
|
545
759
|
exports.MergeSectionsPlugin = __webpack_exports__.MergeSectionsPlugin;
|
|
@@ -550,9 +764,11 @@ exports.SilkChangesetPreset = __webpack_exports__.SilkChangesetPreset;
|
|
|
550
764
|
exports.SilkChangesetTransformPreset = __webpack_exports__.SilkChangesetTransformPreset;
|
|
551
765
|
exports.UncategorizedContentRule = __webpack_exports__.UncategorizedContentRule;
|
|
552
766
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
767
|
+
"AggregateDependencyTablesPlugin",
|
|
553
768
|
"ContentStructureRule",
|
|
554
769
|
"ContributorFootnotesPlugin",
|
|
555
770
|
"DeduplicateItemsPlugin",
|
|
771
|
+
"DependencyTableFormatRule",
|
|
556
772
|
"HeadingHierarchyRule",
|
|
557
773
|
"IssueLinkRefsPlugin",
|
|
558
774
|
"MergeSectionsPlugin",
|