@aigne/doc-smith 0.8.14 → 0.8.15-beta.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.
@@ -913,6 +913,28 @@ Ensure that the shape names used in connections are accurate and match the actua
913
913
  - **Good Practice:**
914
914
  ```d2
915
915
  shape: sequence_diagram
916
+ User: {
917
+ shape: c4-person
918
+ }
919
+
920
+ App: {
921
+ label: "Your Application"
922
+ shape: rectangle
923
+
924
+ ResumeSubscription: {
925
+ label: "ResumeSubscription Component"
926
+ }
927
+ }
928
+
929
+ Payment-API: {
930
+ label: "Payment Backend API"
931
+ shape: rectangle
932
+ }
933
+
934
+ DID-Wallet: {
935
+ label: "DID Wallet"
936
+ icon: "https://www.arcblock.io/image-bin/uploads/37198ddc4a0b9e91e5c1c821ab895a34.svg"
937
+ }
916
938
 
917
939
  User -> App.ResumeSubscription: "1. Triggers resume action"
918
940
 
@@ -922,12 +944,16 @@ Ensure that the shape names used in connections are accurate and match the actua
922
944
  App.ResumeSubscription.t1 -> User: "4. Display confirmation dialog"
923
945
  User -> App.ResumeSubscription.t1: "5. Clicks 'Confirm'"
924
946
 
925
- App.ResumeSubscription.t1 -> DID-Wallet: "6a. Open 're-stake' session"
926
- User -> DID-Wallet: "7a. Approve in wallet"
927
- DID-Wallet -> App.ResumeSubscription.t1: "8a. Send success callback"
947
+ "If Re-Staking is Required": {
948
+ App.ResumeSubscription.t1 -> DID-Wallet: "6a. Open 're-stake' session"
949
+ User -> DID-Wallet: "7a. Approve in wallet"
950
+ DID-Wallet -> App.ResumeSubscription.t1: "8a. Send success callback"
951
+ }
928
952
 
929
- App.ResumeSubscription.t1 -> Payment-API: "6b. Call recover endpoint\n(PUT /recover)"
930
- Payment-API -> App.ResumeSubscription.t1: "7b. Return success"
953
+ "If No Staking is Required": {
954
+ App.ResumeSubscription.t1 -> Payment-API: "6b. Call recover endpoint\n(PUT /recover)"
955
+ Payment-API -> App.ResumeSubscription.t1: "7b. Return success"
956
+ }
931
957
 
932
958
  App.ResumeSubscription.t1 -> Payment-API: "9. Fetch updated subscription details"
933
959
  Payment-API -> App.ResumeSubscription.t1: "10. Return latest subscription"
@@ -1086,12 +1112,12 @@ Ensure that the shape names used in connections are accurate and match the actua
1086
1112
  Blocklet-Service -> Application.Auth-Middleware: "4. Return permissions"
1087
1113
  Application.Auth-Middleware -> Application.Auth-Middleware: "5. Evaluate all rules"
1088
1114
 
1089
- "If Authorized" {
1115
+ "If Authorized": {
1090
1116
  Application.Auth-Middleware -> Application.Protected-Route: "6a. next()"
1091
1117
  Application.Protected-Route -> Client: "7a. 200 OK Response"
1092
1118
  }
1093
1119
 
1094
- "If Forbidden" {
1120
+ "If Forbidden": {
1095
1121
  Application.Auth-Middleware -> Client: "6b. 403 Forbidden Response"
1096
1122
  }
1097
1123
  ```
@@ -80,7 +80,9 @@ Here are some high-quality documentation details for your reference:
80
80
 
81
81
  **Returns**
82
82
 
83
- <x-field data-name="product" data-type="TProductExpanded" data-desc="The newly created product object, including expanded details"></x-field>
83
+ <x-field-group>
84
+ <x-field data-name="product" data-type="TProductExpanded" data-desc="The newly created product object, including expanded details"></x-field>
85
+ </x-field-group>
84
86
 
85
87
  **Example**
86
88
 
@@ -130,11 +132,15 @@ Here are some high-quality documentation details for your reference:
130
132
 
131
133
  **Parameters**
132
134
 
