Skip to content

Commit da9ce4b

Browse files
patrickerclaude
andcommitted
fix: CJS require() now returns the plugin function directly
The esbuild-generated CJS bundle wrapped the default export in { __esModule: true, default: fn }, so require('remark-code-region') returned a namespace object instead of the plugin function. This broke every CJS config example in the README. Fix: hand-written index.cjs shim that requires the esbuild bundle (index.build.cjs) and re-exports module.exports = fn with named exports attached as properties. Now: const codeRegion = require('remark-code-region') // function const { PRESET_STRIP } = require('remark-code-region') // works Also: added DEFAULT_STRIP_PATTERNS to README exports table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f67aba4 commit da9ce4b

4 files changed

Lines changed: 298 additions & 272 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ user = client.create_user(name="Alice")
285285
| `DEFAULT_REGION_MARKERS` | Default region marker pairs (`#` and `//` comments) |
286286
| `PRESET_MARKERS` | Additional markers: `.css`, `.html`, `.sql` |
287287
| `PRESET_STRIP` | Strip patterns by language: `.python`, `.rust`, `.java`, `.js`, `.cpp`, `.go`, `.markers` |
288+
| `DEFAULT_STRIP_PATTERNS` | All built-in strip patterns (union of all `PRESET_STRIP` groups) |
288289

