Skip to content

Commit dc90590

Browse files
update readme
1 parent b7adbc4 commit dc90590

File tree

1 file changed

+51
-13
lines changed
  • scripts/prebuild/mdx-transforms/exclude-content

1 file changed

+51
-13
lines changed

scripts/prebuild/mdx-transforms/exclude-content/README.md

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ exclude-content/
7979

8080
1. **Early Return**: If `productConfig.supportsExclusionDirectives` is false, skip processing
8181
2. **Single AST Pass**: Parse all directive blocks in one traversal (`parseDirectiveBlocks`)
82+
- Stores **node references** (not line numbers) for BEGIN/END comments
83+
- Returns blocks with `{ startNode, endNode, startLine, endLine, content }`
8284
3. **Explicit Routing**: For each block, route to appropriate processor:
8385
```javascript
8486
const directiveProcessingFuncs = {
@@ -139,26 +141,60 @@ if (!isGlobalPartial) {
139141

140142
## Implementation Details
141143

144+
### parseDirectiveBlocks() Function
145+
146+
Parses all directive blocks from the AST in a single pass and returns block objects containing:
147+
148+
- `startNode`: Reference to the BEGIN comment node
149+
- `endNode`: Reference to the END comment node
150+
- `startLine`: Line number where BEGIN comment appears (for error messages)
151+
- `endLine`: Line number where END comment appears (for error messages)
152+
- `content`: The directive content (e.g., "TFEnterprise:only name:project-remote-state")
153+
154+
**Why node references instead of line numbers?**
155+
156+
When multiple partials are included in a file, each partial's AST nodes retain their original line numbers from the source file. This means multiple partials can have overlapping line ranges (e.g., both starting at line 1). Using actual node object references ensures we match the exact BEGIN/END pair, not just any nodes at those line numbers.
157+
142158
### removeNodesInRange() Function
143159

144-
This is the core function that removes content between BEGIN/END comments. Key behaviors:
160+
This is the core function that removes content between BEGIN/END comments using node identity matching.
161+
162+
**Key Algorithm:**
163+
```javascript
164+
// Check if this is the START node
165+
if (node === startNode) {
166+
insideRange = true
167+
nodesToRemove.add(node)
168+
}
169+
170+
// Check if this is the END node
171+
if (node === endNode) {
172+
nodesToRemove.add(node)
173+
insideRange = false
174+
}
175+
176+
// If inside range, mark for removal
177+
if (insideRange) {
178+
nodesToRemove.add(node)
179+
}
180+
```
181+
182+
**Why node identity matching?**
183+
184+
Using `node === startNode` comparison ensures we match the exact node objects that were identified during parsing. This is critical when:
185+
- Multiple partials contain the same directive name (e.g., both have `TFEnterprise:only name:project-remote-state`)
186+
- Partial AST nodes have overlapping line numbers from their source files
187+
- Same directive appears multiple times in sequence
145188

146189
**Handles Partial Content:**
147-
- Nodes from included partials may have position data from the partial file (e.g., lines 1-20), not the parent file (e.g., lines 37-45)
148-
- Tracks an `insideRange` state: once a BEGIN comment is found, all subsequent nodes are removed until the END comment
149-
- Nodes without position data or with mismatched position data are treated as partial content and removed when `insideRange` is true
190+
- Once BEGIN node is found, all subsequent nodes are marked for removal until END node
191+
- Recurses into children to handle nested structures
150192

151193
**Recurse-First Algorithm:**
152194
- Processes children BEFORE deciding parent's fate
153195
- Finds nested END comments even when parent is marked for removal
154196
- Parent nodes that contained removed children are also removed (if empty)
155197

156-
**Critical Edge Case - Same-Line Directive Comments:**
157-
- When two directive blocks have comments on the same line (e.g., `<!-- END: TFC:only --> <!-- BEGIN: TFEnterprise:only -->`), the function tracks `lastEndLine`
158-
- After finding an END comment, it skips any BEGIN comments on that same line
159-
- This prevents starting a new unrelated range removal operation
160-
- **Why**: `removeNodesInRange()` is designed to remove ONE specific range, not multiple overlapping ranges
161-
162198
**Helper Function:**
163199
```javascript
164200
function isCommentNode(node) {
@@ -208,7 +244,7 @@ export function processConsulBlock(directive, block, tree, options) {
208244
if (directive === 'only') {
209245
// Consul:only kept ONLY in consul, removed elsewhere
210246
if (repoSlug !== 'consul') {
211-
removeNodesInRange(tree, block.start, block.end)
247+
removeNodesInRange(tree, block)
212248
}
213249
return
214250
}
@@ -217,9 +253,11 @@ export function processConsulBlock(directive, block, tree, options) {
217253
const versionMatch = directive.match(/^(<=|>=|<|>|=)v(\d+\.\d+\.x)$/)
218254
if (versionMatch) {
219255
// Process version comparison...
256+
// If content should be removed:
257+
// removeNodesInRange(tree, block)
220258
}
221259

222-
throw new Error(`Invalid Consul directive: "${directive}" at lines ${block.start}-${block.end}`)
260+
throw new Error(`Invalid Consul directive: "${directive}" at lines ${block.startLine}-${block.endLine}`)
223261
}
224262
```
225263

@@ -279,7 +317,7 @@ Coverage:
279317
- "Only" directive processing (Terraform products)
280318
- Cross-product behavior
281319
- Error handling for malformed directives
282-
- Edge cases (nested comments, indented comments, same-line directives)
320+
- Edge cases (nested comments, indented comments, multiple partials with same directive name)
283321

284322
### Integration Tests
285323

0 commit comments

Comments
 (0)