133
- <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to retrieve."></x-field>
135
+ <x-field-group>
136
+ <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to retrieve."></x-field>
137
+ </x-field-group>
134
138
 
135
139
  **Returns**
136
140
 
137
- <x-field data-name="product" data-type="TProductExpanded" data-desc="The retrieved product object, including expanded details."></x-field>
141
+ <x-field-group>
142
+ <x-field data-name="product" data-type="TProductExpanded" data-desc="The retrieved product object, including expanded details."></x-field>
143
+ </x-field-group>
138
144
 
139
145
  **Example**
140
146
 
@@ -176,7 +182,9 @@ Here are some high-quality documentation details for your reference:
176
182
 
177
183
  **Returns**
178
184
 
179
- <x-field data-name="product" data-type="TProductExpanded" data-desc="The updated product object."></x-field>
185
+ <x-field-group>
186
+ <x-field data-name="product" data-type="TProductExpanded" data-desc="The updated product object."></x-field>
187
+ </x-field-group>
180
188
 
181
189
  **Example**
182
190
 
@@ -341,11 +349,15 @@ Here are some high-quality documentation details for your reference:
341
349
 
342
350
  **Parameters**
343
351
 
344
- <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to archive."></x-field>
352
+ <x-field-group>
353
+ <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to archive."></x-field>
354
+ </x-field-group>
345
355
 
346
356
  **Returns**
347
357
 
348
- <x-field data-name="product" data-type="TProduct" data-desc="The archived product object."></x-field>
358
+ <x-field-group>
359
+ <x-field data-name="product" data-type="TProduct" data-desc="The archived product object."></x-field>
360
+ </x-field-group>
349
361
 
350
362
  **Example**
351
363
 
@@ -380,11 +392,15 @@ Here are some high-quality documentation details for your reference:
380
392
 
381
393
  **Parameters**
382
394
 
383
- <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to delete."></x-field>
395
+ <x-field-group>
396
+ <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to delete."></x-field>
397
+ </x-field-group>
384
398
 
385
399
  **Returns**
386
400
 
387
- <x-field data-name="product" data-type="TProduct" data-desc="The deleted product object."></x-field>
401
+ <x-field-group>
402
+ <x-field data-name="product" data-type="TProduct" data-desc="The deleted product object."></x-field>
403
+ </x-field-group>
388
404
 
389
405
  **Example**
390
406
 
@@ -7,18 +7,17 @@ Documentation Generation Rules:
7
7
  - Since API names are already specified in document titles, avoid repeating them in subheadings—use sub-API names directly
8
8
  - Include links to related documents in the introduction using Markdown format to help users navigate to relevant content
9
9
  - Add links to further reading materials in the summary section using Markdown format
10
+ - **Markdown Syntax Constraint**: Use only GitHub Flavored Markdown (GFM) syntax by default. Prohibited extensions include: custom blocks `:::`, footnotes `[^1]: notes`, math formulas `$$ LaTeX`, highlighted text `==code==`, and other non-GFM syntax unless explicitly defined in custom component rules
10
11
  - Use proper Markdown link syntax, for example: [Next Chapter Title](next_chapter_path)
11
12
  - **Ensure next_chapter_path references either external URLs or valid paths from the documentation structure**—use absolute paths from the documentation structure
12
13
  - When DataSources includes third-party links, incorporate them appropriately throughout the document
13
14
  - Structure each section with: title, introduction, code examples, response data samples, and explanatory notes. Place explanations directly after code examples without separate "Example Description" subheadings
14
15
  - Maintain content completeness and logical flow so users can follow the documentation seamlessly
15
16
  - Provide comprehensive explanations for configuration options and parameters. When parameters accept multiple values, explain each option's purpose and include code examples where applicable
16
- - Use the `<x-field>` custom component only for displaying structured object data such as API parameters, return values, network request body/query/headers, and complex object properties (e.g., ContextType). This component does not exist independently but represents complete object structures
17
- - Do not use `<x-field>` for individual field descriptions (e.g., name or version in package.json, logo or appUrl in config.yaml) - use regular Markdown text instead
18
- - Wrap the outermost `<x-field>` elements with `<x-field-group>` when describing multiple properties of the same object, even if there's only one `<x-field>` element
19
- - Use recursive `<x-field>` structures to fully express complex object type hierarchies, decomposing all nested properties into more fundamental types. Limit nesting to 5 levels maximum
20
17
  - All interface and method documentation must include **response data examples**
