@patdown/rules 0.3.1 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-patdown-rule-parser.d.ts","sourceRoot":"","sources":["../src/markdown-patdown-rule-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+KpD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAiBtF"}
1
+ {"version":3,"file":"markdown-patdown-rule-parser.d.ts","sourceRoot":"","sources":["../src/markdown-patdown-rule-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA4LpD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAiBtF"}
@@ -12,8 +12,18 @@ function atxHeadingTitle(line) {
12
12
  const title = match[1]?.trim() ?? '';
13
13
  return title.length === 0 ? undefined : title;
14
14
  }
15
+ function unwrapGlobToken(token) {
16
+ const trimmed = token.trim();
17
+ if (trimmed.length >= 2 && trimmed.startsWith('`') && trimmed.endsWith('`')) {
18
+ return trimmed.slice(1, -1);
19
+ }
20
+ return trimmed;
21
+ }
15
22
  function splitGlobList(raw) {
16
- return raw.split(/[,\s]+/u).filter((part) => part.length > 0);
23
+ return raw
24
+ .split(/[,\s]+/u)
25
+ .map(unwrapGlobToken)
26
+ .filter((part) => part.length > 0);
17
27
  }
18
28
  function globValuesFromLine(line) {
19
29
  const match = globLinePattern.exec(line);
@@ -1 +1 @@
1
- {"version":3,"file":"patdown-rule-source.d.ts","sourceRoot":"","sources":["../src/patdown-rule-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAG/E,OAAO,EAA+B,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC1F,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;;;;AAEvE,2FAA2F;AAC3F,qBAAa,uBAAwB,SAAQ,6BAA4C;IACxF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAC/B,CAAC;IACD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACD;;;;AAED,oDAAoD;AACpD,qBAAa,sBAAuB,SAAQ,4BAA2C;IACtF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;CACrC,CAAC;IACD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACD;;;;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAA2C;IACtF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG;;+BASwB,CAC1B,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KACxC,MAAM,CAAC,MAAM,CACjB,oBAAoB,EAClB,uBAAuB,GACvB,sBAAsB,GACtB,sBAAsB,GACtB,0BAA0B,EAC5B,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC;;AAhBH;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,sBAcA;CAAG;AAY1C,uGAAuG;AACvG,wBAAgB,wBAAwB,CACvC,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,CACf,MAAM,EACN,uBAAuB,GAAG,sBAAsB,EAChD,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC,CAsBA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAC1C,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAC5C,aAAa,GAAE,MAAoC,GACjD,MAAM,CAAC,MAAM,CACf,MAAM,EACN,uBAAuB,GAAG,sBAAsB,EAChD,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC,CAkBA;AAqCD,qFAAqF;AACrF,eAAO,MAAM,6BAA6B,8CAExC,CAAA"}
1
+ {"version":3,"file":"patdown-rule-source.d.ts","sourceRoot":"","sources":["../src/patdown-rule-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAG/E,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;;;;AAEvE,2FAA2F;AAC3F,qBAAa,uBAAwB,SAAQ,6BAA4C;IACxF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAC/B,CAAC;IACD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACD;;;;AAED,oDAAoD;AACpD,qBAAa,sBAAuB,SAAQ,4BAA2C;IACtF,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;CACrC,CAAC;IACD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACD;;;;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAA2C;IACtF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG;;+BASwB,CAC1B,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KACxC,MAAM,CAAC,MAAM,CACjB,oBAAoB,EAClB,uBAAuB,GACvB,sBAAsB,GACtB,sBAAsB,GACtB,0BAA0B,EAC5B,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC;;AAhBH;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,sBAcA;CAAG;AAY1C,uGAAuG;AACvG,wBAAgB,wBAAwB,CACvC,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,CACf,MAAM,EACN,uBAAuB,GAAG,sBAAsB,EAChD,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC,CAsBA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAC1C,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAC5C,aAAa,GAAE,MAAoC,GACjD,MAAM,CAAC,MAAM,CACf,MAAM,EACN,uBAAuB,GAAG,sBAAsB,EAChD,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACjC,CAkBA;AAsHD,qFAAqF;AACrF,eAAO,MAAM,6BAA6B,8CAExC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { Context, Data, Effect, FileSystem, Layer, Option, Path } from 'effect';
2
2
  import { parseMarkdownPatdownRules } from '#src/markdown-patdown-rule-parser';
3
- import { defaultPatdownRulesFileName } from '#src/patdown-rule';
3
+ import { defaultPatdownRulesFileName, } from '#src/patdown-rule';
4
4
  import { PatdownYesThresholdInvalid } from '#src/patdown-yes-threshold';
5
5
  /** No AGENTS.PATDOWN.md (or override path) existed walking up from the start directory. */
6
6
  export class PatdownRulesFileMissing extends Data.TaggedError('PatdownRulesFileMissing') {
@@ -71,27 +71,76 @@ export function resolvePatdownRulesFilePath(rulesFilePathOverride, rulesFileName
71
71
  });
72
72
  });
73
73
  }
74
- function loadMarkdownPatdownRules(rulesFilePathOverride) {
74
+ function parseMarkdownPatdownRulesFile(markdown) {
75
+ return Effect.try({
76
+ try: () => parseMarkdownPatdownRules(markdown),
77
+ catch: (cause) => cause instanceof PatdownYesThresholdInvalid
78
+ ? cause
79
+ : new PatdownRulesLoadFailed({
80
+ message: cause instanceof Error ? cause.message : String(cause),
81
+ }),
82
+ });
83
+ }
84
+ function loadMarkdownPatdownRulesFromFile(patdownRulesFilePath) {
75
85
  return Effect.gen(function* () {
76
- const patdownRulesFilePath = yield* resolvePatdownRulesFilePath(rulesFilePathOverride);
77
86
  const fileSystem = yield* FileSystem.FileSystem;
78
87
  const markdown = yield* fileSystem
79
88
  .readFileString(patdownRulesFilePath)
80
89
  .pipe(Effect.mapError(() => new PatdownRulesReadFailed({ patdownRulesFilePath })));
81
- const parsed = yield* Effect.try({
82
- try: () => parseMarkdownPatdownRules(markdown),
83
- catch: (cause) => cause instanceof PatdownYesThresholdInvalid
84
- ? cause
85
- : new PatdownRulesLoadFailed({
86
- message: cause instanceof Error ? cause.message : String(cause),
87
- }),
88
- });
90
+ const parsed = yield* parseMarkdownPatdownRulesFile(markdown);
89
91
  return {
90
92
  patdownRules: parsed,
91
93
  patdownRulesFilePath,
92
94
  };
93
95
  });
94
96
  }
97
+ /** Loads every `*.md` rule file in a directory, skipping README.md. */
98
+ function loadMarkdownPatdownRulesFromDirectory(patdownRulesDirectoryPath) {
99
+ return Effect.gen(function* () {
100
+ const fileSystem = yield* FileSystem.FileSystem;
101
+ const path = yield* Path.Path;
102
+ const entries = yield* fileSystem
103
+ .readDirectory(patdownRulesDirectoryPath)
104
+ .pipe(Effect.mapError(() => new PatdownRulesReadFailed({ patdownRulesFilePath: patdownRulesDirectoryPath })));
105
+ const ruleFiles = entries
106
+ .filter((entry) => entry.toLowerCase().endsWith('.md'))
107
+ .filter((entry) => entry.toLowerCase() !== 'readme.md')
108
+ .toSorted((left, right) => left.localeCompare(right));
109
+ if (ruleFiles.length === 0) {
110
+ return yield* new PatdownRulesLoadFailed({
111
+ message: `patdown: rules directory ${patdownRulesDirectoryPath} has no rule markdown files`,
112
+ });
113
+ }
114
+ const rules = [];
115
+ for (const ruleFile of ruleFiles) {
116
+ const rulePath = path.join(patdownRulesDirectoryPath, ruleFile);
117
+ const document = yield* loadMarkdownPatdownRulesFromFile(rulePath);
118
+ if (document.patdownRules.length === 0) {
119
+ return yield* new PatdownRulesLoadFailed({
120
+ message: `patdown: rules file ${rulePath} has no # headings`,
121
+ });
122
+ }
123
+ rules.push(...document.patdownRules);
124
+ }
125
+ return {
126
+ patdownRules: rules,
127
+ patdownRulesFilePath: patdownRulesDirectoryPath,
128
+ };
129
+ });
130
+ }
131
+ function loadMarkdownPatdownRules(rulesFilePathOverride) {
132
+ return Effect.gen(function* () {
133
+ const patdownRulesFilePath = yield* resolvePatdownRulesFilePath(rulesFilePathOverride);
134
+ const fileSystem = yield* FileSystem.FileSystem;
135
+ const info = yield* fileSystem
136
+ .stat(patdownRulesFilePath)
137
+ .pipe(Effect.mapError(() => new PatdownRulesReadFailed({ patdownRulesFilePath })));
138
+ if (info.type === 'Directory') {
139
+ return yield* loadMarkdownPatdownRulesFromDirectory(patdownRulesFilePath);
140
+ }
141
+ return yield* loadMarkdownPatdownRulesFromFile(patdownRulesFilePath);
142
+ });
143
+ }
95
144
  /** Live patdown rule source that reads markdown (`AGENTS.PATDOWN.md` by default). */
96
145
  export const MarkdownPatdownRuleSourceLive = Layer.succeed(PatdownRuleSource, {
97
146
  loadPatdownRules: loadMarkdownPatdownRules,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patdown/rules",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Fuzzy patdown rule types and markdown rule loading",
5
5
  "homepage": "https://github.com/tyler-dot-earth/patdown",
6
6
  "bugs": {