Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/core/validate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,86 @@ describe('validate-docs-code', () => {
expect(result).toHaveLength(1);
expect(result[0].refPath).toBe('src/example.ts');
});

it('コードブロック内のCODE_REFを除外すること', () => {
const content = `
# Test Document

<!-- CODE_REF: src/valid.ts:1-10 -->

\`\`\`html
<!-- CODE_REF: src/should-be-ignored.ts:1-5 -->
\`\`\`

<!-- CODE_REF: src/another-valid.ts:10-20 -->
`;

const result = extractCodeRefs(content, '/docs/test.md');

expect(result).toHaveLength(2);
expect(result[0].refPath).toBe('src/valid.ts');
expect(result[1].refPath).toBe('src/another-valid.ts');
});

it('インラインコード内のCODE_REFを除外すること', () => {
const content = `
# Test Document

Use this syntax: \`<!-- CODE_REF: src/inline-ignored.ts:1-5 -->\`

<!-- CODE_REF: src/valid.ts:1-10 -->
`;

const result = extractCodeRefs(content, '/docs/test.md');

expect(result).toHaveLength(1);
expect(result[0].refPath).toBe('src/valid.ts');
});

it('閉じていないコードブロック内のCODE_REFを除外すること', () => {
const content = `
# Test Document

<!-- CODE_REF: src/valid.ts:1-10 -->

\`\`\`html
<!-- CODE_REF: src/in-unclosed-block.ts:1-5 -->
<!-- CODE_REF: src/also-in-unclosed-block.ts:1-5 -->
`;

const result = extractCodeRefs(content, '/docs/test.md');

expect(result).toHaveLength(1);
expect(result[0].refPath).toBe('src/valid.ts');
});

it('複数のコードブロックが混在する場合にCODE_REFを正しく抽出すること', () => {
const content = `
# Documentation

<!-- CODE_REF: src/valid1.ts:1-10 -->

\`\`\`typescript
<!-- CODE_REF: src/ignored1.ts:1-5 -->
const x = 1;
\`\`\`

<!-- CODE_REF: src/valid2.ts:10-20 -->

\`\`\`javascript
<!-- CODE_REF: src/ignored2.ts:5-10 -->
\`\`\`

<!-- CODE_REF: src/valid3.ts:20-30 -->
`;

const result = extractCodeRefs(content, '/docs/test.md');

expect(result).toHaveLength(3);
expect(result[0].refPath).toBe('src/valid1.ts');
expect(result[1].refPath).toBe('src/valid2.ts');
expect(result[2].refPath).toBe('src/valid3.ts');
});
});

describe('validateCodeRef', () => {
Expand Down
32 changes: 25 additions & 7 deletions src/core/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,33 @@
function getCodeBlockRanges(content: string): { start: number; end: number }[] {
const ranges: { start: number; end: number }[] = [];

// Triple backtick code blocks
const codeBlockPattern = /```[\s\S]*?```/g;
// Find all triple backtick positions
const backtickPositions: number[] = [];
const backtickPattern = /```/g;
let match: RegExpExecArray | null;

while ((match = codeBlockPattern.exec(content)) !== null) {
ranges.push({
start: match.index,
end: match.index + match[0].length,
});
while ((match = backtickPattern.exec(content)) !== null) {
backtickPositions.push(match.index);
}

// Pair up backticks: even indices (0, 2, 4...) are opening, odd indices (1, 3, 5...) are closing
for (let i = 0; i < backtickPositions.length; i += 2) {
const start = backtickPositions[i];
const end = backtickPositions[i + 1];

if (end !== undefined) {
// Closed code block
ranges.push({
start,
end: end + 3, // +3 to include the closing ```
});
} else {
// Unclosed code block (odd number of backticks)
ranges.push({
start,
end: content.length,
});
}
}

// Inline code (backticks)
Expand Down Expand Up @@ -136,7 +154,7 @@
* Validate code content
*/
export function validateCodeContent(ref: CodeRef, config?: CodeRefConfig): CodeRefError[] {
const cfg = config || loadConfig();

Check warning on line 157 in src/core/validate.ts

View workflow job for this annotation

GitHub Actions / code-quality (22.x)

Prefer using nullish coalescing operator (`??`) instead of a logical or (`||`), as it is a safer operator
const projectRoot = cfg.projectRoot;
const errors: CodeRefError[] = [];

Expand All @@ -159,7 +177,7 @@
const fileContent = fs.readFileSync(absolutePath, 'utf-8');
const matches = findSymbolInAST(fileContent, absolutePath, {
className: ref.className,
memberName: ref.memberName!,

Check warning on line 180 in src/core/validate.ts

View workflow job for this annotation

GitHub Actions / code-quality (22.x)

Forbidden non-null assertion
});

if (matches.length > 0) {
Expand Down
Loading