21
- - For simple list data, use Markdown tables to present information clearly and improve readability
18
+ - **Use `<x-field-group>` for all structured data**: Represent objects with nested `<x-field>` elements, and expand each structure to the **deepest relevant level**.
19
+ - **Enhance field descriptions with example values**: For structured data defined using `<x-field-group>`, extract example values from type definitions, comments, or test cases to make documentation more practical and user-friendly.
20
+ - **Use Markdown tables** for predefined values (e.g., status types, options) or term definitions to improve clarity and allow side-by-side comparison.
22
21
  - Validate output Markdown for completeness, ensuring tables are properly formatted
23
22
  - **Content Integrity**: Generate complete, syntactically correct code blocks (JSON, etc.). Perform self-validation to ensure all code blocks, lists, and tables are properly closed without truncation
24
23
  - **Markdown Syntax Validation**: Ensure correct Markdown formatting, particularly table separators (e.g., `|---|---|---|`) that match column counts
@@ -27,6 +27,43 @@
27
27
 
28
28
  </datasources>
29
29
 
30
+ {% if openAPISpec %}
31
+ <openapi>
32
+
33
+ **Goal:** Use the provided OpenAPI (Swagger) specification, align it with the current page objective, and leverage it to refine this document.
34
+
35
+ **OpenAPI File Content:**
36
+ <openapi_doc>
37
+
38
+ {{ openAPISpec }}
39
+
40
+ </openapi_doc>
41
+
42
+ ---
43
+
44
+ ### **Documentation Requirements and Constraints**
45
+
46
+ 1. **Extract the core content:**
47
+ * Organize the document by functional modules.
48
+ * For each path item, include the following elements:
49
+ * HTTP method and path.
50
+ * Concise summary.
51
+ * Detailed description.
52
+ * Request parameters: name, location (`in`), type, required flag, description.
53
+ * Request body: describe its structure when present.
54
+ * Responses: at least the key status codes (e.g., 200, 201, 400, 500) and their schemas.
55
+
56
+ 2. **Mandatory API description constraints (deduplication rule):**
57
+ * **Ensure that throughout the document (including preface, overview, etc.), any introduction to the project APIs appears only within this OpenAPI-generated "API reference" section.**
58
+ * **Never** repeat or expand the interface list elsewhere in the document (for example, "Quick Start" or "Architecture Overview" sections).
59
+
60
+ ---
61
+
62
+ **Expected output format:** A concise, clear, and easy-to-scan Markdown document.
63
+
64
+ </openapi>
65
+ {% endif %}
66
+
30
67
 
31
68
  {% include "./detail-example.md" %}
32
69
 
@@ -12,6 +12,40 @@
12
12
  {{ datasources }}
13
13
  </datasources>
14
14
 
15
+ {% if userContext.openAPISpec %}
16
+ <openapi>
17
+
18
+ **Goal:** Use the provided OpenAPI (Swagger) specification to design how the OpenAPI content and the overall document should be structured together.
19
+
20
+ **OpenAPI File Content:**
21
+ <openapi_doc>
22
+
23
+ {{ userContext.openAPISpec }}
24
+
25
+ </openapi_doc>
26
+
27
+ ---
28
+
29
+ ### **Documentation Requirements and Constraints**
30
+
31
+ 1. **Section structure and titles:**
32
+ * Create a dedicated top-level section for the OpenAPI content.
33
+ * The section title must be professional and user friendly; **never** include terms such as OpenAPI, Swagger, or file formats. Recommended titles include **"API Interface Reference"** or **"Interface Reference"**.
34
+
35
+ 2. **Content hierarchy and presentation:**
36
+ * **Ideal state (single-level page):** Prefer to present all API endpoints within **one Markdown file (one page)**.
37
+ * **Split criteria (two-level pages):** Only when the number of endpoints is too large for a single file should you split by OpenAPI tags or logical modules, creating individual Markdown files per module.
38
+ * **Forced file hierarchy constraint:** Whether using one or two levels, the generated API reference files (Markdown) may contain **no more than two levels.**
39
+ * **Example (two-level structure):** `/api-reference.md` (index) -> `/api/user.md`, `/api/order.md` (module pages)
40
+ * **Disallow any third level or deeper structure:** for example, `/api/v1/user/get.md`.
41
+
42
+ 3. **Mandatory API description constraints (deduplication rule):**
43
+ * **Ensure that for the entire document (including preface, overview, etc.), any introduction to the project APIs appears only within this OpenAPI-generated "API reference" section.**
44
+ * **Never** repeat or extend the API list elsewhere in the document (for example, "Quick Start" or "Architecture Overview" sections).
45
+
46
+ </openapi>
47
+ {% endif %}
48
+
15
49
 
