@bfra.me/doc-sync 0.1.0 → 0.1.1
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/lib/chunk-45NROJIG.js +327 -0
- package/lib/chunk-DRBRT57F.js +1 -0
- package/lib/chunk-GZ2MP3VN.js +261 -0
- package/lib/{chunk-G5KKGJYO.js → chunk-LOB73H77.js} +18 -260
- package/lib/{chunk-DR6UG237.js → chunk-NC7YTZAL.js} +20 -334
- package/lib/chunk-SQSYXPIF.js +1 -0
- package/lib/cli/index.js +4 -2
- package/lib/generators/index.d.ts +1 -3
- package/lib/generators/index.js +2 -1
- package/lib/index.d.ts +7 -139
- package/lib/index.js +146 -13
- package/lib/orchestrator/index.d.ts +82 -0
- package/lib/orchestrator/index.js +27 -0
- package/lib/utils/index.d.ts +140 -0
- package/lib/utils/index.js +24 -0
- package/lib/watcher/index.d.ts +62 -0
- package/lib/watcher/index.js +25 -0
- package/package.json +17 -2
- package/src/generators/mdx-generator.ts +18 -17
- package/src/index.ts +82 -0
- package/src/utils/safe-patterns.ts +6 -2
package/lib/index.js
CHANGED
|
@@ -1,23 +1,14 @@
|
|
|
1
|
+
import "./chunk-SQSYXPIF.js";
|
|
1
2
|
import {
|
|
2
|
-
categorizeFile,
|
|
3
|
-
consolidateEvents,
|
|
4
|
-
createDocChangeDetector,
|
|
5
|
-
createDocDebouncer,
|
|
6
|
-
createDocWatcher,
|
|
7
3
|
createPackageScanner,
|
|
8
4
|
createSyncOrchestrator,
|
|
9
5
|
createValidationPipeline,
|
|
10
|
-
deduplicateEvents,
|
|
11
|
-
determineRegenerationScope,
|
|
12
|
-
filterDocumentationChanges,
|
|
13
6
|
filterPackagesByPattern,
|
|
14
|
-
groupChangesByPackage,
|
|
15
7
|
groupPackagesByScope,
|
|
16
|
-
hasAnyFileChanged,
|
|
17
8
|
isValidFilePath,
|
|
18
9
|
validateContentString,
|
|
19
10
|
validateDocument
|
|
20
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NC7YTZAL.js";
|
|
21
12
|
import {
|
|
22
13
|
cleanCodeExample,
|
|
23
14
|
createBadge,
|
|
@@ -54,13 +45,99 @@ import {
|
|
|
54
45
|
validateMarkerPairing,
|
|
55
46
|
wrapAutoSection,
|
|
56
47
|
wrapManualSection
|
|
57
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-LOB73H77.js";
|
|
58
49
|
import {
|
|
59
50
|
SENTINEL_MARKERS
|
|
60
51
|
} from "./chunk-ROLA7SBB.js";
|
|
61
|
-
import
|
|
52
|
+
import {
|
|
53
|
+
analyzePublicAPI,
|
|
54
|
+
analyzeTypeScriptContent,
|
|
55
|
+
analyzeTypeScriptFile,
|
|
56
|
+
assertPackageAPI,
|
|
57
|
+
assertPackageInfo,
|
|
58
|
+
assertParseError,
|
|
59
|
+
buildDocSlug,
|
|
60
|
+
createProject,
|
|
61
|
+
extractDocsConfig,
|
|
62
|
+
extractExportedFunctions,
|
|
63
|
+
extractExportedTypes,
|
|
64
|
+
extractJSDocInfo,
|
|
65
|
+
extractPackageAPI,
|
|
66
|
+
extractReExports,
|
|
67
|
+
findEntryPoint,
|
|
68
|
+
findExportedSymbols,
|
|
69
|
+
findReadmePath,
|
|
70
|
+
findSection,
|
|
71
|
+
flattenSections,
|
|
72
|
+
getExportedSymbolInfo,
|
|
73
|
+
getExportsByKind,
|
|
74
|
+
getPackageScope,
|
|
75
|
+
getSectionsByLevel,
|
|
76
|
+
getTableOfContents,
|
|
77
|
+
getUnscopedName,
|
|
78
|
+
hasJSDoc,
|
|
79
|
+
isDocConfigSource,
|
|
80
|
+
isExportedFunction,
|
|
81
|
+
isExportedType,
|
|
82
|
+
isJSDocInfo,
|
|
83
|
+
isJSDocParam,
|
|
84
|
+
isJSDocTag,
|
|
85
|
+
isMDXFrontmatter,
|
|
86
|
+
isPackageAPI,
|
|
87
|
+
isPackageInfo,
|
|
88
|
+
isParseError,
|
|
89
|
+
isReExport,
|
|
90
|
+
isReadmeContent,
|
|
91
|
+
isReadmeSection,
|
|
92
|
+
isSafeContent,
|
|
93
|
+
isSafeFilePath,
|
|
94
|
+
isSymbolExported,
|
|
95
|
+
isSyncError,
|
|
96
|
+
isValidHeadingLevel,
|
|
97
|
+
isValidPackageName,
|
|
98
|
+
isValidSemver,
|
|
99
|
+
parseJSDoc,
|
|
100
|
+
parsePackageComplete,
|
|
101
|
+
parsePackageJson,
|
|
102
|
+
parsePackageJsonContent,
|
|
103
|
+
parseReadme,
|
|
104
|
+
parseReadmeFile,
|
|
105
|
+
parseSourceContent,
|
|
106
|
+
parseSourceFile
|
|
107
|
+
} from "./chunk-6NKAJT2M.js";
|
|
108
|
+
import "./chunk-DRBRT57F.js";
|
|
109
|
+
import {
|
|
110
|
+
createHeadingPattern,
|
|
111
|
+
extractCodeBlocks,
|
|
112
|
+
findEmptyMarkdownLinks,
|
|
113
|
+
hasComponent,
|
|
114
|
+
parseJSXAttributes,
|
|
115
|
+
parseJSXTags,
|
|
116
|
+
sanitizeAttribute,
|
|
117
|
+
sanitizeForMDX,
|
|
118
|
+
sanitizeJSXTag
|
|
119
|
+
} from "./chunk-GZ2MP3VN.js";
|
|
120
|
+
import {
|
|
121
|
+
categorizeFile,
|
|
122
|
+
consolidateEvents,
|
|
123
|
+
createDocChangeDetector,
|
|
124
|
+
createDocDebouncer,
|
|
125
|
+
createDocWatcher,
|
|
126
|
+
deduplicateEvents,
|
|
127
|
+
determineRegenerationScope,
|
|
128
|
+
filterDocumentationChanges,
|
|
129
|
+
groupChangesByPackage,
|
|
130
|
+
hasAnyFileChanged
|
|
131
|
+
} from "./chunk-45NROJIG.js";
|
|
62
132
|
export {
|
|
63
133
|
SENTINEL_MARKERS,
|
|
134
|
+
analyzePublicAPI,
|
|
135
|
+
analyzeTypeScriptContent,
|
|
136
|
+
analyzeTypeScriptFile,
|
|
137
|
+
assertPackageAPI,
|
|
138
|
+
assertPackageInfo,
|
|
139
|
+
assertParseError,
|
|
140
|
+
buildDocSlug,
|
|
64
141
|
categorizeFile,
|
|
65
142
|
cleanCodeExample,
|
|
66
143
|
consolidateEvents,
|
|
@@ -71,7 +148,9 @@ export {
|
|
|
71
148
|
createDocChangeDetector,
|
|
72
149
|
createDocDebouncer,
|
|
73
150
|
createDocWatcher,
|
|
151
|
+
createHeadingPattern,
|
|
74
152
|
createPackageScanner,
|
|
153
|
+
createProject,
|
|
75
154
|
createSyncOrchestrator,
|
|
76
155
|
createTabs,
|
|
77
156
|
createValidationPipeline,
|
|
@@ -79,9 +158,22 @@ export {
|
|
|
79
158
|
detectLanguage,
|
|
80
159
|
determineRegenerationScope,
|
|
81
160
|
extractAutoSections,
|
|
161
|
+
extractCodeBlocks,
|
|
162
|
+
extractDocsConfig,
|
|
163
|
+
extractExportedFunctions,
|
|
164
|
+
extractExportedTypes,
|
|
165
|
+
extractJSDocInfo,
|
|
82
166
|
extractManualSections,
|
|
167
|
+
extractPackageAPI,
|
|
168
|
+
extractReExports,
|
|
83
169
|
filterDocumentationChanges,
|
|
84
170
|
filterPackagesByPattern,
|
|
171
|
+
findEmptyMarkdownLinks,
|
|
172
|
+
findEntryPoint,
|
|
173
|
+
findExportedSymbols,
|
|
174
|
+
findReadmePath,
|
|
175
|
+
findSection,
|
|
176
|
+
flattenSections,
|
|
85
177
|
formatCodeBlock,
|
|
86
178
|
formatCodeExamples,
|
|
87
179
|
formatFunctionExamples,
|
|
@@ -94,17 +186,58 @@ export {
|
|
|
94
186
|
generateFrontmatter,
|
|
95
187
|
generateInstallTabs,
|
|
96
188
|
generateMDXDocument,
|
|
189
|
+
getExportedSymbolInfo,
|
|
190
|
+
getExportsByKind,
|
|
191
|
+
getPackageScope,
|
|
192
|
+
getSectionsByLevel,
|
|
193
|
+
getTableOfContents,
|
|
194
|
+
getUnscopedName,
|
|
97
195
|
groupChangesByPackage,
|
|
98
196
|
groupExamplesByCategory,
|
|
99
197
|
groupPackagesByScope,
|
|
100
198
|
hasAnyFileChanged,
|
|
101
199
|
hasAutoContent,
|
|
200
|
+
hasComponent,
|
|
201
|
+
hasJSDoc,
|
|
102
202
|
hasManualContent,
|
|
203
|
+
isDocConfigSource,
|
|
204
|
+
isExportedFunction,
|
|
205
|
+
isExportedType,
|
|
206
|
+
isJSDocInfo,
|
|
207
|
+
isJSDocParam,
|
|
208
|
+
isJSDocTag,
|
|
209
|
+
isMDXFrontmatter,
|
|
210
|
+
isPackageAPI,
|
|
211
|
+
isPackageInfo,
|
|
212
|
+
isParseError,
|
|
213
|
+
isReExport,
|
|
214
|
+
isReadmeContent,
|
|
215
|
+
isReadmeSection,
|
|
216
|
+
isSafeContent,
|
|
217
|
+
isSafeFilePath,
|
|
218
|
+
isSymbolExported,
|
|
219
|
+
isSyncError,
|
|
103
220
|
isValidFilePath,
|
|
221
|
+
isValidHeadingLevel,
|
|
222
|
+
isValidPackageName,
|
|
223
|
+
isValidSemver,
|
|
104
224
|
mapToStarlightComponents,
|
|
105
225
|
mergeContent,
|
|
106
226
|
parseFrontmatter,
|
|
227
|
+
parseJSDoc,
|
|
228
|
+
parseJSXAttributes,
|
|
229
|
+
parseJSXTags,
|
|
230
|
+
parsePackageComplete,
|
|
231
|
+
parsePackageJson,
|
|
232
|
+
parsePackageJsonContent,
|
|
233
|
+
parseReadme,
|
|
234
|
+
parseReadmeFile,
|
|
235
|
+
parseSourceContent,
|
|
236
|
+
parseSourceFile,
|
|
237
|
+
sanitizeAttribute,
|
|
107
238
|
sanitizeContent,
|
|
239
|
+
sanitizeForMDX,
|
|
240
|
+
sanitizeJSXTag,
|
|
108
241
|
sanitizeTextContent,
|
|
109
242
|
stringifyFrontmatter,
|
|
110
243
|
stripSentinelMarkers,
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Result } from '@bfra.me/es/result';
|
|
2
|
+
import { PackageInfo, ReadmeContent, PackageAPI, SyncError, DocConfig, SyncSummary, FileChangeEvent, MDXDocument } from '../types.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
interface PackageScannerOptions {
|
|
6
|
+
readonly rootDir: string;
|
|
7
|
+
readonly includePatterns?: readonly string[];
|
|
8
|
+
readonly excludePackages?: readonly string[];
|
|
9
|
+
readonly parseSourceFiles?: boolean;
|
|
10
|
+
readonly parseReadme?: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface ScannedPackage {
|
|
13
|
+
readonly info: PackageInfo;
|
|
14
|
+
readonly readme?: ReadmeContent;
|
|
15
|
+
readonly api?: PackageAPI;
|
|
16
|
+
readonly sourceFiles: readonly string[];
|
|
17
|
+
readonly needsDocumentation: boolean;
|
|
18
|
+
readonly existingDocPath?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ScanResult {
|
|
21
|
+
readonly packages: readonly ScannedPackage[];
|
|
22
|
+
readonly packagesNeedingDocs: readonly ScannedPackage[];
|
|
23
|
+
readonly errors: readonly SyncError[];
|
|
24
|
+
readonly durationMs: number;
|
|
25
|
+
}
|
|
26
|
+
declare function createPackageScanner(options: PackageScannerOptions): {
|
|
27
|
+
readonly scan: () => Promise<ScanResult>;
|
|
28
|
+
readonly scanPackage: (packagePath: string) => Promise<Result<ScannedPackage, SyncError>>;
|
|
29
|
+
};
|
|
30
|
+
declare function filterPackagesByPattern(packages: readonly ScannedPackage[], pattern: string): ScannedPackage[];
|
|
31
|
+
declare function groupPackagesByScope(packages: readonly ScannedPackage[]): Map<string, ScannedPackage[]>;
|
|
32
|
+
|
|
33
|
+
interface SyncOrchestratorOptions {
|
|
34
|
+
readonly config: DocConfig;
|
|
35
|
+
readonly dryRun?: boolean;
|
|
36
|
+
readonly verbose?: boolean;
|
|
37
|
+
readonly onProgress?: (message: string) => void;
|
|
38
|
+
readonly onError?: (error: SyncError) => void;
|
|
39
|
+
}
|
|
40
|
+
interface SyncOrchestrator {
|
|
41
|
+
readonly syncAll: () => Promise<SyncSummary>;
|
|
42
|
+
readonly syncPackages: (packageNames: readonly string[]) => Promise<SyncSummary>;
|
|
43
|
+
readonly handleChanges: (events: readonly FileChangeEvent[]) => Promise<SyncSummary>;
|
|
44
|
+
readonly startWatching: () => Promise<void>;
|
|
45
|
+
readonly stopWatching: () => Promise<void>;
|
|
46
|
+
readonly isWatching: () => boolean;
|
|
47
|
+
}
|
|
48
|
+
declare function createSyncOrchestrator(options: SyncOrchestratorOptions): SyncOrchestrator;
|
|
49
|
+
/** Prevents directory traversal attacks (SEC-002) */
|
|
50
|
+
declare function isValidFilePath(filePath: string, rootDir: string): boolean;
|
|
51
|
+
|
|
52
|
+
interface ValidationResult {
|
|
53
|
+
readonly valid: boolean;
|
|
54
|
+
readonly errors: readonly ValidationError[];
|
|
55
|
+
readonly warnings: readonly ValidationWarning[];
|
|
56
|
+
}
|
|
57
|
+
interface ValidationError {
|
|
58
|
+
readonly type: 'syntax' | 'frontmatter' | 'component' | 'content';
|
|
59
|
+
readonly message: string;
|
|
60
|
+
readonly line?: number;
|
|
61
|
+
readonly column?: number;
|
|
62
|
+
}
|
|
63
|
+
interface ValidationWarning {
|
|
64
|
+
readonly type: 'deprecation' | 'recommendation' | 'compatibility';
|
|
65
|
+
readonly message: string;
|
|
66
|
+
readonly line?: number;
|
|
67
|
+
}
|
|
68
|
+
interface ValidationPipelineOptions {
|
|
69
|
+
readonly validateFrontmatter?: boolean;
|
|
70
|
+
readonly validateComponents?: boolean;
|
|
71
|
+
readonly validateContent?: boolean;
|
|
72
|
+
readonly strict?: boolean;
|
|
73
|
+
}
|
|
74
|
+
declare function createValidationPipeline(options?: ValidationPipelineOptions): {
|
|
75
|
+
readonly validate: (doc: MDXDocument) => ValidationResult;
|
|
76
|
+
readonly validateContent: (content: string) => ValidationResult;
|
|
77
|
+
readonly validateMultiple: (docs: readonly MDXDocument[]) => Result<Map<string, ValidationResult>, SyncError>;
|
|
78
|
+
};
|
|
79
|
+
declare function validateDocument(doc: MDXDocument, options?: ValidationPipelineOptions): Result<MDXDocument, SyncError>;
|
|
80
|
+
declare function validateContentString(content: string, options?: ValidationPipelineOptions): Result<string, SyncError>;
|
|
81
|
+
|
|
82
|
+
export { type PackageScannerOptions, type ScanResult, type ScannedPackage, type SyncOrchestrator, type SyncOrchestratorOptions, type ValidationError, type ValidationPipelineOptions, type ValidationResult, type ValidationWarning, createPackageScanner, createSyncOrchestrator, createValidationPipeline, filterPackagesByPattern, groupPackagesByScope, isValidFilePath, validateContentString, validateDocument };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import "../chunk-SQSYXPIF.js";
|
|
2
|
+
import {
|
|
3
|
+
createPackageScanner,
|
|
4
|
+
createSyncOrchestrator,
|
|
5
|
+
createValidationPipeline,
|
|
6
|
+
filterPackagesByPattern,
|
|
7
|
+
groupPackagesByScope,
|
|
8
|
+
isValidFilePath,
|
|
9
|
+
validateContentString,
|
|
10
|
+
validateDocument
|
|
11
|
+
} from "../chunk-NC7YTZAL.js";
|
|
12
|
+
import "../chunk-LOB73H77.js";
|
|
13
|
+
import "../chunk-ROLA7SBB.js";
|
|
14
|
+
import "../chunk-6NKAJT2M.js";
|
|
15
|
+
import "../chunk-GZ2MP3VN.js";
|
|
16
|
+
import "../chunk-45NROJIG.js";
|
|
17
|
+
export {
|
|
18
|
+
createPackageScanner,
|
|
19
|
+
createSyncOrchestrator,
|
|
20
|
+
createValidationPipeline,
|
|
21
|
+
filterPackagesByPattern,
|
|
22
|
+
groupPackagesByScope,
|
|
23
|
+
isValidFilePath,
|
|
24
|
+
validateContentString,
|
|
25
|
+
validateDocument
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bfra.me/doc-sync/utils/safe-patterns - Safe regex patterns and utilities for MDX/HTML parsing
|
|
3
|
+
* All patterns are designed to prevent ReDoS attacks
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Create safe heading pattern for specific level
|
|
7
|
+
* Uses explicit character class instead of greedy `.+` to prevent ReDoS
|
|
8
|
+
*
|
|
9
|
+
* @param level - Heading level (1-6)
|
|
10
|
+
* @returns Safe regex pattern for the heading level
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const h2Pattern = createHeadingPattern(2)
|
|
15
|
+
* const matches = content.match(h2Pattern)
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
declare function createHeadingPattern(level: number): RegExp;
|
|
19
|
+
/**
|
|
20
|
+
* Check if content contains a specific JSX component
|
|
21
|
+
* Uses a safe pattern that avoids catastrophic backtracking
|
|
22
|
+
*
|
|
23
|
+
* @param content - The MDX/HTML content to search
|
|
24
|
+
* @param componentName - Name of the component to find (e.g., 'Card', 'Badge')
|
|
25
|
+
* @returns True if the component is found
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const hasCard = hasComponent(content, 'Card')
|
|
30
|
+
* const hasCardGrid = hasComponent(content, 'CardGrid')
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function hasComponent(content: string, componentName: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Extract code blocks and inline code from markdown content using unified/remark (safe, no regex)
|
|
36
|
+
* This approach uses AST parsing instead of regex to avoid ReDoS vulnerabilities
|
|
37
|
+
*
|
|
38
|
+
* @param content - The markdown content to parse
|
|
39
|
+
* @returns Array of code block strings (fenced blocks with backticks, inline code with backticks)
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const blocks = extractCodeBlocks(content)
|
|
44
|
+
* for (const block of blocks) {
|
|
45
|
+
* console.log(block)
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare function extractCodeBlocks(content: string): readonly string[];
|
|
50
|
+
/**
|
|
51
|
+
* Parse JSX tags from content using a safe, non-backtracking approach.
|
|
52
|
+
* Uses a state machine instead of regex to prevent ReDoS.
|
|
53
|
+
*
|
|
54
|
+
* @param content - The MDX/HTML content to parse
|
|
55
|
+
* @returns Array of matched JSX tags with their positions
|
|
56
|
+
*/
|
|
57
|
+
declare function parseJSXTags(content: string): readonly {
|
|
58
|
+
tag: string;
|
|
59
|
+
index: number;
|
|
60
|
+
isClosing: boolean;
|
|
61
|
+
isSelfClosing: boolean;
|
|
62
|
+
}[];
|
|
63
|
+
/**
|
|
64
|
+
* Find empty markdown links in content using safe parsing.
|
|
65
|
+
* Uses indexOf-based scanning instead of regex to prevent ReDoS.
|
|
66
|
+
*
|
|
67
|
+
* @param content - The markdown content to check
|
|
68
|
+
* @returns Array of positions where empty links were found
|
|
69
|
+
*/
|
|
70
|
+
declare function findEmptyMarkdownLinks(content: string): readonly number[];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @bfra.me/doc-sync/utils/sanitization - Sanitization utilities for MDX content
|
|
74
|
+
* Provides comprehensive XSS prevention for user-generated content
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Sanitize HTML content for MDX context
|
|
78
|
+
* Escapes all HTML entities and JSX curly braces to prevent XSS
|
|
79
|
+
*
|
|
80
|
+
* @param content - The content to sanitize
|
|
81
|
+
* @returns Sanitized content safe for MDX rendering
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const safe = sanitizeForMDX('<script>alert("xss")</script>')
|
|
86
|
+
* // Returns: '<script>alert("xss")</script>'
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function sanitizeForMDX(content: string): string;
|
|
90
|
+
/**
|
|
91
|
+
* Sanitize value for use in HTML/JSX attribute
|
|
92
|
+
* Uses escape-html library for proper attribute encoding
|
|
93
|
+
*
|
|
94
|
+
* @param value - The attribute value to sanitize
|
|
95
|
+
* @returns Sanitized value safe for attribute context
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const safe = sanitizeAttribute('value" onload="alert(1)')
|
|
100
|
+
* // Returns: 'value" onload="alert(1)'
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function sanitizeAttribute(value: string): string;
|
|
104
|
+
/**
|
|
105
|
+
* JSX attribute parsed from a tag
|
|
106
|
+
*/
|
|
107
|
+
interface JSXAttribute {
|
|
108
|
+
readonly name: string;
|
|
109
|
+
readonly value: string | null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parse JSX tag attributes safely without using complex regex
|
|
113
|
+
* Uses a simple state machine approach to avoid ReDoS vulnerabilities
|
|
114
|
+
*
|
|
115
|
+
* @param tag - The complete JSX tag string (e.g., '<Badge text="hello" />')
|
|
116
|
+
* @returns Array of parsed attributes
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const attrs = parseJSXAttributes('<Card title="Hello" icon="star" />')
|
|
121
|
+
* // Returns: [{name: 'title', value: 'Hello'}, {name: 'icon', value: 'star'}]
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
declare function parseJSXAttributes(tag: string): readonly JSXAttribute[];
|
|
125
|
+
/**
|
|
126
|
+
* Sanitize a complete JSX tag including all attributes
|
|
127
|
+
* Parses the tag and escapes all attribute values to prevent XSS
|
|
128
|
+
*
|
|
129
|
+
* @param tag - The complete JSX tag string
|
|
130
|
+
* @returns Sanitized JSX tag safe for rendering
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* const safe = sanitizeJSXTag('<Badge text="v1.0.0" onclick="alert(1)" />')
|
|
135
|
+
* // Returns: '<Badge text="v1.0.0" onclick="alert(1)" />' (with escaped values)
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
declare function sanitizeJSXTag(tag: string): string;
|
|
139
|
+
|
|
140
|
+
export { createHeadingPattern, extractCodeBlocks, findEmptyMarkdownLinks, hasComponent, parseJSXAttributes, parseJSXTags, sanitizeAttribute, sanitizeForMDX, sanitizeJSXTag };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import "../chunk-DRBRT57F.js";
|
|
2
|
+
import {
|
|
3
|
+
createHeadingPattern,
|
|
4
|
+
extractCodeBlocks,
|
|
5
|
+
findEmptyMarkdownLinks,
|
|
6
|
+
hasComponent,
|
|
7
|
+
parseJSXAttributes,
|
|
8
|
+
parseJSXTags,
|
|
9
|
+
sanitizeAttribute,
|
|
10
|
+
sanitizeForMDX,
|
|
11
|
+
sanitizeJSXTag
|
|
12
|
+
} from "../chunk-GZ2MP3VN.js";
|
|
13
|
+
export {
|
|
14
|
+
createHeadingPattern,
|
|
15
|
+
extractCodeBlocks,
|
|
16
|
+
findEmptyMarkdownLinks,
|
|
17
|
+
hasComponent,
|
|
18
|
+
parseJSXAttributes,
|
|
19
|
+
parseJSXTags,
|
|
20
|
+
sanitizeAttribute,
|
|
21
|
+
sanitizeForMDX,
|
|
22
|
+
sanitizeJSXTag
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FileChangeEvent, PackageInfo } from '../types.js';
|
|
2
|
+
import '@bfra.me/es/result';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
interface DocWatcherOptions {
|
|
6
|
+
readonly rootDir?: string;
|
|
7
|
+
readonly debounceMs?: number;
|
|
8
|
+
readonly additionalIgnore?: readonly string[];
|
|
9
|
+
readonly usePolling?: boolean;
|
|
10
|
+
}
|
|
11
|
+
type DocChangeHandler = (events: readonly FileChangeEvent[]) => void | Promise<void>;
|
|
12
|
+
interface DocFileWatcher {
|
|
13
|
+
readonly start: () => Promise<void>;
|
|
14
|
+
readonly close: () => Promise<void>;
|
|
15
|
+
readonly onChanges: (handler: DocChangeHandler) => () => void;
|
|
16
|
+
readonly getWatchedPaths: () => readonly string[];
|
|
17
|
+
}
|
|
18
|
+
declare function createDocWatcher(options?: DocWatcherOptions): DocFileWatcher;
|
|
19
|
+
type FileCategory = 'readme' | 'source' | 'package-json' | 'unknown';
|
|
20
|
+
declare function categorizeFile(filePath: string): FileCategory;
|
|
21
|
+
declare function groupChangesByPackage(events: readonly FileChangeEvent[]): Map<string, FileChangeEvent[]>;
|
|
22
|
+
declare function filterDocumentationChanges(events: readonly FileChangeEvent[]): FileChangeEvent[];
|
|
23
|
+
|
|
24
|
+
interface DocChangeDetectorOptions {
|
|
25
|
+
readonly algorithm?: 'sha256' | 'md5';
|
|
26
|
+
}
|
|
27
|
+
interface PackageChangeAnalysis {
|
|
28
|
+
readonly packageName: string;
|
|
29
|
+
readonly needsRegeneration: boolean;
|
|
30
|
+
readonly changedCategories: readonly FileCategory[];
|
|
31
|
+
readonly changedFiles: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
interface DocChangeDetector {
|
|
34
|
+
readonly hasChanged: (filePath: string) => Promise<boolean>;
|
|
35
|
+
readonly record: (filePath: string) => Promise<void>;
|
|
36
|
+
readonly recordPackage: (pkg: PackageInfo, files: readonly string[]) => Promise<void>;
|
|
37
|
+
readonly clear: (filePath: string) => void;
|
|
38
|
+
readonly clearAll: () => void;
|
|
39
|
+
readonly analyzeChanges: (events: readonly FileChangeEvent[]) => Promise<PackageChangeAnalysis[]>;
|
|
40
|
+
}
|
|
41
|
+
declare function createDocChangeDetector(options?: DocChangeDetectorOptions): DocChangeDetector;
|
|
42
|
+
type RegenerationScope = 'full' | 'api-only' | 'readme-only' | 'metadata-only' | 'none';
|
|
43
|
+
declare function determineRegenerationScope(changedCategories: readonly FileCategory[]): RegenerationScope;
|
|
44
|
+
declare function hasAnyFileChanged(detector: DocChangeDetector, files: readonly string[]): Promise<boolean>;
|
|
45
|
+
|
|
46
|
+
interface DocDebouncerOptions {
|
|
47
|
+
readonly debounceMs?: number;
|
|
48
|
+
readonly maxWaitMs?: number;
|
|
49
|
+
}
|
|
50
|
+
type BatchChangeHandler = (events: readonly FileChangeEvent[]) => void | Promise<void>;
|
|
51
|
+
interface DocDebouncer {
|
|
52
|
+
readonly add: (event: FileChangeEvent) => void;
|
|
53
|
+
readonly addAll: (events: readonly FileChangeEvent[]) => void;
|
|
54
|
+
readonly flush: () => void;
|
|
55
|
+
readonly cancel: () => void;
|
|
56
|
+
readonly getPendingCount: () => number;
|
|
57
|
+
}
|
|
58
|
+
declare function createDocDebouncer(handler: BatchChangeHandler, options?: DocDebouncerOptions): DocDebouncer;
|
|
59
|
+
declare function deduplicateEvents(events: readonly FileChangeEvent[]): FileChangeEvent[];
|
|
60
|
+
declare function consolidateEvents(events: readonly FileChangeEvent[]): FileChangeEvent[];
|
|
61
|
+
|
|
62
|
+
export { type BatchChangeHandler, type DocChangeDetector, type DocChangeDetectorOptions, type DocChangeHandler, type DocDebouncer, type DocDebouncerOptions, type DocFileWatcher, type DocWatcherOptions, type FileCategory, type PackageChangeAnalysis, type RegenerationScope, categorizeFile, consolidateEvents, createDocChangeDetector, createDocDebouncer, createDocWatcher, deduplicateEvents, determineRegenerationScope, filterDocumentationChanges, groupChangesByPackage, hasAnyFileChanged };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
categorizeFile,
|
|
3
|
+
consolidateEvents,
|
|
4
|
+
createDocChangeDetector,
|
|
5
|
+
createDocDebouncer,
|
|
6
|
+
createDocWatcher,
|
|
7
|
+
deduplicateEvents,
|
|
8
|
+
determineRegenerationScope,
|
|
9
|
+
filterDocumentationChanges,
|
|
10
|
+
groupChangesByPackage,
|
|
11
|
+
hasAnyFileChanged
|
|
12
|
+
} from "../chunk-45NROJIG.js";
|
|
13
|
+
export {
|
|
14
|
+
categorizeFile,
|
|
15
|
+
consolidateEvents,
|
|
16
|
+
createDocChangeDetector,
|
|
17
|
+
createDocDebouncer,
|
|
18
|
+
createDocWatcher,
|
|
19
|
+
deduplicateEvents,
|
|
20
|
+
determineRegenerationScope,
|
|
21
|
+
filterDocumentationChanges,
|
|
22
|
+
groupChangesByPackage,
|
|
23
|
+
hasAnyFileChanged
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bfra.me/doc-sync",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Intelligent documentation synchronization engine for automatic Astro Starlight site updates",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -35,6 +35,11 @@
|
|
|
35
35
|
"source": "./src/generators/index.ts",
|
|
36
36
|
"import": "./lib/generators/index.js"
|
|
37
37
|
},
|
|
38
|
+
"./orchestrator": {
|
|
39
|
+
"types": "./lib/orchestrator/index.d.ts",
|
|
40
|
+
"source": "./src/orchestrator/index.ts",
|
|
41
|
+
"import": "./lib/orchestrator/index.js"
|
|
42
|
+
},
|
|
38
43
|
"./parsers": {
|
|
39
44
|
"types": "./lib/parsers/index.d.ts",
|
|
40
45
|
"source": "./src/parsers/index.ts",
|
|
@@ -45,6 +50,16 @@
|
|
|
45
50
|
"source": "./src/types.ts",
|
|
46
51
|
"import": "./lib/types.js"
|
|
47
52
|
},
|
|
53
|
+
"./utils": {
|
|
54
|
+
"types": "./lib/utils/index.d.ts",
|
|
55
|
+
"source": "./src/utils/index.ts",
|
|
56
|
+
"import": "./lib/utils/index.js"
|
|
57
|
+
},
|
|
58
|
+
"./watcher": {
|
|
59
|
+
"types": "./lib/watcher/index.d.ts",
|
|
60
|
+
"source": "./src/watcher/index.ts",
|
|
61
|
+
"import": "./lib/watcher/index.js"
|
|
62
|
+
},
|
|
48
63
|
"./package.json": "./package.json"
|
|
49
64
|
},
|
|
50
65
|
"main": "./lib/index.js",
|
|
@@ -65,7 +80,7 @@
|
|
|
65
80
|
"fast-glob": "3.3.3",
|
|
66
81
|
"remark-mdx": "3.1.1",
|
|
67
82
|
"remark-parse": "11.0.0",
|
|
68
|
-
"ts-morph": "
|
|
83
|
+
"ts-morph": "27.0.2",
|
|
69
84
|
"unified": "11.0.5",
|
|
70
85
|
"zod": "4.1.13",
|
|
71
86
|
"@bfra.me/es": "0.1.0"
|