@savvy-web/silk-effects 9.6.0 → 10.0.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.
Files changed (51) hide show
  1. package/changesets/api/dependency-table.js +12 -12
  2. package/changesets/api/linter.js +23 -19
  3. package/changesets/api/transformer.js +38 -33
  4. package/changesets/categories/index.js +1 -1
  5. package/changesets/categories/types.js +2 -2
  6. package/changesets/changelog/getDependencyReleaseLine.js +1 -1
  7. package/changesets/changelog/index.js +2 -2
  8. package/changesets/constants.js +1 -1
  9. package/changesets/errors.js +1 -1
  10. package/changesets/index.js +11 -40
  11. package/changesets/markdownlint/rules/content-structure.js +2 -2
  12. package/changesets/markdownlint/rules/heading-hierarchy.js +2 -2
  13. package/changesets/markdownlint/rules/required-sections.js +2 -2
  14. package/changesets/markdownlint/rules/uncategorized-content.js +2 -2
  15. package/changesets/markdownlint/rules/utils.js +6 -6
  16. package/changesets/rules/content-structure.js +44 -0
  17. package/changesets/rules/dependency-table-format.js +54 -0
  18. package/changesets/rules/heading-hierarchy.js +37 -0
  19. package/changesets/rules/required-sections.js +34 -0
  20. package/changesets/rules/types.js +20 -0
  21. package/changesets/rules/uncategorized-content.js +30 -0
  22. package/changesets/schemas/changeset.js +1 -1
  23. package/changesets/transforms/aggregate-dependency-tables.js +96 -0
  24. package/changesets/transforms/contributor-footnotes.js +290 -0
  25. package/changesets/transforms/deduplicate-items.js +47 -0
  26. package/changesets/transforms/issue-link-refs.js +47 -0
  27. package/changesets/transforms/maintenance-note.js +65 -0
  28. package/changesets/transforms/merge-sections.js +56 -0
  29. package/changesets/transforms/normalize-format.js +53 -0
  30. package/changesets/transforms/reorder-sections.js +53 -0
  31. package/changesets/utils/blocks.js +67 -0
  32. package/changesets/utils/dependency-table.js +29 -36
  33. package/changesets/utils/markdown-emit.js +11 -36
  34. package/index.d.ts +54 -1199
  35. package/package.json +10 -17
  36. package/changesets/remark/plugins/aggregate-dependency-tables.js +0 -98
  37. package/changesets/remark/plugins/contributor-footnotes.js +0 -334
  38. package/changesets/remark/plugins/deduplicate-items.js +0 -31
  39. package/changesets/remark/plugins/issue-link-refs.js +0 -57
  40. package/changesets/remark/plugins/maintenance-note.js +0 -74
  41. package/changesets/remark/plugins/merge-sections.js +0 -42
  42. package/changesets/remark/plugins/normalize-format.js +0 -46
  43. package/changesets/remark/plugins/reorder-sections.js +0 -48
  44. package/changesets/remark/presets.js +0 -118
  45. package/changesets/remark/rules/content-structure.js +0 -21
  46. package/changesets/remark/rules/dependency-table-format.js +0 -37
  47. package/changesets/remark/rules/heading-hierarchy.js +0 -18
  48. package/changesets/remark/rules/required-sections.js +0 -16
  49. package/changesets/remark/rules/uncategorized-content.js +0 -30
  50. package/changesets/utils/remark-pipeline.js +0 -35
  51. package/changesets/utils/version-blocks.js +0 -107