16
50
  {% if originalDocumentStructure %}
17
51
  <last_document_structure>
@@ -1,16 +1,23 @@
1
1
  <code_block_rules>
2
2
  The following formats are considered Code Blocks:
3
- - Wrapped with ```
4
- - Supports configurations: language, title, icon, where title and icon are optional
5
- - content can be code, command line examples, text or any other content
3
+
4
+ - Wrapped with ```
5
+ - Supports configurations: language, title, icon, where title and icon are optional
6
+ - content can be code, command line examples, text or any other content
6
7
 
7
8
  <code_block_sample>
9
+
8
10
  ```{language} [{title}] [icon={icon}]
9
11
  {content}
10
12
  ```
13
+
11
14
  </code_block_sample>
12
15
 
13
- Code Block Translation:
14
- - For D2 code blocks, only translate labels
15
- - For other language code blocks, **only translate comments starting with #, keep all other content unchanged without translation**
16
- </code_block_rules>
16
+ Code Block Translation Rules:
17
+
18
+ - For D2 code blocks, translate **labels only**; leave all variable names, component names, and syntax unchanged.
19
+ - Translate **comments only** using the language-specific comment syntax; **preserve** all code, variables, functions, and syntax.
20
+ - **Do not translate** command examples, terminal/log outputs, or runtime output.
21
+ - **Preserve** all formatting, indentation, and code block structure.
22
+
23
+ </code_block_rules>
@@ -9,6 +9,7 @@ Core Mandates:
9
9
  3. Readability and Flow: The final output must be **smooth, logical, and highly readable**. Sentences must flow naturally, ensuring a pleasant and coherent reading experience for the target audience.
10
10
  4. Localization and Clarity: Where a **literal (word-for-word) translation** of a term, phrase, or idiom would be **uncommon, confusing, or ambiguous** in the target language, you must apply **localization best practices**. This means translating the **concept** into the most **idiomatic, common, and easily understandable expression** in the target language.
11
11
  5. Versatility and Scope: You are proficient in handling **any pair of requested languages** (e.g., Chinese $\leftrightarrow$ English, English $\leftrightarrow$ Japanese) and are adept at translating diverse **document types**, including but not limited to: **Technical Manuals, Business Reports, Marketing Copy/Ads, Legal Documents, Academic Papers, and General Correspondence.**
12
+
12
13
  </role_and_goal>
13
14
 
14
15
  <translation_rules>