289290
```js
290291
remarkPlugins: [[codeRegion, {

index.build.cjs

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
var __create = Object.create;
2+
var __defProp = Object.defineProperty;
3+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4+
var __getOwnPropNames = Object.getOwnPropertyNames;
5+
var __getProtoOf = Object.getPrototypeOf;
6+
var __hasOwnProp = Object.prototype.hasOwnProperty;
7+
var __export = (target, all) => {
8+
for (var name in all)
9+
__defProp(target, name, { get: all[name], enumerable: true });
10+
};
11+
var __copyProps = (to, from, except, desc) => {
12+
if (from && typeof from === "object" || typeof from === "function") {
13+
for (let key of __getOwnPropNames(from))
14+
if (!__hasOwnProp.call(to, key) && key !== except)
15+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16+
}
17+
return to;
18+
};
19+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20+
// If the importer is in node compatibility mode or this is not an ESM
21+
// file that has been converted to a CommonJS file using a Babel-
22+
// compatible transform (i.e. "__esModule" has not been set), then set
23+
// "default" to the CommonJS "module.exports" for node compatibility.
24+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25+
mod
26+
));
27+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28+
29+
// index.mjs
30+
var index_exports = {};
31+
__export(index_exports, {
32+
DEFAULT_REGION_MARKERS: () => DEFAULT_REGION_MARKERS,
33+
DEFAULT_STRIP_PATTERNS: () => DEFAULT_STRIP_PATTERNS,
34+
PRESET_MARKERS: () => PRESET_MARKERS,
35+
PRESET_STRIP: () => PRESET_STRIP,
36+
default: () => remarkCodeRegion
37+
});
38+
module.exports = __toCommonJS(index_exports);
39+
var import_unist_util_visit = require("unist-util-visit");
40+
var import_node_fs = __toESM(require("node:fs"), 1);
41+
var import_node_path = __toESM(require("node:path"), 1);
42+
43+
// lib/extract-region.mjs
44+
function extractRegion(content, regionName, filePath, markers) {
45+
const lines = content.split("\n");
46+
let capturing = false;
47+
const captured = [];
48+
let found = false;
49+
for (const line of lines) {
50+
let isStart = false;
51+
let isEnd = false;
52+
for (const { start, end } of markers) {
53+
const startMatch = line.match(start);
54+
if (startMatch && startMatch[1] === regionName) {
55+
isStart = true;
56+
break;
57+
}
58+
const endMatch = line.match(end);
59+
if (endMatch && endMatch[1] === regionName) {
60+
isEnd = true;
61+
break;
62+
}
63+
}
64+
if (isStart) {
65+
capturing = true;
66+
found = true;
67+
continue;
68+
}
69+
if (isEnd) {
70+
capturing = false;
71+
continue;
72+
}
73+
if (capturing) {
74+
captured.push(line);
75+
}
76+
}
77+
if (!found) {
78+
throw new Error(
79+
`remark-code-region: region '${regionName}' not found in ${filePath}`
80+
);
81+
}
82+
if (found && capturing) {
83+
throw new Error(
84+
`remark-code-region: region '${regionName}' in ${filePath} was opened but never closed`
85+
);
86+
}
87+
return captured.join("\n");
88+
}
89+
90+
// lib/strip-asserts.mjs
91+
function stripAsserts(code, patterns) {
92+
return code.split("\n").filter((line) => !patterns.some((pat) => pat.test(line))).join("\n");
93+
}
94+
function dedent(code) {
95+
const lines = code.split("\n");
96+
const nonEmpty = lines.filter((l) => l.trim().length > 0);
97+
if (nonEmpty.length === 0) return code;
98+
const minIndent = Math.min(...nonEmpty.map((l) => l.match(/^(\s*)/)[1].length));
99+
if (minIndent === 0) return code;
100+
return lines.map((l) => l.length >= minIndent ? l.slice(minIndent) : l).join("\n");
101+
}
102+
function cleanCode(code, { noStrip = false, patterns = [] } = {}) {
103+
let result = code;
104+
if (!noStrip && patterns.length > 0) {
105+
result = stripAsserts(result, patterns);
106+
}
107+
result = dedent(result);
108+
result = result.replace(/\n{3,}/g, "\n\n");
109+
return result.trim();
110+
}
111+
112+
// lib/patterns.mjs
113+
var DEFAULT_REGION_MARKERS = [
114+
{
115+
// Python, bash, Ruby, YAML, TOML
116+
start: /^[ \t]*#\s*region:\s*(\S+)\s*$/,
117+
end: /^[ \t]*#\s*endregion:\s*(\S+)\s*$/
118+
},
119+
{
120+
// JavaScript, TypeScript, Rust, Go, Java, C, C++, Swift, Kotlin
121+
start: /^[ \t]*\/\/\s*region:\s*(\S+)\s*$/,
122+
end: /^[ \t]*\/\/\s*endregion:\s*(\S+)\s*$/
123+
}
124+
];
125+
var PRESET_MARKERS = {
126+
/** CSS, HTML (<!-- -->), SCSS, C block comments */
127+
css: {
128+
start: /^[ \t]*\/\*\s*region:\s*(\S+)\s*\*\/\s*$/,
129+
end: /^[ \t]*\/\*\s*endregion:\s*(\S+)\s*\*\/\s*$/
130+
},
131+
/** HTML comments */
132+
html: {
133+
start: /^[ \t]*<!--\s*region:\s*(\S+)\s*-->\s*$/,
134+
end: /^[ \t]*<!--\s*endregion:\s*(\S+)\s*-->\s*$/
135+
},
136+
/** SQL, Lua, Haskell */
137+
sql: {
138+
start: /^[ \t]*--\s*region:\s*(\S+)\s*$/,
139+
end: /^[ \t]*--\s*endregion:\s*(\S+)\s*$/
140+
}
141+
};
142+
var PRESET_STRIP = {
143+
python: [
144+
/^\s*assert\s/
145+
// assert ...
146+
],
147+
rust: [
148+
/^\s*assert_eq!\s*\(/,
149+
// assert_eq!(...)
150+
/^\s*assert_ne!\s*\(/
151+
// assert_ne!(...)
152+
],
153+
java: [
154+
/^\s*assertEquals\s*\(/,
155+
// assertEquals(...)
156+
/^\s*assertNotEquals\s*\(/,
157+
// assertNotEquals(...)
158+
/^\s*assertNull\s*\(/,
159+
// assertNull(...)
160+
/^\s*assertNotNull\s*\(/,
161+
// assertNotNull(...)
162+
/^\s*assertThrows\s*\(/,
163+
// assertThrows(...)
164+
/^\s*assertTrue\s*\(/,
165+
// assertTrue(...)
166+
/^\s*assertFalse\s*\(/
167+
// assertFalse(...)
168+
],
169+
js: [
170+
/^\s*expect\s*\(/
171+
// expect(...)
172+
],
173+
cpp: [
174+
/^\s*ASSERT_/,
175+
// ASSERT_*
176+
/^\s*EXPECT_/
177+
// EXPECT_*
178+
],
179+
go: [
180+
/^\s*if err != nil \{\s*t\.Fatal/
181+
// if err != nil { t.Fatal
182+
],
183+
/** Matches lines ending with // test-only or # test-only — works in any language. */
184+
markers: [
185+
/.*\/\/\s*test-only\s*$/,
186+
// // test-only
187+
/.*#\s*test-only\s*$/
188+
// # test-only
189+
]
190+
};
191+
var DEFAULT_STRIP_PATTERNS = [
192+
...PRESET_STRIP.python,
193+
...PRESET_STRIP.rust,
194+
...PRESET_STRIP.java,
195+
...PRESET_STRIP.js,
196+
...PRESET_STRIP.cpp,
197+
...PRESET_STRIP.go,
198+
...PRESET_STRIP.markers
199+
];
200+
201+
// index.mjs
202+
var REF_REGEX = /reference="([^"]+)"/;
203+
function remarkCodeRegion(options = {}) {
204+
const {
205+
rootDir,
206+
allowOutsideRoot = false,
207+
regionMarkers = DEFAULT_REGION_MARKERS,
208+
strip
209+
} = options;
210+
const stripPatterns = strip === false ? [] : Array.isArray(strip) ? strip : DEFAULT_STRIP_PATTERNS;
211+
return (tree, file) => {
212+
const baseDir = rootDir || file?.cwd || process.cwd();
213+
const resolvedBase = import_node_path.default.resolve(baseDir);
214+
(0, import_unist_util_visit.visit)(tree, "code", (node) => {
215+
if (!node.meta) return;
216+
const refMatch = node.meta.match(REF_REGEX);
217+
if (!refMatch) return;
218+
let ref = refMatch[1];
219+
const qIndex = ref.indexOf("?");
220+
const flags = qIndex >= 0 ? ref.slice(qIndex + 1).split("&") : [];
221+
ref = qIndex >= 0 ? ref.slice(0, qIndex) : ref;
222+
const blockNoStrip = flags.includes("noStrip");
223+
const hashIndex = ref.indexOf("#");
224+
const filePath = hashIndex >= 0 ? ref.slice(0, hashIndex) : ref;
225+
const regionName = hashIndex >= 0 ? ref.slice(hashIndex + 1) : null;
226+
const absPath = import_node_path.default.resolve(baseDir, filePath);
227+
if (!allowOutsideRoot && !absPath.startsWith(resolvedBase + import_node_path.default.sep) && absPath !== resolvedBase) {
228+
const msg = `remark-code-region: '${filePath}' resolves outside the root directory '${resolvedBase}'`;
229+
if (file?.fail) {
230+
file.fail(msg);
231+
return;
232+
}
233+
throw new Error(msg);
234+
}
235+
let content;
236+
try {
237+
content = import_node_fs.default.readFileSync(absPath, "utf-8");
238+
} catch (e) {
239+
const msg = `remark-code-region: cannot read file '${filePath}' (resolved to '${absPath}'): ${e.message}`;
240+
if (file?.fail) {
241+
file.fail(msg);
242+
return;
243+
}
244+
throw new Error(msg);
245+
}
246+
let code;
247+
try {
248+
if (regionName) {
249+
code = extractRegion(content, regionName, filePath, regionMarkers);
250+
} else {
251+
code = content;
252+
}
253+
} catch (e) {
254+
if (file?.fail) {
255+
file.fail(e.message);
256+
return;
257+
}
258+
throw e;
259+
}
260+
code = cleanCode(code, {
261+
noStrip: blockNoStrip || strip === false,
262+
patterns: stripPatterns
263+
});
264+
node.value = code;
265+
node.meta = node.meta.replace(/\s*reference="[^"]*"/, "").trim() || null;
266+
});
267+
};
268+
}
269+
// Annotate the CommonJS export names for ESM import in node:
270+
0 && (module.exports = {
271+
DEFAULT_REGION_MARKERS,
272+
DEFAULT_STRIP_PATTERNS,
273+
PRESET_MARKERS,
274+
PRESET_STRIP
275+
});

0 commit comments

Comments
 (0)