@@ -12,10 +12,10 @@ import { collapseDependencyRows, parseDependencyTable, serializeDependencyTable,
12
12
  * @remarks
13
13
  * The typical workflow for processing dependency tables is:
14
14
  *
15
- * 1. **Parse** an mdast `Table` node into typed {@link DependencyTableRow} objects
15
+ * 1. **Parse** an `@effected/markdown` `Table` node into typed {@link DependencyTableRow} objects
16
16
  * 2. **Collapse** duplicate rows (same package updated multiple times) into single entries
17
17
  * 3. **Sort** rows by dependency type, then alphabetically by package name
18
- * 4. **Serialize** back to an mdast `Table` node or directly to a markdown string
18
+ * 4. **Serialize** back to an `@effected/markdown` `Table` node or directly to a markdown string
19
19
  *
20
20
  * The {@link DependencyTable.aggregate} method combines the collapse and sort
21
21
  * steps into a single call, which is the most common usage pattern.
@@ -28,9 +28,9 @@ import { collapseDependencyRows, parseDependencyTable, serializeDependencyTable,
28
28
  * ```typescript
29
29
  * import { DependencyTable } from "\@savvy-web/changesets";
30
30
  * import type { DependencyTableRow } from "\@savvy-web/changesets";
31
- * import type { Table } from "mdast";
31
+ * import type { Table } from "\@effected/markdown";
32
32
  *
33
- * // Given an mdast Table node from a parsed CHANGELOG
33
+ * // Given an \@effected/markdown Table node from a parsed CHANGELOG
34
34
  * declare const tableNode: Table;
35
35
  *
36
36
  * // Parse into typed rows
@@ -39,7 +39,7 @@ import { collapseDependencyRows, parseDependencyTable, serializeDependencyTable,
39
39
  * // Collapse duplicates and sort by type, then name
40
40
  * const aggregated: DependencyTableRow[] = DependencyTable.aggregate(rows);
41
41
  *
42
- * // Serialize back to an mdast Table node for further AST manipulation
42
+ * // Serialize back to an \@effected/markdown Table node for further AST manipulation
43
43
  * const outputNode: Table = DependencyTable.serialize(aggregated);
44
44
  *
45
45
  * // Or serialize directly to a markdown string
@@ -70,7 +70,7 @@ var DependencyTable = class {
70
70
  /* v8 ignore next -- private constructor prevents direct instantiation */
71
71
  constructor() {}
72
72
  /**
73
- * Parse an mdast `Table` node into typed dependency table rows.
73
+ * Parse an `@effected/markdown` `Table` node into typed dependency table rows.
74
74
  *
75
75
  * @remarks
76
76
  * Extracts the text content from each table cell and maps it to the
@@ -78,23 +78,23 @@ var DependencyTable = class {
78
78
  * treated as the header and skipped. Rows that do not have the expected
79
79
  * number of columns are ignored.
80
80
  *
81
- * @param tableNode - An mdast `Table` node from a parsed markdown AST
81
+ * @param tableNode - An `@effected/markdown` `Table` node from a parsed markdown tree
82
82
  * @returns Array of {@link DependencyTableRow} objects, one per data row
83
83
  */
84
84
  static parse(tableNode) {
85
85
  return parseDependencyTable(tableNode);
86
86
  }
87
87
  /**
88
- * Serialize typed dependency table rows into an mdast `Table` node.
88
+ * Serialize typed dependency table rows into an `@effected/markdown` `Table` node.
89
89
  *
90
90
  * @remarks
91
- * Produces a well-formed mdast `Table` with a header row
91
+ * Produces a well-formed `@effected/markdown` `Table` with a header row
92
92
  * (`Dependency | Type | Action | From | To`) followed by one data row
93
- * per input entry. The resulting node can be inserted into a remark AST
93
+ * per input entry. The resulting node can be inserted into a kit tree
94
94
  * for further processing or stringification.
95
95
  *
96
96
  * @param rows - Array of {@link DependencyTableRow} objects to serialize
97
- * @returns An mdast `Table` node ready for AST insertion
97
+ * @returns An `@effected/markdown` `Table` node ready for tree insertion
98
98
  */
99
99
  static serialize(rows) {
100
100
  return serializeDependencyTable(rows);
@@ -104,7 +104,7 @@ var DependencyTable = class {
104
104
  *
105
105
  * @remarks
106
106
  * Convenience method that combines {@link DependencyTable.serialize} with
107
- * remark stringification. Produces a GFM-compatible markdown table string.
107
+ * the canonical `@effected/markdown` emitter. Produces a GFM-compatible markdown table string.
108
108
  *
109
109
  * @param rows - Array of {@link DependencyTableRow} objects to render
110
110
  * @returns A markdown string containing the formatted table
@@ -1,29 +1,34 @@
1
- import { ContentStructureRule } from "../remark/rules/content-structure.js";
2
- import { DependencyTableFormatRule } from "../remark/rules/dependency-table-format.js";
3
- import { HeadingHierarchyRule } from "../remark/rules/heading-hierarchy.js";
4
- import { RequiredSectionsRule } from "../remark/rules/required-sections.js";
5
- import { UncategorizedContentRule } from "../remark/rules/uncategorized-content.js";
1
+ import { parseKitMarkdown } from "../utils/markdown-emit.js";
2
+ import { contentStructure } from "../rules/content-structure.js";
3
+ import { dependencyTableFormat } from "../rules/dependency-table-format.js";
4
+ import { headingHierarchy } from "../rules/heading-hierarchy.js";
5
+ import { requiredSections } from "../rules/required-sections.js";
6
+ import { uncategorizedContent } from "../rules/uncategorized-content.js";
6
7
  import { stripFrontmatter } from "../utils/strip-frontmatter.js";
7
- import remarkGfm from "remark-gfm";
8
- import remarkParse from "remark-parse";
9
- import { unified } from "unified";
10
8
  import { readFileSync, readdirSync } from "node:fs";
11
9
  import { join } from "node:path";
12
- import remarkStringify from "remark-stringify";
13
10
 
14
11
  // src/changesets/api/linter.ts
15
12
  /**
16
13
  * Class-based API wrapper for changeset linting.
17
14
  *
18
- * Provides a static class interface that runs all five remark-lint rules
15
+ * Provides a static class interface that runs all five kit-node lint rules
19
16
  * against changeset markdown files and returns structured diagnostics.
20
17
  *
21
18
  * @internal
22
19
  */
20
+ /** The five changeset lint rules, in reporting order. */
21
+ const RULES = [
22
+ headingHierarchy,
23
+ requiredSections,
24
+ contentStructure,
25
+ dependencyTableFormat,
26
+ uncategorizedContent
27
+ ];
23
28
  /**
24
29
  * Static class for linting changeset markdown files.
25
30
  *
26
- * Runs the five remark-lint rules (heading-hierarchy, required-sections,
31
+ * Runs the five `@effected/markdown` kit-node lint rules (heading-hierarchy, required-sections,
27
32
  * content-structure, dependency-table-format, uncategorized-content) against
28
33
  * changeset markdown and returns structured {@link LintMessage} diagnostics.
29
34
  *
@@ -136,15 +141,14 @@ var ChangesetLinter = class ChangesetLinter {
136
141
  * @returns Array of {@link LintMessage} diagnostics (empty if the content is valid)
137
142
  */
138
143
  static validateContent(content, filePath = "<input>") {
139
- const body = stripFrontmatter(content);
140
- return unified().use(remarkParse).use(remarkGfm).use(remarkStringify).use(HeadingHierarchyRule).use(RequiredSectionsRule).use(ContentStructureRule).use(DependencyTableFormatRule).use(UncategorizedContentRule).processSync(body).messages.map((msg) => ({
144
+ const root = parseKitMarkdown(stripFrontmatter(content));
145
+ return RULES.flatMap((rule) => rule(root).map((finding) => ({
141
146
  file: filePath,
142
- /* v8 ignore next 3 -- ruleId/line/column fallbacks; remark-lint always provides these */
143
- rule: msg.ruleId ?? msg.source ?? "unknown",
144
- line: msg.line ?? 1,
145
- column: msg.column ?? 1,
146
- message: msg.message
147
- }));
147
+ rule: finding.rule,
148
+ line: finding.position.start.line,
149
+ column: finding.position.start.column,
150
+ message: finding.message
151
+ })));
148
152
  }
149
153
  /**
150
154
  * Validate all changeset `.md` files in a directory.
@@ -1,34 +1,36 @@
1
- import { emitMarkdown } from "../utils/markdown-emit.js";
2
- import { ContributorFootnotesPlugin } from "../remark/plugins/contributor-footnotes.js";
3
- import { MaintenanceNotePlugin } from "../remark/plugins/maintenance-note.js";
4
- import { SilkChangesetTransformPreset } from "../remark/presets.js";
5
- import remarkGfm from "remark-gfm";
6
- import remarkParse from "remark-parse";
7
- import { unified } from "unified";
1
+ import { emitKitMarkdown, parseKitMarkdown } from "../utils/markdown-emit.js";
2
+ import { aggregateDependencyTables } from "../transforms/aggregate-dependency-tables.js";
3
+ import { contributorFootnotes } from "../transforms/contributor-footnotes.js";
4
+ import { deduplicateItems } from "../transforms/deduplicate-items.js";
5
+ import { issueLinkRefs } from "../transforms/issue-link-refs.js";
6
+ import { maintenanceNote } from "../transforms/maintenance-note.js";
7
+ import { mergeSections } from "../transforms/merge-sections.js";
8
+ import { normalizeFormat } from "../transforms/normalize-format.js";
9
+ import { reorderSections } from "../transforms/reorder-sections.js";
8
10
  import { readFileSync, writeFileSync } from "node:fs";
9
11
 
10
12
  // src/changesets/api/transformer.ts
11
13
  /**
12
14
  * Class-based API wrapper for changelog transformation.
13
15
  *
14
- * Provides a static class interface that runs all remark transform
15
- * plugins against CHANGELOG markdown content as the post-processing
16
- * layer of the three-layer pipeline.
16
+ * Provides a static class interface that runs the `@effected/markdown`
17
+ * kit-node changelog transforms against CHANGELOG markdown content as the
18
+ * post-processing layer of the three-layer pipeline.
17
19
  *
18
20
  * @internal
19
21
  */
20
22
  /**
21
23
  * Static class for post-processing CHANGELOG.md files.
22
24
  *
23
- * Implements the third layer of the three-layer pipeline by running
24
- * the {@link SilkChangesetTransformPreset} plugins (currently seven) in a
25
- * fixed order to clean up, normalize, and enhance changelog output produced
26
- * by the formatter layer.
25
+ * Implements the third layer of the three-layer pipeline by running seven
26
+ * `@effected/markdown` kit-node transforms in a fixed order to clean up,
27
+ * normalize, and enhance changelog output produced by the formatter layer:
28
+ * aggregate dependency tables, merge duplicate sections, reorder sections by
29
+ * category priority, deduplicate list items, aggregate contributor thanks,
30
+ * convert issue references to reference links, and normalize formatting. An
31
+ * optional maintenance-note transform runs last.
27
32
  *
28
33
  * @remarks
29
- * See {@link SilkChangesetTransformPreset} for the ordered plugin list and
30
- * the rationale behind each plugin's position.
31
- *
32
34
  * The transformer operates on the full CHANGELOG.md content (all versions),
33
35
  * not just the latest release block. It is idempotent -- running it multiple
34
36
  * times produces the same output.
@@ -77,7 +79,7 @@ import { readFileSync, writeFileSync } from "node:fs";
77
79
  * }
78
80
  * ```
79
81
  *
80
- * @see {@link Categories} for the priority order used by ReorderSectionsPlugin
82
+ * @see {@link Categories} for the priority order used when reordering sections
81
83
  * @see {@link ChangesetLinter} for the pre-validation layer (layer 1)
82
84
  * @see {@link Changelog} for the formatter layer (layer 2)
83
85
  *
@@ -87,15 +89,14 @@ var ChangelogTransformer = class ChangelogTransformer {
87
89
  /* v8 ignore next -- private constructor prevents direct instantiation */
88
90
  constructor() {}
89
91
  /**
90
- * Transform CHANGELOG markdown content by running the
91
- * {@link SilkChangesetTransformPreset} plugins.
92
+ * Transform CHANGELOG markdown content by running the kit-node
93
+ * changelog transforms.
92
94
  *
93
95
  * @remarks
94
- * The input is parsed with `remark-parse` and `remark-gfm` (for table
95
- * support), processed through every plugin in {@link SilkChangesetTransformPreset}
96
- * in order, and emitted back to markdown through the canonical
97
- * `@effected/markdown` stringifier. The operation is synchronous and
98
- * idempotent.
96
+ * The input is parsed into `@effected/markdown` nodes (GFM dialect, author
97
+ * spellings canonicalized), folded through every transform in order, and
98
+ * emitted back to markdown through the canonical `@effected/markdown`
99
+ * stringifier. The operation is synchronous and idempotent.
99
100
  *
100
101
  * @param content - Raw CHANGELOG markdown string (may contain multiple
101
102
  * version blocks, GFM tables, footnotes, and reference links)
@@ -104,19 +105,23 @@ var ChangelogTransformer = class ChangelogTransformer {
104
105
  * sections merged, reordered, deduplicated, and normalized
105
106
  */
106
107
  static transformContent(content, options) {
107
- const processor = unified().use(remarkParse).use(remarkGfm);
108
- for (const plugin of SilkChangesetTransformPreset) if (plugin === ContributorFootnotesPlugin && options?.thanks !== void 0) processor.use(ContributorFootnotesPlugin, { thanks: options.thanks });
109
- else processor.use(plugin);
110
- if (options?.maintenance) processor.use(MaintenanceNotePlugin, options.maintenance);
111
- const parsed = processor.parse(content);
112
- const transformed = processor.runSync(parsed);
113
- return emitMarkdown(transformed);
108
+ const pipeline = [
109
+ aggregateDependencyTables,
110
+ mergeSections,
111
+ reorderSections,
112
+ deduplicateItems,
113
+ contributorFootnotes(options?.thanks !== void 0 ? { thanks: options.thanks } : void 0),
114
+ issueLinkRefs,
115
+ normalizeFormat
116
+ ];
117
+ if (options?.maintenance) pipeline.push(maintenanceNote(options.maintenance));
118
+ return emitKitMarkdown(pipeline.reduce((root, transform) => transform(root), parseKitMarkdown(content)));
114
119
  }
115
120
  /**
116
121
  * Transform a CHANGELOG file in-place.
117
122
  *
118
123
  * @remarks
119
- * Reads the file synchronously, runs all transform plugins via
124
+ * Reads the file synchronously, runs all transforms via
120
125
  * {@link ChangelogTransformer.transformContent}, and writes the result
121
126
  * back to the same path. The file is overwritten atomically (single
122
127
  * `writeFileSync` call).
@@ -217,7 +217,7 @@ const CATEGORIES = [
217
217
  ];
218
218
  /**
219
219
  * Set of all valid section heading strings (case-insensitive lookup).
220
- * Used by Layer 1 (remark-lint) to validate changeset headings.
220
+ * Used by the kit lint rules (Layer 1) to validate changeset headings.
221
221
  */
222
222
  const headingToCategory = new Map(CATEGORIES.map((cat) => [cat.heading.toLowerCase(), cat]));
223
223
  /**
@@ -8,8 +8,8 @@ import { Schema } from "effect";
8
8
  * Section categories define how changes are grouped and ordered in release
9
9
  * notes and CHANGELOGs. Each category maps conventional commit types to a
10
10
  * display heading with a priority for ordering. Categories are used across
11
- * all three processing layers: remark-lint pre-validation (Layer 1),
12
- * changelog formatting (Layer 2), and remark-transform post-processing
11
+ * all three processing layers: kit lint-rule pre-validation (Layer 1),
12
+ * changelog formatting (Layer 2), and kit transform post-processing
13
13
  * (Layer 3).
14
14
  *
15
15
  * @see {@link CATEGORIES} for the predefined list of 13 section categories
@@ -21,7 +21,7 @@ import { Effect } from "effect";
21
21
  * consuming package's `package.json` fields (`dependencies`,
22
22
  * `devDependencies`, `peerDependencies`, `optionalDependencies`) via
23
23
  * the {@link inferDependencyType} helper. Downstream, the heading is
24
- * consumed by `AggregateDependencyTablesPlugin`, which locates and
24
+ * consumed by the aggregate-dependency-tables transform, which locates and
25
25
  * merges per-package dependency tables during changelog assembly.
26
26
  *
27
27
  * ### Dependency type inference
@@ -61,8 +61,8 @@ import { Effect } from "effect";
61
61
  *
62
62
  * `GitHubService.layer` satisfies the requirements of both `getReleaseLine` and
63
63
  * `getDependencyReleaseLine`, which each need only `GitHubService`. Markdown
64
- * parsing is not a layer: the formatters call the remark pipeline's
65
- * `parseMarkdown` / `stringifyMarkdown` functions directly.
64
+ * parsing is not a layer: the formatters call `parseKitMarkdown` /
65
+ * `emitKitMarkdown` from `utils/markdown-emit.ts` directly.
66
66
  *
67
67
  * @internal
68
68
  */
@@ -12,7 +12,7 @@ const DOCS_BASE = "https://github.com/savvy-web/systems/blob/main/packages/silk-
12
12
  * @remarks
13
13
  * Keyed by rule code (`CSH001`--`CSH005`). Each value is a full URL
14
14
  * pointing to the rule's documentation page on GitHub. Used by the
15
- * remark-lint plugins to attach documentation links to diagnostic
15
+ * lint rules to attach documentation links to diagnostic
16
16
  * messages.
17
17
  *
18
18
  * @internal
@@ -135,7 +135,7 @@ const MarkdownParseErrorBase = Data.TaggedError("MarkdownParseError");
135
135
  * Markdown parsing failure.
136
136
  *
137
137
  * @remarks
138
- * Raised when a markdown file cannot be parsed into an AST by the unified/remark
138
+ * Raised when a markdown file cannot be parsed into an AST by the @effected/markdown
139
139
  * pipeline. Carries optional source file location information (line, column)
140
140
  * for diagnostic display.
141
141
  *
@@ -13,21 +13,7 @@ import { GitHubInfoSchema, IssueNumberSchema, UrlOrMarkdownLinkSchema, UsernameS
13
13
  import changelogFunctions, { makeChangelogFunctions } from "./changelog/index.js";
14
14
  import { Changelog } from "./api/changelog.js";
15
15
  import { DependencyTable } from "./api/dependency-table.js";
16
- import { ContentStructureRule } from "./remark/rules/content-structure.js";
17
- import { DependencyTableFormatRule } from "./remark/rules/dependency-table-format.js";
18
- import { HeadingHierarchyRule } from "./remark/rules/heading-hierarchy.js";
19
- import { RequiredSectionsRule } from "./remark/rules/required-sections.js";
20
- import { UncategorizedContentRule } from "./remark/rules/uncategorized-content.js";
21
16
  import { ChangesetLinter } from "./api/linter.js";
22
- import { ContributorFootnotesPlugin } from "./remark/plugins/contributor-footnotes.js";
23
- import { MaintenanceNotePlugin } from "./remark/plugins/maintenance-note.js";
24
- import { AggregateDependencyTablesPlugin } from "./remark/plugins/aggregate-dependency-tables.js";
25
- import { DeduplicateItemsPlugin } from "./remark/plugins/deduplicate-items.js";
26
- import { IssueLinkRefsPlugin } from "./remark/plugins/issue-link-refs.js";
27
- import { MergeSectionsPlugin } from "./remark/plugins/merge-sections.js";
28
- import { NormalizeFormatPlugin } from "./remark/plugins/normalize-format.js";
29
- import { ReorderSectionsPlugin } from "./remark/plugins/reorder-sections.js";
30
- import { SilkChangesetPreset, SilkChangesetTransformPreset } from "./remark/presets.js";
31
17
  import { ChangelogTransformer } from "./api/transformer.js";
32
18
  import { vanillaChangelogFunctions } from "./changelog/vanilla.js";
33
19
  import { ClassificationReasonSchema, ClassificationSchema, ConfigInspector, InspectedConfigSchema, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, makeConfigInspectorTest } from "./services/config-inspector.js";
@@ -45,16 +31,15 @@ import { CommitHashSchema, VersionTypeSchema } from "./schemas/git.js";
45
31
  import { ChangesetSchema, ChangesetSummarySchema, DependencyTypeSchema, DependencyUpdateSchema } from "./schemas/changeset.js";
46
32
  import { CoexistingChangesetSchema, RegenDiffRowSchema, RegenPlanSchema, RegenResultSchema } from "./schemas/deps-regen.js";
47
33
  import { AppliedReleaseEntrySchema, AppliedReleaseSchema, BumpTypeSchema, ChangesetPreviewSchema, PendingChangesetSchema, PreviewReleaseSchema, VersionFileUpdateRecordSchema } from "./schemas/release-plan.js";
48
- import { ContentStructureRule as ContentStructureRule$1 } from "./markdownlint/rules/content-structure.js";
49
- import { DependencyTableFormatRule as DependencyTableFormatRule$1 } from "./markdownlint/rules/dependency-table-format.js";
50
- import { HeadingHierarchyRule as HeadingHierarchyRule$1 } from "./markdownlint/rules/heading-hierarchy.js";
51
- import { RequiredSectionsRule as RequiredSectionsRule$1 } from "./markdownlint/rules/required-sections.js";
52
- import { UncategorizedContentRule as UncategorizedContentRule$1 } from "./markdownlint/rules/uncategorized-content.js";
34
+ import { ContentStructureRule } from "./markdownlint/rules/content-structure.js";
35
+ import { DependencyTableFormatRule } from "./markdownlint/rules/dependency-table-format.js";
36
+ import { HeadingHierarchyRule } from "./markdownlint/rules/heading-hierarchy.js";
37
+ import { RequiredSectionsRule } from "./markdownlint/rules/required-sections.js";
38
+ import { UncategorizedContentRule } from "./markdownlint/rules/uncategorized-content.js";
53
39
  import SilkChangesetsRules from "./markdownlint/index.js";
54
40
 
55
41
  // src/changesets/index.ts
56
42
  var changesets_exports = /* @__PURE__ */ __exportAll({
57
- AggregateDependencyTablesPlugin: () => AggregateDependencyTablesPlugin,
58
43
  AppliedReleaseEntrySchema: () => AppliedReleaseEntrySchema,
59
44
  AppliedReleaseSchema: () => AppliedReleaseSchema,
60
45
  BranchAnalysisSchema: () => BranchAnalysisSchema,
@@ -79,12 +64,8 @@ var changesets_exports = /* @__PURE__ */ __exportAll({
79
64
  CommitHashSchema: () => CommitHashSchema,
80
65
  ConfigInspector: () => ConfigInspector,
81
66
  ConfigurationError: () => ConfigurationError,
82
- ContentStructureRule: () => ContentStructureRule,
83
- ContributorFootnotesPlugin: () => ContributorFootnotesPlugin,
84
- DeduplicateItemsPlugin: () => DeduplicateItemsPlugin,
85
67
  DependencyActionSchema: () => DependencyActionSchema,
86
68
  DependencyTable: () => DependencyTable,
87
- DependencyTableFormatRule: () => DependencyTableFormatRule,
88
69
  DependencyTableRowSchema: () => DependencyTableRowSchema,
89
70
  DependencyTableSchema: () => DependencyTableSchema,
90
71
  DependencyTableTypeSchema: () => DependencyTableTypeSchema,
@@ -98,26 +79,21 @@ var changesets_exports = /* @__PURE__ */ __exportAll({
98
79
  GitHubInfoSchema: () => GitHubInfoSchema,
99
80
  GitHubService: () => GitHubService,
100
81
  GlobSchema: () => GlobSchema,
101
- HeadingHierarchyRule: () => HeadingHierarchyRule,
102
82
  HookReplayError: () => HookReplayError,
103
83
  InspectedConfigSchema: () => InspectedConfigSchema,
104
- IssueLinkRefsPlugin: () => IssueLinkRefsPlugin,
105
84
  IssueNumberSchema: () => IssueNumberSchema,
106
85
  JsonPathSchema: () => JsonPathSchema,
107
86
  LegacyVersionFileConfigSchema: () => LegacyVersionFileConfigSchema,
108
87
  LegacyVersionFilesSchema: () => LegacyVersionFilesSchema,
109
- MaintenanceNotePlugin: () => MaintenanceNotePlugin,
110
88
  MaintenanceReasonSchema: () => MaintenanceReasonSchema,
111
89
  MaintenanceTriggerSchema: () => MaintenanceTriggerSchema,
112
90
  MarkdownParseError: () => MarkdownParseError,
113
- MarkdownlintContentStructureRule: () => ContentStructureRule$1,
114
- MarkdownlintDependencyTableFormatRule: () => DependencyTableFormatRule$1,
115
- MarkdownlintHeadingHierarchyRule: () => HeadingHierarchyRule$1,
116
- MarkdownlintRequiredSectionsRule: () => RequiredSectionsRule$1,
117
- MarkdownlintUncategorizedContentRule: () => UncategorizedContentRule$1,
118
- MergeSectionsPlugin: () => MergeSectionsPlugin,
91
+ MarkdownlintContentStructureRule: () => ContentStructureRule,
92
+ MarkdownlintDependencyTableFormatRule: () => DependencyTableFormatRule,
93
+ MarkdownlintHeadingHierarchyRule: () => HeadingHierarchyRule,
94
+ MarkdownlintRequiredSectionsRule: () => RequiredSectionsRule,
95
+ MarkdownlintUncategorizedContentRule: () => UncategorizedContentRule,
119
96
  NonEmptyString: () => NonEmptyString,
120
- NormalizeFormatPlugin: () => NormalizeFormatPlugin,
121
97
  PackageScopeSchema: () => PackageScopeSchema,
122
98
  PackagesRecordSchema: () => PackagesRecordSchema,
123
99
  PendingChangesetSchema: () => PendingChangesetSchema,
@@ -128,16 +104,11 @@ var changesets_exports = /* @__PURE__ */ __exportAll({
128
104
  RegenResultSchema: () => RegenResultSchema,
129
105
  ReleasePlanError: () => ReleasePlanError,
130
106
  ReleasePlanner: () => ReleasePlanner,
131
- ReorderSectionsPlugin: () => ReorderSectionsPlugin,
132
107
  RepoSchema: () => RepoSchema,
133
- RequiredSectionsRule: () => RequiredSectionsRule,
134
108
  ResolvedPackageScopeSchema: () => ResolvedPackageScopeSchema,
135
109
  ResolvedVersionFileSchema: () => ResolvedVersionFileSchema,
136
110
  SectionCategorySchema: () => SectionCategorySchema,
137
- SilkChangesetPreset: () => SilkChangesetPreset,
138
- SilkChangesetTransformPreset: () => SilkChangesetTransformPreset,
139
111
  SilkChangesetsRules: () => SilkChangesetsRules,
140
- UncategorizedContentRule: () => UncategorizedContentRule,
141
112
  UrlOrMarkdownLinkSchema: () => UrlOrMarkdownLinkSchema,
142
113
  UsernameSchema: () => UsernameSchema,
143
114
  VERSION_RE: () => VERSION_RE,
@@ -165,4 +136,4 @@ var changesets_exports = /* @__PURE__ */ __exportAll({
165
136
  vanillaChangelogFunctions: () => vanillaChangelogFunctions
166
137
  });
167
138
 
168
- export { AggregateDependencyTablesPlugin, AppliedReleaseEntrySchema, AppliedReleaseSchema, BranchAnalysisSchema, BranchAnalyzer, BranchFileEntrySchema, BumpTypeSchema, Categories, Changelog, ChangelogService, ChangelogTransformer, ChangesetIOError, ChangesetLinter, ChangesetLogMode, ChangesetOptionsSchema, ChangesetPreviewSchema, ChangesetSchema, ChangesetSummarySchema, ChangesetValidationError, ClassificationReasonSchema, ClassificationSchema, CoexistingChangesetSchema, CommitHashSchema, ConfigInspector, ConfigurationError, ContentStructureRule, ContributorFootnotesPlugin, DeduplicateItemsPlugin, DependencyActionSchema, DependencyTable, DependencyTableFormatRule, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, DependencyTypeSchema, DependencyUpdateSchema, DepsRegen, DepsRegenDefault, FileStatusSchema, GitError, GitHubApiError, GitHubInfoSchema, GitHubService, GlobSchema, HeadingHierarchyRule, HookReplayError, InspectedConfigSchema, IssueLinkRefsPlugin, IssueNumberSchema, JsonPathSchema, LegacyVersionFileConfigSchema, LegacyVersionFilesSchema, MaintenanceNotePlugin, MaintenanceReasonSchema, MaintenanceTriggerSchema, MarkdownParseError, ContentStructureRule$1 as MarkdownlintContentStructureRule, DependencyTableFormatRule$1 as MarkdownlintDependencyTableFormatRule, HeadingHierarchyRule$1 as MarkdownlintHeadingHierarchyRule, RequiredSectionsRule$1 as MarkdownlintRequiredSectionsRule, UncategorizedContentRule$1 as MarkdownlintUncategorizedContentRule, MergeSectionsPlugin, NonEmptyString, NormalizeFormatPlugin, PackageScopeSchema, PackagesRecordSchema, PendingChangesetSchema, PositiveInteger, PreviewReleaseSchema, RegenDiffRowSchema, RegenPlanSchema, RegenResultSchema, ReleasePlanError, ReleasePlanner, ReorderSectionsPlugin, RepoSchema, RequiredSectionsRule, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, SectionCategorySchema, SilkChangesetPreset, SilkChangesetTransformPreset, SilkChangesetsRules, UncategorizedContentRule, UrlOrMarkdownLinkSchema, UsernameSchema, VERSION_RE, VersionFileConfigSchema, VersionFileError, VersionFileUpdateRecordSchema, VersionFiles, VersionFilesSchema, VersionOrEmptySchema, VersionTypeSchema, changelogFunctions, changesets_exports, computeWorkspaceDependencyDiffs, deriveMaintenanceReason, gitMergeBase, isPureDependencyChangeset, listPublishablePackageNames, makeBranchAnalyzerTest, makeChangelogFunctions, makeConfigInspectorTest, makeDepsRegenDefault, makeGitHubTest, makeReleasePlannerTest, parseChangesetPackages, serializeDependencyTableToMarkdown, vanillaChangelogFunctions };
139
+ export { AppliedReleaseEntrySchema, AppliedReleaseSchema, BranchAnalysisSchema, BranchAnalyzer, BranchFileEntrySchema, BumpTypeSchema, Categories, Changelog, ChangelogService, ChangelogTransformer, ChangesetIOError, ChangesetLinter, ChangesetLogMode, ChangesetOptionsSchema, ChangesetPreviewSchema, ChangesetSchema, ChangesetSummarySchema, ChangesetValidationError, ClassificationReasonSchema, ClassificationSchema, CoexistingChangesetSchema, CommitHashSchema, ConfigInspector, ConfigurationError, DependencyActionSchema, DependencyTable, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, DependencyTypeSchema, DependencyUpdateSchema, DepsRegen, DepsRegenDefault, FileStatusSchema, GitError, GitHubApiError, GitHubInfoSchema, GitHubService, GlobSchema, HookReplayError, InspectedConfigSchema, IssueNumberSchema, JsonPathSchema, LegacyVersionFileConfigSchema, LegacyVersionFilesSchema, MaintenanceReasonSchema, MaintenanceTriggerSchema, MarkdownParseError, ContentStructureRule as MarkdownlintContentStructureRule, DependencyTableFormatRule as MarkdownlintDependencyTableFormatRule, HeadingHierarchyRule as MarkdownlintHeadingHierarchyRule, RequiredSectionsRule as MarkdownlintRequiredSectionsRule, UncategorizedContentRule as MarkdownlintUncategorizedContentRule, NonEmptyString, PackageScopeSchema, PackagesRecordSchema, PendingChangesetSchema, PositiveInteger, PreviewReleaseSchema, RegenDiffRowSchema, RegenPlanSchema, RegenResultSchema, ReleasePlanError, ReleasePlanner, RepoSchema, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, SectionCategorySchema, SilkChangesetsRules, UrlOrMarkdownLinkSchema, UsernameSchema, VERSION_RE, VersionFileConfigSchema, VersionFileError, VersionFileUpdateRecordSchema, VersionFiles, VersionFilesSchema, VersionOrEmptySchema, VersionTypeSchema, changelogFunctions, changesets_exports, computeWorkspaceDependencyDiffs, deriveMaintenanceReason, gitMergeBase, isPureDependencyChangeset, listPublishablePackageNames, makeBranchAnalyzerTest, makeChangelogFunctions, makeConfigInspectorTest, makeDepsRegenDefault, makeGitHubTest, makeReleasePlannerTest, parseChangesetPackages, serializeDependencyTableToMarkdown, vanillaChangelogFunctions };
@@ -33,7 +33,7 @@ function hasContentBetween(tokens, currentIdx, nextIdx) {
33
33
  * `content` token before the next prefix or end of list.
34
34
  *
35
35
  * @remarks
36
- * This rule mirrors the remark-lint rule `remarkLintContentStructure` but uses
36
+ * This rule mirrors the kit rule `contentStructure` in `src/changesets/rules/content-structure.ts` but uses
37
37
  * markdownlint's micromark token API so it can run inside markdownlint-cli2 and
38
38
  * the VS Code markdownlint extension.
39
39
  *
@@ -45,7 +45,7 @@ function hasContentBetween(tokens, currentIdx, nextIdx) {
45
45
  * ```
46
46
  *
47
47
  * @see {@link https://github.com/savvy-web/systems/blob/main/packages/silk-effects/docs/rules/CSH003.md | CSH003 rule documentation}
48
- * @see `src/remark/rules/content-structure.ts` for the corresponding remark-lint rule
48
+ * @see `src/changesets/rules/content-structure.ts` for the corresponding kit-node rule
49
49
  *
50
50
  * @public
51
51
  */
@@ -15,7 +15,7 @@ import { getHeadingLevel } from "./utils.js";
15
15
  * (h2 then h3, not h2 then h4).
16
16
  *
17
17
  * @remarks
18
- * This rule mirrors the remark-lint rule `remarkLintHeadingHierarchy` but uses
18
+ * This rule mirrors the kit rule `headingHierarchy` in `src/changesets/rules/heading-hierarchy.ts` but uses
19
19
  * markdownlint's micromark token API so it can run inside markdownlint-cli2 and
20
20
  * the VS Code markdownlint extension.
21
21
  *
@@ -27,7 +27,7 @@ import { getHeadingLevel } from "./utils.js";
27
27
  * ```
28
28
  *
29
29
  * @see {@link https://github.com/savvy-web/systems/blob/main/packages/silk-effects/docs/rules/CSH001.md | CSH001 rule documentation}
30
- * @see `src/remark/rules/heading-hierarchy.ts` for the corresponding remark-lint rule
30
+ * @see `src/changesets/rules/heading-hierarchy.ts` for the corresponding kit-node rule
31
31
  *
32
32
  * @public
33
33
  */
@@ -16,7 +16,7 @@ import { getHeadingLevel, getHeadingText } from "./utils.js";
16
16
  * (`src/categories/index.ts`). This rule inspects `atxHeading` micromark
17
17
  * tokens and extracts their text via the {@link getHeadingText} utility.
18
18
  *
19
- * This rule mirrors the remark-lint rule `remarkLintRequiredSections` but uses
19
+ * This rule mirrors the kit rule `requiredSections` in `src/changesets/rules/required-sections.ts` but uses
20
20
  * markdownlint's micromark token API so it can run inside markdownlint-cli2 and
21
21
  * the VS Code markdownlint extension.
22
22
  *
@@ -28,7 +28,7 @@ import { getHeadingLevel, getHeadingText } from "./utils.js";
28
28
  * ```
29
29
  *
30
30
  * @see {@link https://github.com/savvy-web/systems/blob/main/packages/silk-effects/docs/rules/CSH002.md | CSH002 rule documentation}
31
- * @see `src/remark/rules/required-sections.ts` for the corresponding remark-lint rule
31
+ * @see `src/changesets/rules/required-sections.ts` for the corresponding kit-node rule
32
32
  *
33
33
  * @public
34
34
  */
@@ -16,7 +16,7 @@ import { getHeadingLevel } from "./utils.js";
16
16
  * triggers an error. This ensures that changeset content is always grouped
17
17
  * under a recognized category heading.
18
18
  *
19
- * This rule mirrors the remark-lint rule `remarkLintUncategorizedContent` but
19
+ * This rule mirrors the kit rule `uncategorizedContent` in `src/changesets/rules/uncategorized-content.ts` but
20
20
  * uses markdownlint's micromark token API so it can run inside
21
21
  * markdownlint-cli2 and the VS Code markdownlint extension.
22
22
  *
@@ -28,7 +28,7 @@ import { getHeadingLevel } from "./utils.js";
28
28
  * ```
29
29
  *
30
30
  * @see {@link https://github.com/savvy-web/systems/blob/main/packages/silk-effects/docs/rules/CSH004.md | CSH004 rule documentation}
31
- * @see `src/remark/rules/uncategorized-content.ts` for the corresponding remark-lint rule
31
+ * @see `src/changesets/rules/uncategorized-content.ts` for the corresponding kit-node rule
32
32
  *
33
33
  * @public
34
34
  */
@@ -5,8 +5,8 @@ import { RULE_DOCS } from "../../constants.js";
5
5
  * Get the heading level (1-6) from an `atxHeading` or `setextHeading` token.
6
6
  *
7
7
  * @remarks
8
- * remark-parse normalizes setext headings to plain depth-1/2 heading nodes,
9
- * so the remark siblings of these rules see them as ordinary headings. The
8
+ * `@effected/markdown` normalizes setext headings to plain depth-1/2 heading nodes,
9
+ * so the kit siblings of these rules see them as ordinary headings. The
10
10
  * micromark extractors must agree, or the two engines disagree about the
11
11
  * same file (the issue #367 class of drift).
12
12
  *
@@ -33,9 +33,9 @@ const BACKSLASH_ESCAPE_RE = /\\([!-/:-@[-`{-~])/g;
33
33
  * Resolve CommonMark backslash escapes in raw micromark source text.
34
34
  *
35
35
  * @remarks
36
- * Every rule in this directory has a sibling remark implementation that reads
37
- * the parsed mdast tree, where the parser has already resolved escapes, via
38
- * `mdast-util-to-string`. Micromark tokens instead carry RAW source. Comparing
36
+ * Every rule in this directory has a sibling kit implementation that reads
37
+ * the parsed `@effected/markdown` tree, where the parser has already resolved escapes, via
38
+ * `Mdast.toText`. Micromark tokens instead carry RAW source. Comparing
39
39
  * raw text against a value the parsed form would produce makes the two
40
40
  * implementations of one documented rule disagree about the same file
41
41
  * (issue #367).
@@ -54,7 +54,7 @@ function unescapeMarkdown(raw) {
54
54
  *
55
55
  * @remarks
56
56
  * Escape-resolved, so a heading compares equal to the same heading as the
57
- * remark rules see it. `getHeadingLevel` needs no equivalent — it counts
57
+ * the kit rules see it. `getHeadingLevel` needs no equivalent — it counts
58
58
  * sequence characters rather than reading text.
59
59
  *
60
60
  * @param heading - The `atxHeading` or `setextHeading` micromark token
@@ -0,0 +1,44 @@
1
+ import { RULE_DOCS } from "../constants.js";
2
+ import { finding } from "./types.js";
3
+ import { MarkdownVisitor, Mdast } from "@effected/markdown";
4
+
5
+ // src/changesets/rules/content-structure.ts
6
+ /**
7
+ * Lint rule: changeset-content-structure (CSH003).
8
+ *
9
+ * @remarks
10
+ * Kit rule. Flags empty h2 sections, code fences
11
+ * without a language, and empty list items. Findings are emitted in three
12
+ * passes (headings, code, list items) to match the markdownlint rule's order.
13
+ *
14
+ * @internal
15
+ */
16
+ const RULE = "changeset-content-structure";
17
+ /**
18
+ * Validate section and block content quality.
19
+ *
20
+ * @internal
21
+ */
22
+ const contentStructure = (root) => {
23
+ const findings = [];
24
+ root.children.forEach((node, index) => {
25
+ if (node.type !== "heading" || node.depth !== 2) return;
26
+ const next = root.children[index + 1];
27
+ if (!next || next.type === "heading" && next.depth === 2) findings.push(finding(RULE, `Empty section: heading has no content before the next section or end of file. Add a list of changes (e.g., "- Added feature X") under this heading, or remove the empty heading. See: ${RULE_DOCS.CSH003}`, node));
28
+ });
29
+ const codes = [];
30
+ const items = [];
31
+ for (const event of MarkdownVisitor.walk(root)) {
32
+ if (event._tag !== "Enter") continue;
33
+ const node = event.node;
34
+ if (node.type === "code" && !node.lang) codes.push(finding(RULE, `Code block is missing a language identifier. Add a language after the opening fence (e.g., \`\`\`ts, \`\`\`json, \`\`\`bash). See: ${RULE_DOCS.CSH003}`, node));
35
+ else if (node.type === "listItem" && !Mdast.toText(node).trim()) items.push(finding(RULE, `Empty list item. Each list item must contain descriptive text (e.g., "- Fixed login timeout issue"). See: ${RULE_DOCS.CSH003}`, node));
36
+ }
37
+ return [
38
+ ...findings,
39
+ ...codes,
40
+ ...items
41
+ ];
42
+ };
43
+
44
+ export { contentStructure };