@aigne/doc-smith 0.8.10-beta.1 → 0.8.10-beta.2

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.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.8.10-beta.1"
2
+ ".": "0.8.10-beta.2"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.10-beta.2](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.10-beta.1...v0.8.10-beta.2) (2025-09-18)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * polish code test ([#122](https://github.com/AIGNE-io/aigne-doc-smith/issues/122)) ([0629705](https://github.com/AIGNE-io/aigne-doc-smith/commit/0629705ebd271282411d507421c1ba5dd01473b9))
9
+ * update document structure review prompts and display ([#119](https://github.com/AIGNE-io/aigne-doc-smith/issues/119)) ([e2d99db](https://github.com/AIGNE-io/aigne-doc-smith/commit/e2d99db83ff3a6266b32dd450a79b6e000aff09e))
10
+ * update usage rules for field elements ([#120](https://github.com/AIGNE-io/aigne-doc-smith/issues/120)) ([434f161](https://github.com/AIGNE-io/aigne-doc-smith/commit/434f161ab7dd989d57ca670f36d0828c09abe38a))
11
+
3
12
  ## [0.8.10-beta.1](https://github.com/AIGNE-io/aigne-doc-smith/compare/v0.8.10-beta...v0.8.10-beta.1) (2025-09-18)
4
13
 
5
14
 
@@ -167,7 +167,7 @@ export default async function checkNeedGenerateStructure(
167
167
  }
168
168
 
169
169
  if (hasUpdated) {
170
- message = `\n### Project Information Updated\n\nSaved to \`.aigne/doc-smith/config.yaml\`:\n\n${message}\n\n`;
170
+ message = `\n## Project Information Updated\n\nSaved to \`.aigne/doc-smith/config.yaml\`:\n\n${message}\n\n`;
171
171
  }
172
172
  }
173
173
  } catch (error) {
@@ -10,6 +10,12 @@ skills:
10
10
  skipIfExists: true
11
11
  - ../utils/load-sources.mjs
12
12
  - ./check-need-generate-structure.mjs
13
+ - url: ../utils/save-output.mjs
14
+ default_input:
15
+ saveKey: documentStructure
16
+ savePath:
17
+ $get: outputDir
18
+ fileName: structure-plan.json
13
19
  - ./user-review-document-structure.mjs
14
20
  - url: ../utils/save-output.mjs
15
21
  default_input:
@@ -29,8 +29,8 @@ function formatDocumentStructure(structure) {
29
29
 
30
30
  function printNode(node, depth = 0) {
31
31
  const INDENT_SPACES = " ";
32
- const FOLDER_ICON = "📁";
33
- const FILE_ICON = "📄";
32
+ const FOLDER_ICON = " 📁";
33
+ const FILE_ICON = " 📄";
34
34
  const indent = INDENT_SPACES.repeat(depth);
35
35
  const prefix = depth === 0 ? FOLDER_ICON : FILE_ICON;
36
36
 
@@ -46,6 +46,21 @@ function formatDocumentStructure(structure) {
46
46
  return { rootNodes, printNode };
47
47
  }
48
48
 
49
+ function printDocumentStructure(structure) {
50
+ console.log(`\n ${"-".repeat(50)}`);
51
+ console.log(" Current Document Structure");
52
+ console.log(` ${"-".repeat(50)}`);
53
+
54
+ const { rootNodes, printNode } = formatDocumentStructure(structure);
55
+
56
+ if (rootNodes.length === 0) {
57
+ console.log(" No document structure found.");
58
+ } else {
59
+ rootNodes.forEach((node) => printNode(node));
60
+ }
61
+ console.log();
62
+ }
63
+
49
64
  export default async function userReviewDocumentStructure({ documentStructure, ...rest }, options) {
50
65
  // Check if document structure exists
51
66
  if (!documentStructure || !Array.isArray(documentStructure) || documentStructure.length === 0) {
@@ -53,17 +68,20 @@ export default async function userReviewDocumentStructure({ documentStructure, .
53
68
  return { documentStructure };
54
69
  }
55
70
 
71
+ // Print current document structure in a user-friendly format
72
+ printDocumentStructure(documentStructure);
73
+
56
74
  // Ask user if they want to review the document structure
57
75
  const needReview = await options.prompts.select({
58
76
  message:
59
- "Would you like to review the document structure?\n You can modify titles, reorganize sections, or refine content outlines.",
77
+ "Would you like to optimize the document structure?\n You can modify titles, reorganize sections.",
60
78
  choices: [
61
79
  {
62
80
  name: "Looks good - proceed with current structure",
63
81
  value: "no",
64
82
  },
65
83
  {
66
- name: "Review and provide feedback",
84
+ name: "Yes, optimize the structure",
67
85
  value: "yes",
68
86
  },
69
87
  ],
@@ -80,27 +98,11 @@ export default async function userReviewDocumentStructure({ documentStructure, .
80
98
  while (iterationCount < MAX_ITERATIONS) {
81
99
  iterationCount++;
82
100
 
83
- // Print current document structure in a user-friendly format
84
- console.log(`\n${"=".repeat(50)}`);
85
- console.log("Current Document Structure");
86
- console.log("=".repeat(50));
87
-
88
- const { rootNodes, printNode } = formatDocumentStructure(currentStructure);
89
-
90
- if (rootNodes.length === 0) {
91
- console.log("No document structure found.");
92
- } else {
93
- rootNodes.forEach((node) => printNode(node));
94
- }
95
-
96
- console.log(`${"=".repeat(50)}\n`);
97
-
98
101
  // Ask for feedback
99
102
  const feedback = await options.prompts.input({
100
103
  message:
101
104
  "How would you like to improve the structure?\n" +
102
- " • Rename, reorganize, add, or remove sections\n" +
103
- " • Adjust content outlines for clarity\n\n" +
105
+ " • Rename, reorganize, add, or remove sections\n\n" +
104
106
  " Press Enter to finish reviewing:",
105
107
  });
106
108
 
@@ -139,6 +141,9 @@ export default async function userReviewDocumentStructure({ documentStructure, .
139
141
  currentStructure = result.documentStructure;
140
142
  }
141
143
 
144
+ // Print current document structure in a user-friendly format
145
+ printDocumentStructure(currentStructure);
146
+
142
147
  // Check if feedback should be saved as user preference
143
148
  const feedbackRefinerAgent = options.context.agents["checkFeedbackRefiner"];
144
149
  if (feedbackRefinerAgent) {
@@ -393,17 +393,11 @@ export function generateYAML(input) {
393
393
  let yaml = "# Project information for documentation publishing\n";
394
394
 
395
395
  // Serialize the project info section safely with string quoting
396
- const projectSection = yamlStringify(
397
- {
398
- projectName: config.projectName,
399
- projectDesc: config.projectDesc,
400
- projectLogo: config.projectLogo,
401
- },
402
- {
403
- quotingType: '"',
404
- defaultStringType: "QUOTE_DOUBLE",
405
- },
406
- ).trim();
396
+ const projectSection = yamlStringify({
397
+ projectName: config.projectName,
398
+ projectDesc: config.projectDesc,
399
+ projectLogo: config.projectLogo,
400
+ }).trim();
407
401
 
408
402
  yaml += `${projectSection}\n\n`;
409
403
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/doc-smith",
3
- "version": "0.8.10-beta.1",
3
+ "version": "0.8.10-beta.2",
4
4
  "description": "AI-driven documentation generation tool built on the AIGNE Framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -12,13 +12,13 @@
12
12
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
13
13
  "license": "Elastic-2.0",
14
14
  "dependencies": {
15
- "@aigne/aigne-hub": "^0.9.3",
16
- "@aigne/anthropic": "^0.13.3",
17
- "@aigne/cli": "^1.46.2",
18
- "@aigne/core": "^1.60.2",
19
- "@aigne/gemini": "^0.13.3",
20
- "@aigne/openai": "^0.15.3",
21
- "@aigne/publish-docs": "^0.10.0",
15
+ "@aigne/aigne-hub": "^0.9.5",
16
+ "@aigne/anthropic": "^0.13.4",
17
+ "@aigne/cli": "^1.48.1",
18
+ "@aigne/core": "^1.60.3",
19
+ "@aigne/gemini": "^0.13.4",
20
+ "@aigne/openai": "^0.15.4",
21
+ "@aigne/publish-docs": "^0.11.0",
22
22
  "@terrastruct/d2": "^0.1.33",
23
23
  "chalk": "^5.5.0",
24
24
  "debug": "^4.4.1",
@@ -37,12 +37,38 @@ Attribute Rules:
37
37
 
38
38
  Suitable for displaying API parameters, return values, context data, and any structured data with metadata in a clean, organized format. Supports nested structures for complex data types.
39
39
 
40
+ ### 2.1. `<x-field-group>` Field Group Component
41
+
42
+ Used to group multiple related `<x-field>` elements at the top level, indicating they belong to the same object or context. This provides better organization and visual grouping for related parameters.
43
+
44
+ Syntax:
45
+
46
+ ```
47
+ <x-field-group>
48
+ <x-field data-name="field1" data-type="string" data-desc="First field description"></x-field>
49
+ <x-field data-name="field2" data-type="number" data-desc="Second field description"></x-field>
50
+ <x-field data-name="field3" data-type="boolean" data-desc="Third field description"></x-field>
51
+ </x-field-group>
52
+ ```
53
+
54
+ Attribute Rules:
55
+
56
+ - No attributes required
57
+ - Must contain multiple `<x-field>` elements
58
+ - Only `<x-field>` elements are allowed as children
59
+ - Cannot be nested inside other `<x-field>` or `<x-field-group>` elements
60
+ - Used only at the top level for grouping related fields
61
+
62
+ ### 2.2. `<x-field>` Individual Field Component
63
+
40
64
  Syntax:
41
65
 
42
66
  ```
43
67
  <x-field data-name="field_name" data-type="string" data-default="default_value" data-required="true" data-deprecated="false" data-desc="Field description">
44
68
  <!-- For complex types, children can only be other x-field elements -->
45
69
  <x-field data-name="nested_field" data-type="string" data-desc="Nested field description"></x-field>
70
+ <!-- Optional: Use x-field-desc for rich text descriptions with inline markdown -->
71
+ <x-field-desc markdown>This field supports **bold text**, `inline code`, and other inline markdown formatting.</x-field-desc>
46
72
  </x-field>
47
73
  ```
48
74
 
@@ -53,48 +79,117 @@ Attribute Rules:
53
79
  - `data-default` (optional): Default value for the field
54
80
  - `data-required` (optional): Whether the field is required ("true" or "false")
55
81
  - `data-deprecated` (optional): Whether the field is deprecated ("true" or "false")
56
- - `data-desc` (optional): Description of the field (replaces previous body content)
57
- - Children: For complex types (object, array), children can only be other `<x-field>` elements. For simple types, children can be empty.
82
+ - `data-desc` (optional): Simple description of the field (plain text only)
83
+ - Children: For complex types (object, array), children can contain multiple `<x-field>` elements and optionally one `<x-field-desc>` element. For simple types, children can be empty or contain one `<x-field-desc>` element.
84
+
85
+ Child Elements:
86
+
87
+ - `<x-field-desc>` (optional): Rich text description supporting inline markdown formatting
88
+ - `markdown` (required): **MUST** be set to "markdown" - this attribute is mandatory and cannot be omitted
89
+ - Supports **bold text**, `inline code`, *italic text*, and other inline markdown
90
+ - Cannot contain block-level elements (no code blocks, headers, lists)
91
+ - **Mutually exclusive with `data-desc`**: Use either `data-desc` attribute OR `<x-field-desc>` element, not both
92
+ - Only one `<x-field-desc>` element per `<x-field>` is allowed
93
+ - **Validation**: `<x-field-desc>` without `markdown` attribute will be rejected
58
94
 
59
95
  Nesting Rules:
60
96
 
61
97
  - Maximum nesting depth: 5 levels (to avoid overly complex structures)
62
- - Children elements must only be `<x-field>` components
63
- - Use `data-desc` attribute for field descriptions instead of body content
64
- - **Always use opening/closing tags format**: `<x-field ...></x-field>` for all types
65
- - For simple types (string, number, boolean), children can be empty: `<x-field ...></x-field>`
66
- - For complex types (object, array), children contain nested `<x-field>` elements
98
+ - **Top-level organization**: Use `<x-field-group>` to group related `<x-field>` elements at the top level
99
+ - **Field component children**: Children elements must only be `<x-field>` and `<x-field-desc>` components
100
+ - **Group component children**: `<x-field-group>` can only contain `<x-field>` elements
101
+ - **Mutually exclusive descriptions**: Use either `data-desc` attribute OR `<x-field-desc>` element, not both
102
+ - **Child element limits**:
103
+ - For simple types: children can be empty or contain exactly one `<x-field-desc>` element
104
+ - For complex types: children can contain multiple `<x-field>` elements and optionally one `<x-field-desc>` element
105
+ - **Always use opening/closing tags format**: `<x-field ...></x-field>` and `<x-field-group>...</x-field-group>` for all types
106
+ - **Mandatory markdown attribute**: Every `<x-field-desc>` element **MUST** include `markdown` attribute - elements without this attribute will be rejected
107
+ - **Grouping rules**:
108
+ - `<x-field-group>` can only be used at the top level
109
+ - Cannot be nested inside `<x-field>` or other `<x-field-group>` elements
110
+ - Must contain multiple `<x-field>` elements
111
+ - For simple types (string, number, boolean), children can be empty or contain one `<x-field-desc>`: `<x-field ...></x-field>` or `<x-field ...><x-field-desc markdown>...</x-field-desc></x-field>`
112
+ - For complex types (object, array), children contain nested `<x-field>` elements and optionally one `<x-field-desc>` element
67
113
 
68
114
  **Usage Rules:**
69
115
 
70
116
  - **Context types must use `<x-field>` instead of tables** for consistent formatting
117
+ - **Mandatory markdown attribute**: Every `<x-field-desc>` element must include `markdown` attribute
118
+
119
+ **Error Examples:**
120
+
121
+ ❌ **INCORRECT** - Missing `markdown` attribute:
122
+ ```
123
+ <x-field data-name="api_key" data-type="string" data-required="true">
124
+ <x-field-desc>Your **API key** for authentication.</x-field-desc>
125
+ </x-field>
126
+ ```
127
+
128
+ ✅ **CORRECT** - With required `markdown` attribute:
129
+ ```
130
+ <x-field data-name="api_key" data-type="string" data-required="true">
131
+ <x-field-desc markdown>Your **API key** for authentication.</x-field-desc>
132
+ </x-field>
133
+ ```
71
134
 
72
135
  Example:
73
136
 
74
137
  ```
75
- <!-- Single field -->
138
+ <!-- Single field with simple description (using data-desc) -->
76
139
  <x-field data-name="user_id" data-type="string" data-default="u0911" data-required="true" data-deprecated="true" data-desc="Unique identifier for the user. Must be a valid UUID v4 format."></x-field>
77
140
 
78
- <!-- Multiple related fields (Props, Parameters, Returns, Context) -->
79
- <x-field data-name="name" data-type="string" data-required="true" data-desc="The name of the product."></x-field>
80
- <x-field data-name="description" data-type="string" data-required="false" data-desc="An optional description for the product."></x-field>
81
- <x-field data-name="type" data-type="string" data-required="false" data-desc="The type of product (e.g., 'service', 'good')."></x-field>
141
+ <!-- Single field with rich text description (using x-field-desc) -->
142
+ <x-field data-name="api_key" data-type="string" data-required="true">
143
+ <x-field-desc markdown>Your **API key** for authentication. Generate one from the `Settings > API Keys` section. Keep it secure and never expose it in client-side code.</x-field-desc>
144
+ </x-field>
82
145
 
83
- <!-- Complex nested object -->
84
- <x-field data-name="session" data-type="object" data-required="true" data-desc="User session information containing authentication and permission data">
146
+ <!-- Multiple related fields grouped together (Props, Parameters, Returns, Context) -->
147
+ <x-field-group>
148
+ <x-field data-name="name" data-type="string" data-required="true" data-desc="The name of the product."></x-field>
149
+ <x-field data-name="description" data-type="string" data-required="false" data-desc="An optional description for the product."></x-field>
150
+ <x-field data-name="type" data-type="string" data-required="false" data-desc="The type of product (e.g., 'service', 'good')."></x-field>
151
+ <x-field data-name="price" data-type="number" data-required="true" data-default="0">
152
+ <x-field-desc markdown>Product price in **USD**. Must be a positive number with up to 2 decimal places.</x-field-desc>
153
+ </x-field>
154
+ </x-field-group>
155
+
156
+ <!-- Multiple field groups for different contexts -->
157
+ <x-field-group>
158
+ <x-field data-name="username" data-type="string" data-required="true" data-desc="User login name"></x-field>
159
+ <x-field data-name="email" data-type="string" data-required="true" data-desc="User email address"></x-field>
160
+ <x-field data-name="password" data-type="string" data-required="true" data-desc="User password"></x-field>
161
+ </x-field-group>
162
+
163
+ <x-field-group>
164
+ <x-field data-name="host" data-type="string" data-required="true" data-default="localhost" data-desc="Database host address"></x-field>
165
+ <x-field data-name="port" data-type="number" data-required="true" data-default="5432" data-desc="Database port number"></x-field>
166
+ <x-field data-name="ssl" data-type="boolean" data-required="false" data-default="false" data-desc="Enable SSL connection"></x-field>
167
+ </x-field-group>
168
+
169
+ <!-- Complex nested object with rich descriptions -->
170
+ <x-field data-name="session" data-type="object" data-required="true">
171
+ <x-field-desc markdown>Contains all **authentication** and **authorization** data for the current user session. This object is automatically populated after successful login.</x-field-desc>
85
172
  <x-field data-name="auth" data-type="object" data-required="true" data-desc="User authentication information">
86
173
  <x-field data-name="token" data-type="object" data-required="true" data-desc="Access token information">
87
- <x-field data-name="access_token" data-type="string" data-required="true" data-default="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." data-desc="JWT access token for API authentication"></x-field>
88
- <x-field data-name="refresh_token" data-type="string" data-required="false" data-default="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." data-desc="Refresh token for obtaining new access tokens"></x-field>
174
+ <x-field data-name="access_token" data-type="string" data-required="true" data-default="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...">
175
+ <x-field-desc markdown>**JWT token** containing user identity and permissions. Expires in `24 hours` by default. Use the `refresh_token` to obtain a new one.</x-field-desc>
176
+ </x-field>
177
+ <x-field data-name="refresh_token" data-type="string" data-required="false" data-default="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...">
178
+ <x-field-desc markdown>Used to obtain new `access_token` when the current one expires. Valid for **30 days**.</x-field-desc>
179
+ </x-field>
89
180
  <x-field data-name="expires_at" data-type="number" data-required="true" data-default="1704067200" data-desc="Token expiration timestamp (Unix timestamp)"></x-field>
90
181
  </x-field>
91
182
  <x-field data-name="user" data-type="object" data-required="true" data-desc="User basic information">
92
183
  <x-field data-name="profile" data-type="object" data-required="true" data-desc="User profile information">
93
184
  <x-field data-name="name" data-type="string" data-required="true" data-default="John Doe" data-desc="User name"></x-field>
94
- <x-field data-name="email" data-type="string" data-required="true" data-default="john.doe@example.com" data-desc="User email address"></x-field>
185
+ <x-field data-name="email" data-type="string" data-required="true" data-default="john.doe@example.com">
186
+ <x-field-desc markdown>Primary email address used for **login** and **notifications**. Must be a valid email format.</x-field-desc>
187
+ </x-field>
95
188
  <x-field data-name="avatar" data-type="string" data-required="false" data-default="https://example.com/avatars/john-doe.jpg" data-desc="User avatar URL"></x-field>
96
189
  </x-field>
97
- <x-field data-name="permissions" data-type="array" data-required="true" data-default='["read", "write", "admin"]' data-desc="User permissions list"></x-field>
190
+ <x-field data-name="permissions" data-type="array" data-required="true" data-default='["read", "write", "admin"]'>
191
+ <x-field-desc markdown>Array of **permission strings** that determine what actions the user can perform. Common values: `"read"`, `"write"`, `"admin"`, `"delete"`.</x-field-desc>
192
+ </x-field>
98
193
  </x-field>
99
194
  </x-field>
100
195
  </x-field>
@@ -63,21 +63,20 @@
63
63
 
64
64
  **Parameters**
65
65
 
66
- <x-field data-name="name" data-type="string" data-required="true" data-desc="The name of the product."></x-field>
67
-
68
- <x-field data-name="description" data-type="string" data-required="false" data-desc="An optional description for the product."></x-field>
69
-
70
- <x-field data-name="type" data-type="string" data-required="false" data-desc="The type of product (e.g., 'service', 'good')."></x-field>
71
-
72
- <x-field data-name="prices" data-type="Partial<TPrice>[]" data-required="false" data-desc="An optional array of partial price objects to associate with the product upon creation">
73
- <x-field data-name="type" data-type="string" data-required="true" data-desc="The type of price (e.g., 'recurring', 'one_time')"></x-field>
74
- <x-field data-name="unit_amount" data-type="string" data-required="true" data-desc="The price amount as a string"></x-field>
75
- <x-field data-name="currency_id" data-type="string" data-required="true" data-desc="The currency identifier"></x-field>
76
- <x-field data-name="recurring" data-type="object" data-required="false" data-desc="Recurring price configuration">
77
- <x-field data-name="interval" data-type="string" data-required="true" data-desc="The billing interval (e.g., 'month', 'year')"></x-field>
78
- <x-field data-name="interval_count" data-type="number" data-required="true" data-desc="The number of intervals between each billing"></x-field>
66
+ <x-field-group>
67
+ <x-field data-name="name" data-type="string" data-required="true" data-desc="The name of the product."></x-field>
68
+ <x-field data-name="description" data-type="string" data-required="false" data-desc="An optional description for the product."></x-field>
69
+ <x-field data-name="type" data-type="string" data-required="false" data-desc="The type of product (e.g., 'service', 'good')."></x-field>
70
+ <x-field data-name="prices" data-type="Partial<TPrice>[]" data-required="false" data-desc="An optional array of partial price objects to associate with the product upon creation">
71
+ <x-field data-name="type" data-type="string" data-required="true" data-desc="The type of price (e.g., 'recurring', 'one_time')"></x-field>
72
+ <x-field data-name="unit_amount" data-type="string" data-required="true" data-desc="The price amount as a string"></x-field>
73
+ <x-field data-name="currency_id" data-type="string" data-required="true" data-desc="The currency identifier"></x-field>
74
+ <x-field data-name="recurring" data-type="object" data-required="false" data-desc="Recurring price configuration">
75
+ <x-field data-name="interval" data-type="string" data-required="true" data-desc="The billing interval (e.g., 'month', 'year')"></x-field>
76
+ <x-field data-name="interval_count" data-type="number" data-required="true" data-desc="The number of intervals between each billing"></x-field>
77
+ </x-field>
79
78
  </x-field>
80
- </x-field>
79
+ </x-field-group>
81
80
 
82
81
  **Returns**
83
82
 
@@ -169,10 +168,11 @@
169
168
  Use the `update` method to modify an existing product's details.
170
169
 
171
170
  **Parameters**
172
-
173
- <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to update."></x-field>
174
-
175
- <x-field data-name="data" data-type="Partial<TProduct>" data-required="true" data-desc="An object containing the product fields to update. Available fields include name, description, type, etc."></x-field>
171
+
172
+ <x-field-group>
173
+ <x-field data-name="id" data-type="string" data-required="true" data-desc="The unique identifier of the product to update."></x-field>
174
+ <x-field data-name="data" data-type="Partial<TProduct>" data-required="true" data-desc="An object containing the product fields to update. Available fields include name, description, type, etc."></x-field>
175
+ </x-field-group>
176
176
 
177
177
  **Returns**
178
178
 
@@ -213,31 +213,25 @@
213
213
 
214
214
  **Parameters**
215
215
 
216
- <x-field data-name="active" data-type="boolean" data-required="false" data-desc="Optional. Filter by product active status."></x-field>
217
-
218
- <x-field data-name="name" data-type="string" data-required="false" data-desc="Optional. Filter by product name."></x-field>
219
-
220
- <x-field data-name="description" data-type="string" data-required="false" data-desc="Optional. Filter by product description."></x-field>
221
-
222
- <x-field data-name="metadata.{key}" data-type="string" data-required="false" data-desc="Optional. Filter by custom metadata fields. Use metadata.yourKey to specify a metadata property."></x-field>
223
-
224
- <x-field data-name="page" data-type="number" data-default="1" data-required="false" data-desc="Optional. The page number for pagination (default: 1)."></x-field>
225
-
226
- <x-field data-name="pageSize" data-type="number" data-default="50" data-required="false" data-desc="Optional. The number of items per page (default: 50)."></x-field>
227
-
228
- <x-field data-name="order" data-type="string" data-required="false" data-desc="Optional. Sort order (e.g., 'created_at:ASC', 'updated_at:DESC')."></x-field>
229
-
230
- <x-field data-name="activeFirst" data-type="boolean" data-required="false" data-desc="Optional. If true, active products are listed first."></x-field>
216
+ <x-field-group>
217
+ <x-field data-name="active" data-type="boolean" data-required="false" data-desc="Optional. Filter by product active status."></x-field>
218
+ <x-field data-name="name" data-type="string" data-required="false" data-desc="Optional. Filter by product name."></x-field>
219
+ <x-field data-name="description" data-type="string" data-required="false" data-desc="Optional. Filter by product description."></x-field>
220
+ <x-field data-name="metadata.{key}" data-type="string" data-required="false" data-desc="Optional. Filter by custom metadata fields. Use metadata.yourKey to specify a metadata property."></x-field>
221
+ <x-field data-name="page" data-type="number" data-default="1" data-required="false" data-desc="Optional. The page number for pagination (default: 1)."></x-field>
222
+ <x-field data-name="pageSize" data-type="number" data-default="50" data-required="false" data-desc="Optional. The number of items per page (default: 50)."></x-field>
223
+ <x-field data-name="order" data-type="string" data-required="false" data-desc="Optional. Sort order (e.g., 'created_at:ASC', 'updated_at:DESC')."></x-field>
224
+ <x-field data-name="activeFirst" data-type="boolean" data-required="false" data-desc="Optional. If true, active products are listed first."></x-field>
225
+ </x-field-group>
231
226
 
232
227
  **Returns**
233
228
 
234
- <x-field data-name="data" data-type="TProductExpanded[]" data-desc="An array of product objects."></x-field>
235
-
236
- <x-field data-name="page" data-type="number" data-desc="The current page number."></x-field>
237
-
238
- <x-field data-name="pageSize" data-type="number" data-desc="The number of items per page."></x-field>
239
-
240
- <x-field data-name="total" data-type="number" data-desc="The total number of products matching the criteria."></x-field>
229
+ <x-field-group>
230
+ <x-field data-name="data" data-type="TProductExpanded[]" data-desc="An array of product objects."></x-field>
231
+ <x-field data-name="page" data-type="number" data-desc="The current page number."></x-field>
232
+ <x-field data-name="pageSize" data-type="number" data-desc="The number of items per page."></x-field>
233
+ <x-field data-name="total" data-type="number" data-desc="The total number of products matching the criteria."></x-field>
234
+ </x-field-group>
241
235
 
242
236
  **Example**
243
237
 
@@ -286,21 +280,20 @@
286
280
 
287
281
  **Parameters**
288
282
 
289
- <x-field data-name="query" data-type="string" data-required="true" data-desc="The search string to match against product fields."></x-field>
290
-
291
- <x-field data-name="page" data-type="number" data-default="1" data-required="false" data-desc="Optional. The page number for pagination (default: 1)."></x-field>
292
-
293
- <x-field data-name="pageSize" data-type="number" data-default="50" data-required="false" data-desc="Optional. The number of items per page (default: 50)."></x-field>
283
+ <x-field-group>
284
+ <x-field data-name="query" data-type="string" data-required="true" data-desc="The search string to match against product fields."></x-field>
285
+ <x-field data-name="page" data-type="number" data-default="1" data-required="false" data-desc="Optional. The page number for pagination (default: 1)."></x-field>
286
+ <x-field data-name="pageSize" data-type="number" data-default="50" data-required="false" data-desc="Optional. The number of items per page (default: 50)."></x-field>
287
+ </x-field-group>
294
288
 
295
289
  **Returns**
296
290
 
297
- <x-field data-name="data" data-type="TProductExpanded[]" data-desc="An array of product objects that match the search query."></x-field>
298
-
299
- <x-field data-name="page" data-type="number" data-desc="The current page number."></x-field>
300
-
301
- <x-field data-name="pageSize" data-type="number" data-desc="The number of items per page."></x-field>
302
-
303
- <x-field data-name="total" data-type="number" data-desc="The total number of products matching the criteria."></x-field>
291
+ <x-field-group>
292
+ <x-field data-name="data" data-type="TProductExpanded[]" data-desc="An array of product objects that match the search query."></x-field>
293
+ <x-field data-name="page" data-type="number" data-desc="The current page number."></x-field>
294
+ <x-field data-name="pageSize" data-type="number" data-desc="The number of items per page."></x-field>
295
+ <x-field data-name="total" data-type="number" data-desc="The total number of products matching the criteria."></x-field>
296
+ </x-field-group>
304
297
 
305
298
  **Example**
306
299
 
@@ -426,19 +419,19 @@
426
419
 
427
420
  **UserContext**
428
421
 
429
- <x-field data-name="user" data-type="object" data-required="true" data-desc="Current user information">
430
- <x-field data-name="id" data-type="string" data-required="true" data-desc="User unique identifier"></x-field>
431
- <x-field data-name="name" data-type="string" data-required="true" data-desc="User display name"></x-field>
432
- <x-field data-name="email" data-type="string" data-required="true" data-desc="User email address"></x-field>
433
- <x-field data-name="role" data-type="string" data-default="user" data-desc="User role (user, admin, moderator)"></x-field>
434
- </x-field>
435
-
436
- <x-field data-name="session" data-type="object" data-required="true" data-desc="Current session information">
437
- <x-field data-name="token" data-type="string" data-required="true" data-desc="Session authentication token"></x-field>
438
- <x-field data-name="expiresAt" data-type="number" data-required="true" data-desc="Session expiration timestamp"></x-field>
439
- </x-field>
440
-
441
- <x-field data-name="permissions" data-type="array" data-required="false" data-desc="User permissions list"></x-field>
422
+ <x-field-group>
423
+ <x-field data-name="user" data-type="object" data-required="true" data-desc="Current user information">
424
+ <x-field data-name="id" data-type="string" data-required="true" data-desc="User unique identifier"></x-field>
425
+ <x-field data-name="name" data-type="string" data-required="true" data-desc="User display name"></x-field>
426
+ <x-field data-name="email" data-type="string" data-required="true" data-desc="User email address"></x-field>
427
+ <x-field data-name="role" data-type="string" data-default="user" data-desc="User role (user, admin, moderator)"></x-field>
428
+ </x-field>
429
+ <x-field data-name="session" data-type="object" data-required="true" data-desc="Current session information">
430
+ <x-field data-name="token" data-type="string" data-required="true" data-desc="Session authentication token"></x-field>
431
+ <x-field data-name="expiresAt" data-type="number" data-required="true" data-desc="Session expiration timestamp"></x-field>
432
+ </x-field>
433
+ <x-field data-name="permissions" data-type="array" data-required="false" data-desc="User permissions list"></x-field>
434
+ </x-field-group>
442
435
 
443
436
  ---
444
437
 
@@ -16,6 +16,7 @@
16
16
  - 参数、返回值、上下文数据(Context)、Props 以及其它与类型相关的内容优先使用 `<x-field>` 自定义组件来展示,支持嵌套结构来清晰描述复杂数据类型
17
17
  - 对于复杂对象类型,使用嵌套的 `<x-field>` 结构来递归描述参数结构,嵌套层级不超过 5 级
18
18
  - 所有类型都使用开闭标签格式 `<x-field ...></x-field>`,简单类型 children 为空,复杂类型包含嵌套字段
19
+ - 描述同一个对象的多个最外层的 `<x-field>` 元素应该用 `<x-field-group>` 元素包裹。注意内嵌的 `<x-field>` 不需要包裹
19
20
  - 接口/方法调用的说明必须包含 **响应数据示例**
20
21
  - 对于其他类型的列表数据,数据内容简单,优先使用 markdown 中的 table 来展示,让内容看上去更整齐,容易阅读
21
22
  - 对输出的 markdown 进行检查,确认输出内容完整,table、d2 信息完整并且格式正确
@@ -2,30 +2,32 @@
2
2
  你是一位精通多种语言(尤其精通中文和英语)的专业翻译人员,擅长准确规范的双语转换。
3
3
  </role>
4
4
 
5
-
6
5
  <translation_rules>
7
6
  翻译要求:
7
+
8
8
  - **准确传达**原文的事实和背景,确保完整无遗漏。
9
9
  - **避免夸张**,避免使用带有情绪化和主观色彩的词语(例如“激动”、“震惊”等)。
10
10
  - **遵守语言规范**,确保标点符号和语法正确,表达自然流畅。
11
11
  - **保留原文结构**,仅翻译内容部分,不添加或修改标签,不添加额外内容或标点符号。不要在最外层添加 markdown 语法。确保翻译后结构和原文相同,原文中的换行、空白行也要保留。
12
- - **严格保护 Markdown 语法**:Markdown 的所有语法字符,包括但不限于表格中的 `|` 和 `-`、列表中的 `*` 和 `-`、标题的 `#`、代码块的 ``` ` ``` 等,都必须**原样复制**,不得进行任何形式的修改、增删或合并。特别是表格的分隔线(例如 `|---|---|---|`),必须与原文的列数和格式完全一致,且表格的分隔线与表格数据列数相同。
12
+ - **严格保护 Markdown 语法**:Markdown 的所有语法字符,包括但不限于表格中的 `|` 和 `-`、列表中的 `*` 和 `-`、标题的 `#`、代码块的 `` ` `` 等,都必须**原样复制**,不得进行任何形式的修改、增删或合并。特别是表格的分隔线(例如 `|---|---|---|`),必须与原文的列数和格式完全一致,且表格的分隔线与表格数据列数相同。
13
13
  - **遵循翻译流程**,包括直译、优化和检查遗漏,确保最终输出符合要求。
14
14
  - **使用术语参考**,确保专业术语的准确性和一致性。
15
15
  - **保留术语**,保留特定术语的原文形式,避免翻译。
16
16
 
17
17
  翻译过程:
18
+
18
19
  - **直译**:将原文逐字逐句翻译成目标语言,确保每个词语的含义都被准确传达。
19
20
  - **优化**:在直译结果的基础上,确保译文在忠实于原文含义的同时更加通俗易懂,并符合 **{{ language }}** 的表达习惯。
20
21
  - **检查遗漏**:将原文与直译结果进行比较,纠正任何歪曲原文含义或遗漏的信息。
21
22
  - **格式检查**:将原文与直译结果进行比较,确保翻译后的内容完整,如果原文是 markdown 格式,检查格式与原文相同。
22
23
  - **最终输出**:输出优化后的翻译结果,确保符合上述要求(不要输出直译内容)。
23
- </translation_rules>
24
+ </translation_rules>
24
25
 
25
26
  {% include "./glossary.md" %}
26
27
 
27
28
  保留术语(不翻译):
28
29
  <terms>
30
+
29
31
  - Agent(所有 Agent 或带有 Agent 前缀或后缀的术语均不翻译)
30
32
 
31
33
  {{glossary}}
@@ -33,9 +35,9 @@
33
35
 
34
36
  双语术语(使用 `原文 (翻译)` 格式):
35
37
  <bilingual-terms>
36
- - Guide Rails: 行为导轨
37
- </bilingual-terms>
38
38
 
39
+ - Guide Rails: 行为导轨
40
+ </bilingual-terms>
39
41
 
40
42
  <example>
41
43
  <before_translate>
@@ -62,11 +64,19 @@
62
64
  <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>
63
65
  </before_translate>
64
66
 
67
+ <x-field data-name="apiKey" data-type="string" data-required="true">
68
+ <x-field-desc markdown>Your **API key** for authentication. Generate one from the `Settings > API Keys` section.</x-field-desc>
69
+ </x-field>
70
+
65
71
  <after_translate>
66
72
  <x-field data-name="teamDid" data-type="string" data-required="true" data-desc="管理 Webhook 的团队或 Blocklet 的 DID。"></x-field>
73
+
74
+ <x-field data-name="apiKey" data-type="string" data-required="true">
75
+ <x-field-desc markdown>您的 **API 密钥**,用于身份验证。请从 `设置 > API 密钥` 部分生成一个。</x-field-desc>
76
+ </x-field>
67
77
  </after_translate>
68
78
 
69
- **特别注意**: x-field 组件的所有属性都需要保持原文格式,只翻译 data-desc 属性中的描述内容
79
+ **特别注意**: x-field 组件的所有属性都需要保持原文格式,只翻译 data-desc 属性中或 x-field-desc 元素中的描述内容
70
80
  </example>
71
81
 
72
82
  原文如下:
@@ -91,10 +101,11 @@
91
101
  {{userPreferences}}
92
102
 
93
103
  用户偏好使用规则:
104
+
94
105
  - 用户偏好来自用户之前操作中提供的反馈,生成结构规划中需要考虑用户的偏好,避免出现用户反馈的问题又重复出现
95
106
  - 用户偏好的权重低于本次用户提交的反馈
96
- </user_preferences>
97
- {% endif %}
107
+ </user_preferences>
108
+ {% endif %}
98
109
 
99
110
  指令:
100
- 请将 <content> 中的内容(不包含最外层的 <content> 标签) **准确** 地翻译成 **{{ language }}**,并严格遵循翻译要求。
111
+ 请将 <content> 中的内容(不包含最外层的 <content> 标签) **准确** 地翻译成 **{{ language }}**,并严格遵循翻译要求。
@@ -618,12 +618,6 @@ describe("generateYAML", () => {
618
618
  projectDesc: "",
619
619
  projectLogo: "",
620
620
  },
621
- {
622
- name: "Whitespace-only values",
623
- projectName: " ",
624
- projectDesc: "\n\n \t \n",
625
- projectLogo: " ",
626
- },
627
621
  {
628
622
  name: "Very long values",
629
623
  projectName: "a".repeat(200),
@@ -913,7 +907,7 @@ describe("generateYAML", () => {
913
907
  // Should always include these sections
914
908
  expect(result).toContain("# Project information for documentation publishing");
915
909
  expect(result).toContain("# Documentation Configuration");
916
- expect(result).toContain('"projectName":');
910
+ expect(result).toContain("projectName:");
917
911
  expect(result).toContain("documentPurpose:");
918
912
  expect(result).toContain("targetAudienceTypes:");
919
913
  expect(result).toContain("locale:");
@@ -1287,7 +1281,7 @@ describe("init", () => {
1287
1281
 
1288
1282
  // Config should be generated since original was empty
1289
1283
  const configContent = await fs.readFile(configPath, "utf8");
1290
- expect(configContent).toContain('"projectName":');
1284
+ expect(configContent).toContain("projectName:");
1291
1285
  expect(configContent).toContain("locale: en");
1292
1286
  } finally {
1293
1287
  await cleanupTempDir(tempDir);