@@ -19,11 +20,12 @@ Translation Requirements:
19
20
  - Strictly Protect Markdown Syntax: All Markdown syntax characters, including but not limited to `|` and `-` in tables, `*` and `-` in lists, `#` in headings, `` ` `` in code blocks, etc., must be **copied exactly**, with no modification, addition, deletion, or merging. Table separators (e.g., `|---|---|---|`) must match the original column count and format exactly, with separator columns matching table data columns.
20
21
  - Use Terminology Reference: Ensure accuracy and consistency of professional terminology.
21
22
  - Preserve Terms: Retain specific terms in their original form, avoiding translation.
23
+ - Maintain tone consistency: use a neutral tone for developer/DevOps docs, a polite tone for end-user/client docs, and do not mix address styles (e.g., **"you"** vs **"您"**).
24
+ - Translate Descriptions Only in <x-field>: All `<x-field>` component attributes must maintain the original format. Only translate the description content within `data-desc` attribute or `<x-field-desc>` elements.
22
25
 
23
26
  {% include "./code-block.md" %}
24
27
  </translation_rules>
25
28
 
26
-
27
29
  {% if feedback %}
28
30
  <translation_user_feedback>
29
31
  {{ feedback }}
@@ -41,10 +43,11 @@ Translation Requirements:
41
43
  {{userPreferences}}
42
44
 
43
45
  User preference guidelines:
46
+
44
47
  - User preferences are derived from feedback provided in previous user interactions. When generating translations, consider user preferences to avoid repeating issues mentioned in user feedback
45
48
  - User preferences carry less weight than current user feedback
46
- </user_preferences>
47
- {% endif %}
49
+ </user_preferences>
50
+ {% endif %}
48
51
 
49
52
  {% include "./glossary.md" %}
50
53
 
@@ -58,7 +61,7 @@ Terms to preserve (do not translate):
58
61
 
59
62
  <example>
60
63
  <example_item>
61
- **Special Note**: Keep table separators `|---|---|---|` unchanged from the original
64
+ Table Translation - Demonstrates how to translate table content while preserving markdown structure and separators.
62
65
 
63
66
  <before_translate>
64
67
  | Name | Type | Description |
@@ -77,7 +80,8 @@ Terms to preserve (do not translate):
77
80
  </example_item>
78
81
 
79
82
  <example_item>
80
- **Special Note**: All x-field component attributes must maintain the original format. Only translate the description content within data-desc attributes or x-field-desc elements
83
+ XField Component Translation - Shows how to translate only description content within x-field components while preserving all attributes.
84
+
81
85
  <before_translate>
82
86
 
83
87
  <x-field data-name="teamDid" data-type="string" data-required="true" data-desc="The DID of the team or Blocklet managing the webhook."></x-field>
@@ -96,9 +100,10 @@ Terms to preserve (do not translate):
96
100
  </example_item>
97
101
 
98
102
  <example_item>
99
- **Special Note**: In code blocks, only translate comments while keeping all other code content (variables, functions, syntax) unchanged
103
+ Code Block Translation - Illustrates translating only comments in code blocks while keeping all code content unchanged.
100
104
 
101
105
  <before_translate>
106
+
102
107
  ```xxx
103
108
  // Initialize the API client
