@a16njs/engine 0.4.0 → 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/dist/index.d.ts CHANGED
@@ -7,10 +7,25 @@ export interface ConversionOptions {
7
7
  source: string;
8
8
  /** Target plugin ID */
9
9
  target: string;
10
- /** Project root directory */
10
+ /** Project root directory (used as default for both source and target) */
11
11
  root: string;
12
12
  /** If true, only discover without writing */
13
13
  dryRun?: boolean;
14
+ /**
15
+ * Override root directory for discovery (reading).
16
+ * When set, discover() uses this instead of `root`.
17
+ */
18
+ sourceRoot?: string;
19
+ /**
20
+ * Override root directory for emission (writing).
21
+ * When set, emit() uses this instead of `root`.
22
+ */
23
+ targetRoot?: string;
24
+ /**
25
+ * If true, rewrite file path references in content so they point
26
+ * to the target-format paths instead of source-format paths.
27
+ */
28
+ rewritePathRefs?: boolean;
14
29
  }
15
30
  /**
16
31
  * Git-ignore change information.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,WAAW,EACX,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,8BAA8B;IAC9B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAsC;IAErD;;;OAGG;gBACS,OAAO,GAAE,UAAU,EAAO;IAMtC;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIxC;;;OAGG;IACH,WAAW,IAAI,UAAU,EAAE;IAS3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI7C;;;;;OAKG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQxE;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA0BrE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,WAAW,EACX,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AAsBxB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,8BAA8B;IAC9B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,mDAAmD;IACnD,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAsC;IAErD;;;OAGG;gBACS,OAAO,GAAE,UAAU,EAAO;IAMtC;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIxC;;;OAGG;IACH,WAAW,IAAI,UAAU,EAAE;IAS3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI7C;;;;;OAKG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQxE;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAmFrE"}
package/dist/index.js CHANGED
@@ -1,3 +1,22 @@
1
+ import { buildMapping, rewriteContent, detectOrphans } from './path-rewriter.js';
2
+ /**
3
+ * Well-known directory prefixes and file extensions for each plugin.
4
+ * Used by detectOrphans() to identify source-format path references.
5
+ */
6
+ const PLUGIN_PATH_PATTERNS = {
7
+ cursor: {
8
+ prefixes: ['.cursor/rules/', '.cursor/skills/', '.cursor/commands/'],
9
+ extensions: ['.mdc', '.md'],
10
+ },
11
+ claude: {
12
+ prefixes: ['.claude/rules/', '.claude/skills/'],
13
+ extensions: ['.md'],
14
+ },
15
+ a16n: {
16
+ prefixes: ['.a16n/'],
17
+ extensions: ['.md', '.json'],
18
+ },
19
+ };
1
20
  /**
2
21
  * The a16n conversion engine.
3
22
  * Orchestrates plugins to discover and emit agent customizations.
@@ -67,16 +86,55 @@ export class A16nEngine {
67
86
  if (!targetPlugin) {
68
87
  throw new Error(`Unknown target: ${options.target}`);
69
88
  }
89
+ // Resolve split roots: sourceRoot for discover, targetRoot for emit
90
+ const effectiveSourceRoot = options.sourceRoot ?? options.root;
91
+ const effectiveTargetRoot = options.targetRoot ?? options.root;
70
92
  // Discover from source
71
- const discovery = await sourcePlugin.discover(options.root);
72
- // Emit to target (pass dryRun to calculate what would be written)
73
- const emission = await targetPlugin.emit(discovery.items, options.root, {
93
+ const discovery = await sourcePlugin.discover(effectiveSourceRoot);
94
+ const allWarnings = [...discovery.warnings];
95
+ if (options.rewritePathRefs && discovery.items.length > 0) {
96
+ // Two-pass emit approach:
97
+ // Pass 1: Dry-run emit to get target paths for building the mapping
98
+ const dryEmission = await targetPlugin.emit(discovery.items, effectiveTargetRoot, {
99
+ dryRun: true,
100
+ });
101
+ allWarnings.push(...dryEmission.warnings);
102
+ // Build source→target path mapping from the dry-run results
103
+ const mapping = buildMapping(discovery.items, dryEmission.written, effectiveSourceRoot, effectiveTargetRoot);
104
+ // Rewrite content in discovered items
105
+ const rewriteResult = rewriteContent(discovery.items, mapping);
106
+ // Detect orphan references
107
+ const sourcePatterns = PLUGIN_PATH_PATTERNS[options.source];
108
+ if (sourcePatterns) {
109
+ const orphanWarnings = detectOrphans(rewriteResult.items, mapping, sourcePatterns.prefixes, sourcePatterns.extensions);
110
+ allWarnings.push(...orphanWarnings);
111
+ }
112
+ // Pass 2: Real emit with rewritten items
113
+ const emission = await targetPlugin.emit(rewriteResult.items, effectiveTargetRoot, {
114
+ dryRun: options.dryRun,
115
+ });
116
+ // Deduplicate: add only emission warnings not already present from dry-run
117
+ const existingMessages = new Set(allWarnings.map((w) => w.message));
118
+ for (const w of emission.warnings) {
119
+ if (!existingMessages.has(w.message)) {
120
+ allWarnings.push(w);
121
+ }
122
+ }
123
+ return {
124
+ discovered: discovery.items,
125
+ written: emission.written,
126
+ warnings: allWarnings,
127
+ unsupported: emission.unsupported,
128
+ };
129
+ }
130
+ // Standard single-pass emit (no rewriting)
131
+ const emission = await targetPlugin.emit(discovery.items, effectiveTargetRoot, {
74
132
  dryRun: options.dryRun,
75
133
  });
76
134
  return {
77
135
  discovered: discovery.items,
78
136
  written: emission.written,
79
- warnings: [...discovery.warnings, ...emission.warnings],
137
+ warnings: [...allWarnings, ...emission.warnings],
80
138
  unsupported: emission.unsupported,
81
139
  };
82
140
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6DA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACb,OAAO,GAA4B,IAAI,GAAG,EAAE,CAAC;IAErD;;;OAGG;IACH,YAAY,UAAwB,EAAE;QACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,MAAkB;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnD,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,MAAM,EAAE,SAAkB;SAC3B,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,EAAU;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAY;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,OAA0B;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEpD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,uBAAuB;QACvB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE5D,kEAAkE;QAClE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE;YACtE,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,OAAO;YACL,UAAU,EAAE,SAAS,CAAC,KAAK;YAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC;YACvD,WAAW,EAAE,QAAQ,CAAC,WAAW;SAClC,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { AgentCustomization, Warning } from '@a16njs/models';
2
+ import type { WrittenFile } from '@a16njs/models';
3
+ /**
4
+ * A mapping from source-relative paths to target-relative paths.
5
+ * Used to rewrite path references in content during format conversion.
6
+ */
7
+ export type PathMapping = Map<string, string>;
8
+ /**
9
+ * Result of a path rewriting operation.
10
+ */
11
+ export interface RewriteResult {
12
+ /** The items with rewritten content (cloned; originals are not mutated) */
13
+ items: AgentCustomization[];
14
+ /** Count of replacements made across all items */
15
+ replacementCount: number;
16
+ }
17
+ /**
18
+ * Build a mapping from source-relative paths to target-relative paths.
19
+ *
20
+ * Given the discovered items (with sourcePaths relative to sourceRoot)
21
+ * and the written files (with absolute paths under targetRoot), produces
22
+ * a Map where keys are source-relative paths and values are target-relative paths.
23
+ *
24
+ * The mapping is derived from the `sourceItems` array on each WrittenFile,
25
+ * which links each output file back to the source AgentCustomization(s) that
26
+ * produced it. This handles merges, extension changes, and directory flattening
27
+ * naturally because the mapping is derived from actual emit output.
28
+ *
29
+ * @param _discovered - Items discovered from the source plugin (unused directly; mapping comes from written.sourceItems)
30
+ * @param written - Files written (or planned) by the target plugin
31
+ * @param _sourceRoot - Root directory used for discovery (unused; sourcePaths are already relative)
32
+ * @param targetRoot - Root directory used for emission
33
+ * @returns A map of source-relative path to target-relative path
34
+ */
35
+ export declare function buildMapping(_discovered: AgentCustomization[], written: WrittenFile[], _sourceRoot: string, targetRoot: string): PathMapping;
36
+ /**
37
+ * Rewrite file path references in item content.
38
+ *
39
+ * For each item, every occurrence of a mapped source path in the content
40
+ * is replaced with the corresponding target path. Replacements are applied
41
+ * longest-first to prevent partial match corruption (e.g., replacing
42
+ * "foo/bar.mdc.bak" before "foo/bar.mdc").
43
+ *
44
+ * Items are cloned before modification; originals are not mutated.
45
+ *
46
+ * @param items - The items whose content should be rewritten
47
+ * @param mapping - The source-to-target path mapping
48
+ * @returns Cloned items with rewritten content and replacement count
49
+ */
50
+ export declare function rewriteContent(items: AgentCustomization[], mapping: PathMapping): RewriteResult;
51
+ /**
52
+ * Detect orphan path references in item content.
53
+ *
54
+ * An "orphan" is a string in content that looks like it could be a
55
+ * source-format file path (matches known source plugin path prefixes
56
+ * and file extensions) but is NOT present in the mapping (i.e., it
57
+ * wasn't converted).
58
+ *
59
+ * @param items - The items to scan for orphan references
60
+ * @param mapping - The source-to-target path mapping
61
+ * @param sourcePluginPrefixes - Known directory prefixes for the source format
62
+ * (e.g., ['.cursor/rules/', '.cursor/skills/'] for cursor plugin)
63
+ * @param sourceExtensions - Known file extensions for the source format
64
+ * (e.g., ['.mdc', '.md'] for cursor plugin)
65
+ * @returns Warnings about orphan references found
66
+ */
67
+ export declare function detectOrphans(items: AgentCustomization[], mapping: PathMapping, sourcePluginPrefixes: string[], sourceExtensions: string[]): Warning[];
68
+ //# sourceMappingURL=path-rewriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-rewriter.d.ts","sourceRoot":"","sources":["../src/path-rewriter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,kDAAkD;IAClD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,kBAAkB,EAAE,EACjC,OAAO,EAAE,WAAW,EAAE,EACtB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,WAAW,CAoBb;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,kBAAkB,EAAE,EAC3B,OAAO,EAAE,WAAW,GACnB,aAAa,CAgDf;AASD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,EAAE,EAC3B,OAAO,EAAE,WAAW,EACpB,oBAAoB,EAAE,MAAM,EAAE,EAC9B,gBAAgB,EAAE,MAAM,EAAE,GACzB,OAAO,EAAE,CAmCX"}
@@ -0,0 +1,144 @@
1
+ import * as path from 'path';
2
+ import { WarningCode } from '@a16njs/models';
3
+ /**
4
+ * Build a mapping from source-relative paths to target-relative paths.
5
+ *
6
+ * Given the discovered items (with sourcePaths relative to sourceRoot)
7
+ * and the written files (with absolute paths under targetRoot), produces
8
+ * a Map where keys are source-relative paths and values are target-relative paths.
9
+ *
10
+ * The mapping is derived from the `sourceItems` array on each WrittenFile,
11
+ * which links each output file back to the source AgentCustomization(s) that
12
+ * produced it. This handles merges, extension changes, and directory flattening
13
+ * naturally because the mapping is derived from actual emit output.
14
+ *
15
+ * @param _discovered - Items discovered from the source plugin (unused directly; mapping comes from written.sourceItems)
16
+ * @param written - Files written (or planned) by the target plugin
17
+ * @param _sourceRoot - Root directory used for discovery (unused; sourcePaths are already relative)
18
+ * @param targetRoot - Root directory used for emission
19
+ * @returns A map of source-relative path to target-relative path
20
+ */
21
+ export function buildMapping(_discovered, written, _sourceRoot, targetRoot) {
22
+ const mapping = new Map();
23
+ for (const file of written) {
24
+ // Compute target-relative path using POSIX separators for consistency
25
+ const targetRelative = path.relative(targetRoot, file.path).split(path.sep).join('/');
26
+ // Map each source item's sourcePath to this target path
27
+ if (file.sourceItems) {
28
+ for (const sourceItem of file.sourceItems) {
29
+ if (sourceItem.sourcePath) {
30
+ // Normalize to POSIX separators
31
+ const normalizedSourcePath = sourceItem.sourcePath.split(path.sep).join('/');
32
+ mapping.set(normalizedSourcePath, targetRelative);
33
+ }
34
+ }
35
+ }
36
+ }
37
+ return mapping;
38
+ }
39
+ /**
40
+ * Rewrite file path references in item content.
41
+ *
42
+ * For each item, every occurrence of a mapped source path in the content
43
+ * is replaced with the corresponding target path. Replacements are applied
44
+ * longest-first to prevent partial match corruption (e.g., replacing
45
+ * "foo/bar.mdc.bak" before "foo/bar.mdc").
46
+ *
47
+ * Items are cloned before modification; originals are not mutated.
48
+ *
49
+ * @param items - The items whose content should be rewritten
50
+ * @param mapping - The source-to-target path mapping
51
+ * @returns Cloned items with rewritten content and replacement count
52
+ */
53
+ export function rewriteContent(items, mapping) {
54
+ if (mapping.size === 0) {
55
+ // No mapping → return clones with no changes
56
+ return {
57
+ items: items.map((item) => ({ ...item })),
58
+ replacementCount: 0,
59
+ };
60
+ }
61
+ // Sort replacements longest-first to prevent partial match corruption
62
+ const sortedEntries = Array.from(mapping.entries()).sort((a, b) => b[0].length - a[0].length);
63
+ let totalReplacements = 0;
64
+ const rewrittenItems = items.map((item) => {
65
+ // Clone the item (shallow clone is sufficient since we only modify content)
66
+ const clone = { ...item };
67
+ let content = clone.content;
68
+ // NOTE: Replacements are applied sequentially. This is safe because source
69
+ // and target paths use different plugin directory prefixes, so a target path
70
+ // won't match a subsequent source key.
71
+ for (const [sourcePath, targetPath] of sortedEntries) {
72
+ // Count occurrences before replacement
73
+ let count = 0;
74
+ let idx = 0;
75
+ while ((idx = content.indexOf(sourcePath, idx)) !== -1) {
76
+ count++;
77
+ idx += sourcePath.length;
78
+ }
79
+ if (count > 0) {
80
+ // Use split+join for exact string replacement (no regex escaping needed)
81
+ content = content.split(sourcePath).join(targetPath);
82
+ totalReplacements += count;
83
+ }
84
+ }
85
+ clone.content = content;
86
+ return clone;
87
+ });
88
+ return {
89
+ items: rewrittenItems,
90
+ replacementCount: totalReplacements,
91
+ };
92
+ }
93
+ /**
94
+ * Escape a string for use in a RegExp.
95
+ */
96
+ function escapeRegExp(str) {
97
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
98
+ }
99
+ /**
100
+ * Detect orphan path references in item content.
101
+ *
102
+ * An "orphan" is a string in content that looks like it could be a
103
+ * source-format file path (matches known source plugin path prefixes
104
+ * and file extensions) but is NOT present in the mapping (i.e., it
105
+ * wasn't converted).
106
+ *
107
+ * @param items - The items to scan for orphan references
108
+ * @param mapping - The source-to-target path mapping
109
+ * @param sourcePluginPrefixes - Known directory prefixes for the source format
110
+ * (e.g., ['.cursor/rules/', '.cursor/skills/'] for cursor plugin)
111
+ * @param sourceExtensions - Known file extensions for the source format
112
+ * (e.g., ['.mdc', '.md'] for cursor plugin)
113
+ * @returns Warnings about orphan references found
114
+ */
115
+ export function detectOrphans(items, mapping, sourcePluginPrefixes, sourceExtensions) {
116
+ if (sourcePluginPrefixes.length === 0 || sourceExtensions.length === 0) {
117
+ return [];
118
+ }
119
+ const warnings = [];
120
+ const mappedPaths = new Set(mapping.keys());
121
+ const seen = new Set();
122
+ // Build a regex that matches: <prefix><non-whitespace-path><extension>
123
+ // e.g., .cursor/rules/some-file.mdc
124
+ const escapedPrefixes = sourcePluginPrefixes.map(escapeRegExp).join('|');
125
+ const escapedExtensions = sourceExtensions.map(escapeRegExp).join('|');
126
+ const pattern = new RegExp(`(?:${escapedPrefixes})[^\\s)\\]}>,"']+(?:${escapedExtensions})`, 'g');
127
+ for (const item of items) {
128
+ const matches = item.content.matchAll(pattern);
129
+ for (const match of matches) {
130
+ const foundPath = match[0];
131
+ const key = `${item.sourcePath ?? ''}::${foundPath}`;
132
+ if (!mappedPaths.has(foundPath) && !seen.has(key)) {
133
+ seen.add(key);
134
+ warnings.push({
135
+ code: WarningCode.OrphanPathRef,
136
+ message: `Orphan path reference: '${foundPath}' is not in the conversion set`,
137
+ sources: item.sourcePath ? [item.sourcePath] : undefined,
138
+ });
139
+ }
140
+ }
141
+ }
142
+ return warnings;
143
+ }
144
+ //# sourceMappingURL=path-rewriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-rewriter.js","sourceRoot":"","sources":["../src/path-rewriter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a16njs/engine",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Conversion engine for a16n",
5
5
  "license": "AGPL-3.0",
6
6
  "author": "Texarkanine",
@@ -31,14 +31,14 @@
31
31
  "dist"
32
32
  ],
33
33
  "dependencies": {
34
- "@a16njs/models": "0.6.0"
34
+ "@a16njs/models": "0.9.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^20.0.0",
38
38
  "typescript": "^5.4.0",
39
39
  "vitest": "^2.0.0",
40
- "@a16njs/plugin-cursor": "0.7.0",
41
- "@a16njs/plugin-claude": "0.7.0"
40
+ "@a16njs/plugin-cursor": "0.9.0",
41
+ "@a16njs/plugin-claude": "0.9.0"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsc",