catport 1.0.1 → 1.0.3

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 CHANGED
@@ -6,7 +6,7 @@
6
6
  <a href="https://www.npmjs.com/package/catport">
7
7
  <img src="https://img.shields.io/npm/v/catport?style=flat-square&color=000" alt="npm" />
8
8
  </a>
9
- <a href="./LICENSE">
9
+ <a href="https://github.com/Jelodar/catport/blob/main/LICENSE">
10
10
  <img src="https://img.shields.io/github/license/Jelodar/catport?style=flat-square&color=000" alt="license" />
11
11
  </a>
12
12
  <img src="https://img.shields.io/badge/dependencies-0-000?style=flat-square" alt="zero dependencies" />
@@ -407,7 +407,7 @@ Use `--unsafe` (`-U`) **only** when you fully trust the source (e.g., internal a
407
407
 
408
408
  ## Contributing
409
409
 
410
- We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on the architectural philosophy (Unix-style pipes, zero-deps) and coding standards.
410
+ We welcome contributions! Please see [CONTRIBUTING.md](https://github.com/Jelodar/catport/blob/main/CONTRIBUTING.md) for details on the architectural philosophy (Unix-style pipes, zero-deps) and coding standards.
411
411
 
412
412
  ## License
413
413
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "catport",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A high-performance, minimalist, and dependency-free CLI tool for bundling file contents or extracting files from a bundle.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -2,7 +2,7 @@ import { DEFAULT_IGNORES } from './ignores.js';
2
2
 
3
3
  export const APP = {
4
4
  NAME: 'catport',
5
- VERSION: '1.0.1',
5
+ VERSION: '1.0.3',
6
6
  DESC: 'Deterministic filesystem serializer for LLM contexts'
7
7
  };
8
8
 
@@ -67,20 +67,25 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
67
67
  },
68
68
 
69
69
  parse: (text, logger) => {
70
- // Find the last occurrence of INSTRUCTION_MARKER to avoid splitting on markers inside file content
71
- const lastInstructionIdx = text.lastIndexOf(INSTRUCTION_MARKER);
72
- const processText = lastInstructionIdx !== -1 ? text.slice(0, lastInstructionIdx) : text;
73
-
74
70
  const files = [];
75
71
  let pos = 0;
76
72
 
77
73
  while (true) {
74
+ // Check if we hit the instructions block before the next file
75
+ const instrIdx = text.indexOf(INSTRUCTION_MARKER, pos);
76
+
78
77
  FILE_MARKER_RE.lastIndex = pos;
79
- const markerMatch = FILE_MARKER_RE.exec(processText);
78
+ const markerMatch = FILE_MARKER_RE.exec(text);
79
+
80
80
  if (!markerMatch) {
81
81
  break;
82
82
  }
83
83
 
84
+ // If instructions appear before the next file marker, we are done
85
+ if (instrIdx !== -1 && instrIdx < markerMatch.index) {
86
+ break;
87
+ }
88
+
84
89
  const rawPath = markerMatch[1].trim()
85
90
  .replace(/[:'"`]*$/, '') // trailing : or quotes
86
91
  .replace(/\s*\(.*\)$/, '') // (updated), (copy), …
@@ -97,7 +102,7 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
97
102
  }
98
103
 
99
104
  const afterMarkerPos = markerMatch.index + markerMatch[0].length;
100
- const rest = processText.slice(afterMarkerPos);
105
+ const rest = text.slice(afterMarkerPos);
101
106
 
102
107
  const openFenceMatch = rest.match(/^([ \t]*)(`{3,}|~{3,})/m);
103
108
  if (!openFenceMatch) {
@@ -119,7 +124,7 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
119
124
  const langLineMatch = afterFence.match(/^(.*\r?\n)/);
120
125
  const codeBlockStart = fenceStartPos + (langLineMatch?.[0].length ?? 0);
121
126
 
122
- const closeMatch = fenceRE.exec(processText.slice(codeBlockStart));
127
+ const closeMatch = fenceRE.exec(text.slice(codeBlockStart));
123
128
  if (!closeMatch) {
124
129
  if (logger) {
125
130
  logger.warn(`Skipping file "${path}": Code block not closed (reached end of input).`);
@@ -131,7 +136,7 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
131
136
 
132
137
  const closePosAbs = codeBlockStart + closeMatch.index + closeMatch[0].length;
133
138
 
134
- let content = processText.slice(codeBlockStart, codeBlockStart + closeMatch.index);
139
+ let content = text.slice(codeBlockStart, codeBlockStart + closeMatch.index);
135
140
 
136
141
  if (indent) {
137
142
  const indentRE = new RegExp(`^${indent}`, 'gm');
@@ -143,7 +148,7 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
143
148
  .replace(/\r/g, '\n')
144
149
  .trimEnd();
145
150
 
146
- if (content.length > 0 || processText.slice(codeBlockStart, codeBlockStart + closeMatch.index).trim().length > 0) {
151
+ if (content.length > 0 || text.slice(codeBlockStart, codeBlockStart + closeMatch.index).trim().length > 0) {
147
152
  files.push({ path, content });
148
153
  } else {
149
154
  if (logger) {
@@ -153,7 +158,7 @@ Only output "${FILE_MARKER} <path>" followed by a fenced code block. Nothing els
153
158
 
154
159
  pos = closePosAbs;
155
160
 
156
- const trailing = processText.slice(pos).match(/^\r?\n/);
161
+ const trailing = text.slice(pos).match(/^\r?\n/);
157
162
  if (trailing) {
158
163
  pos += trailing[0].length;
159
164
  }