104
109
  const client = new APIClient({
@@ -125,9 +130,11 @@ async function getUserData(userId) {
125
130
  }
126
131
  }
127
132
  ```
133
+
128
134
  </before_translate>
129
135
 
130
136
  <after_translate>
137
+
131
138
  ```xxx
132
139
  // 初始化 API 客户端
133
140
  const client = new APIClient({
@@ -154,13 +161,15 @@ async function getUserData(userId) {
154
161
  }
155
162
  }
156
163
  ```
164
+
157
165
  </after_translate>
158
166
  </example_item>
159
167
 
160
168
  <example_item>
161
- **Special Note**: **Command execution and log printing** should untranslated
169
+ Command and Log Preservation - Demonstrates preserving command execution and log output without translation.
162
170
 
163
171
  <before_translate>
172
+
164
173
  ```text Timeout Error Message
165
174
  Blocklet Server failed to stop within 5 minutes
166
175
  You can stop blocklet server with blocklet stop --force
@@ -171,9 +180,11 @@ $ cli log
171
180
 
172
181
  Cache for server cleared: [list of cleared cache keys]
173
182
  ```
183
+
174
184
  </before_translate>
175
185
 
176
186
  <after_translate>
187
+
177
188
  ```text 超时错误消息
178
189
  Blocklet Server failed to stop within 5 minutes
179
190
  You can stop blocklet server with blocklet stop --force
@@ -184,6 +195,99 @@ $ cli log
184
195
 
185
196
  Cache for server cleared: [list of cleared cache keys]
186
197
  ```
198
+
199
+ </after_translate>
200
+ </example_item>
201
+
202
+ <example_item>
203
+ D2 Diagram Translation - Shows how to translate only labels in D2 diagrams while preserving all syntax and structure.
204
+
205
+ <before_translate>
206
+
207
+ ```d2 High-Level Architecture
208
+ direction: down
209
+
210
+ User: {
211
+ shape: c4-person
212
+ }
213
+
214
+ Your-Application: {
215
+ label: "Your Application"
216
+ shape: rectangle
217
+
218
+ PaymentProvider: {
219
+ label: "PaymentProvider"
220
+ shape: rectangle
221
+
222
+ Payment-Components: {
223
+ label: "Payment Components"
224
+ shape: rectangle
225
+ grid-columns: 2
226
+
227
+ CheckoutForm: { label: "CheckoutForm" }
228
+ CheckoutTable: { label: "CheckoutTable" }
229
+ CheckoutDonate: { label: "CheckoutDonate" }
230
+ CustomerInvoiceList: { label: "CustomerInvoiceList" }
231
+ }
232
+ }
233
+ }
234
+
235
+ Payment-Kit-Backend: {
236
+ label: "Payment Kit Backend"
237
+ shape: cylinder
238
+ }
239
+
240
+ User -> Your-Application.PaymentProvider.Payment-Components: "Interacts with UI"
241
+ Your-Application.PaymentProvider -> Payment-Kit-Backend: "Handles API Communication"
242
+ Payment-Kit-Backend -> Your-Application.PaymentProvider: "Returns Data"
243
+ Your-Application.PaymentProvider.Payment-Components -> User: "Renders UI Updates"
244
+
245
+ ```
246
+
247
+ </before_translate>
248
+
249
+ <after_translate>
250
+
251
+ ```d2 高层架构
252
+ direction: down
253
+
254
+ User: {
255
+ shape: c4-person
256
+ }
257
+
258
+ Your-Application: {
259
+ label: "您的应用程序"
260
+ shape: rectangle
261
+
262
+ PaymentProvider: {
263
+ label: "PaymentProvider"
264
+ shape: rectangle
265
+
266
+ Payment-Components: {
267
+ label: "支付组件"
268
+ shape: rectangle
269
+ grid-columns: 2
270
+
271
+ CheckoutForm: { label: "CheckoutForm" }
272
+ CheckoutTable: { label: "CheckoutTable" }
273
+ CheckoutDonate: { label: "CheckoutDonate" }
274
+ CustomerInvoiceList: { label: "CustomerInvoiceList" }
275
+ }
276
+ }
277
+ }
278
+
279
+ Payment-Kit-Backend: {
280
+ label: "Payment Kit 后端"
281
+ shape: cylinder
282
+ }
283
+
284
+ User -> Your-Application.PaymentProvider.Payment-Components: "与 UI 交互"
285
+ Your-Application.PaymentProvider -> Payment-Kit-Backend: "处理 API 通信"
286
+ Payment-Kit-Backend -> Your-Application.PaymentProvider: "返回数据"
287
+ Your-Application.PaymentProvider.Payment-Components -> User: "渲染 UI 更新"
288
+
289
+ ```
290
+
187
291
  </after_translate>
188
292
  </example_item>
189
293
 
@@ -8,6 +8,8 @@ import { isBinaryFile } from "isbinaryfile";
8
8
  import { encode } from "gpt-tokenizer";
9
9
  import { fileTypeFromBuffer } from "file-type";
10
10
  import { gunzipSync } from "node:zlib";
11
+
12
+ import { debug } from "./debug.mjs";
11
13
  import { isGlobPattern } from "./utils.mjs";
12
14
  import { INTELLIGENT_SUGGESTION_TOKEN_THRESHOLD } from "./constants/index.mjs";
13
15
  import { uploadFiles } from "./upload-files.mjs";
@@ -284,6 +286,11 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
284
286
  continue;
285
287
  }
286
288
 
289
+ if (checkIsRemoteFile(dir)) {
290
+ allFiles.push(dir);
291
+ continue;
292
+ }
293
+
287
294
  // First try to access as a file or directory
288
295
  const stats = await stat(dir);
289
296
 
@@ -313,7 +320,13 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
313
320
  : [];
314
321
 
315
322
  finalIncludePatterns = [...defaultIncludePatterns, ...userInclude];
316
- finalExcludePatterns = [...defaultExcludePatterns, ...userExclude];
323
+ finalExcludePatterns = [
324
+ ...defaultExcludePatterns,
325
+ ...userExclude.map((x) => {
326
+ const prefix = `${dir}/`;
327
+ return x.startsWith(prefix) ? x.slice(prefix.length) : x;
328
+ }),
329
+ ];
317
330
  } else {
318
331
  // Use only user patterns
319
332
  if (includePatterns) {
@@ -374,6 +387,10 @@ export async function loadFilesFromPaths(sourcesPath, options = {}) {
374
387
  * @returns {Promise<boolean>} True if file appears to be a text file
375
388
  */
376
389
  async function isTextFile(filePath) {
390
+ if (checkIsRemoteFile(filePath)) {
391
+ return checkIsHttpTextFile(filePath);
392
+ }
393
+
377
394
  try {
378
395
  const isBinary = await isBinaryFile(filePath);
379
396
  return !isBinary;
@@ -383,6 +400,53 @@ async function isTextFile(filePath) {
383
400
  }
384
401
  }
385
402
 
403
+ export function checkIsRemoteFile(filepath) {
404
+ if (filepath.startsWith("http://") || filepath.startsWith("https://")) {
405
+ return true;
406
+ }
407
+ return false;
408
+ }
409
+
410
+ export async function checkIsHttpTextFile(fileUrl) {
411
+ try {
412
+ const res = await fetch(fileUrl, {
413
+ method: "HEAD",
414
+ });
415
+ const contentType = res.headers.get("content-type") || "";
416
+ const textMimeTypes = [
417
+ "application/json",
418
+ "application/ld+json",
419
+ "application/graphql+json",
420
+ "application/xml",
421
+ "application/xhtml+xml",
422
+ "application/javascript",
423
+ "application/ecmascript",
424
+ "application/x-www-form-urlencoded",
425
+ "application/rss+xml",
426
+ "application/atom+xml",
427
+ ];
428
+ if (contentType.startsWith("text/") || textMimeTypes.includes(contentType)) {
429
+ return true;
430
+ }
431
+ return false;
432
+ } catch (error) {
433
+ debug(`Failed to check HTTP file content type: ${fileUrl} - ${error.message}`);
434
+ return null;
435
+ }
436
+ }
437
+
438
+ export async function getHttpFileContent(file) {
439
+ if (!file) return null;
440
+ try {
441
+ const res = await fetch(file);
442
+ const text = await res.text();
443
+ return text;
444
+ } catch (error) {
445
+ debug(`Failed to fetch HTTP file content: ${file} - ${error.message}`);
446
+ return null;
447
+ }
448
+ }
449
+
386
450
  /**
387
451
  * Read and parse file contents from an array of file paths
388
452
  * @param {string[]} files - Array of file paths to read
@@ -405,12 +469,24 @@ export async function readFileContents(files, baseDir = process.cwd(), options =
405
469
  }
406
470
 
407
471
  try {
408
- const content = await readFile(file, "utf8");
409
- const relativePath = path.relative(baseDir, file);
410
- return {
411
- sourceId: relativePath,
412
- content,
413
- };
472
+ if (checkIsRemoteFile(file)) {
473
+ const content = await getHttpFileContent(file);
474
+ if (content) {
475
+ return {
476
+ sourceId: file,
477
+ content,
478
+ };
479
+ }
480
+
481
+ return null;
482
+ } else {
483
+ const content = await readFile(file, "utf8");
484
+ const relativePath = path.relative(baseDir, file);
485
+ return {
486
+ sourceId: relativePath,
487
+ content,
488
+ };
489
+ }
414
490
  } catch (error) {
415
491
  // If reading as text fails (e.g., binary file), skip it
416
492
  console.warn(`Failed to read file as text: ${file} - ${error.message}`);
@@ -0,0 +1,24 @@
1
+ import { parse } from "yaml";
2
+
3
+ export function isOpenAPISpecFile(content) {
4
+ const trimmedContent = content.trim();
5
+ try {
6
+ const parsed = parse(trimmedContent, {
7
+ logLevel: "silent",
8
+ });
9
+ if (parsed.openapi || parsed.swagger) {
10
+ return true;
11
+ }
12
+ } catch {
13
+ //
14
+ }
15
+ try {
16
+ const parsed = JSON.parse(trimmedContent);
17
+ if (parsed.openapi || parsed.swagger) {
18
+ return true;
19
+ }
20
+ } catch {
21
+ //
22
+ }
23
+ return false;
24
+ }