@spaceflow/review 1.0.0 → 2.0.0
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review@0.83.0...@spaceflow/review@1.0.0) (2026-04-13)
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* **review:** 重构 example 数据结构,支持 `### Example:` 分组和 `#### Good:/Bad:` 标题语法
|
|
8
|
+
|
|
9
|
+
### 新特性
|
|
10
|
+
|
|
11
|
+
* **review:** 新增 includes 变更类型前缀语法支持 ([2f5655f](https://github.com/Lydanne/spaceflow/commit/2f5655fc414828ea3a0269fba04611d2bf2591a9))
|
|
12
|
+
* **review:** 重构 example 数据结构,支持 `### Example:` 分组和 `#### Good:/Bad:` 标题语法 ([e45bd5a](https://github.com/Lydanne/spaceflow/commit/e45bd5aab5e317b8f70a8b107c17aab6548c3296))
|
|
13
|
+
|
|
14
|
+
### 其他修改
|
|
15
|
+
|
|
16
|
+
* **review-summary:** released version 0.52.0 [no ci] ([1d0cdac](https://github.com/Lydanne/spaceflow/commit/1d0cdacdbe12db98399e69fd53bbfdd23825cc10))
|
|
17
|
+
|
|
3
18
|
## [0.83.0](https://github.com/Lydanne/spaceflow/compare/@spaceflow/review@0.82.0...@spaceflow/review@0.83.0) (2026-04-10)
|
|
4
19
|
|
|
5
20
|
### 代码重构
|
package/dist/index.js
CHANGED
|
@@ -305,7 +305,7 @@ const CODE_BLOCK_TYPES = [
|
|
|
305
305
|
function formatExample(example) {
|
|
306
306
|
let text = "";
|
|
307
307
|
if (example.title) {
|
|
308
|
-
text += `##### ${example.title}\n`;
|
|
308
|
+
text += `##### Example: ${example.title}\n`;
|
|
309
309
|
}
|
|
310
310
|
if (example.description) {
|
|
311
311
|
text += `${example.description}\n`;
|
|
@@ -903,13 +903,18 @@ class ReviewSpecService {
|
|
|
903
903
|
for (const groupSection of groupSections){
|
|
904
904
|
const trimmedGroup = groupSection.trim();
|
|
905
905
|
if (!trimmedGroup) continue;
|
|
906
|
-
//
|
|
906
|
+
// 提取分组标题和描述,如 "### Example: 函数行数"
|
|
907
907
|
let exampleTitle = "";
|
|
908
908
|
let exampleDescription = "";
|
|
909
909
|
const groupMatch = trimmedGroup.match(/^###\s+Example\s*[::]\s*(.+)/i);
|
|
910
910
|
if (groupMatch) {
|
|
911
|
-
exampleTitle =
|
|
912
|
-
|
|
911
|
+
exampleTitle = groupMatch[1].trim();
|
|
912
|
+
// 提取标题行和第一个 #### 之间的文本作为 description
|
|
913
|
+
const afterTitle = trimmedGroup.slice(trimmedGroup.indexOf("\n")).trim();
|
|
914
|
+
const firstSubIdx = afterTitle.search(/(?:^|\n)####\s+/);
|
|
915
|
+
if (firstSubIdx > 0) {
|
|
916
|
+
exampleDescription = afterTitle.slice(0, firstSubIdx).trim();
|
|
917
|
+
}
|
|
913
918
|
}
|
|
914
919
|
// 在分组内按 #### 提取 Good/Bad
|
|
915
920
|
const ruleContents = [];
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ export function buildSpecsSection(specs: ReviewSpec[]): string {
|
|
|
31
31
|
function formatExample(example: RuleExample): string {
|
|
32
32
|
let text = "";
|
|
33
33
|
if (example.title) {
|
|
34
|
-
text += `##### ${example.title}\n`;
|
|
34
|
+
text += `##### Example: ${example.title}\n`;
|
|
35
35
|
}
|
|
36
36
|
if (example.description) {
|
|
37
37
|
text += `${example.description}\n`;
|
|
@@ -1821,18 +1821,55 @@ const statusActive = "active";
|
|
|
1821
1821
|
expect(spec!.rules[1].examples).toHaveLength(2);
|
|
1822
1822
|
|
|
1823
1823
|
// 第一组
|
|
1824
|
-
expect(spec!.rules[1].examples[0].title).toBe("
|
|
1825
|
-
expect(spec!.rules[1].examples[0].description).toBe("
|
|
1824
|
+
expect(spec!.rules[1].examples[0].title).toBe("下面的明明规则说明");
|
|
1825
|
+
expect(spec!.rules[1].examples[0].description).toBe("");
|
|
1826
1826
|
expect(spec!.rules[1].examples[0].content).toHaveLength(2);
|
|
1827
1827
|
expect(spec!.rules[1].examples[0].content[0].type).toBe("good");
|
|
1828
1828
|
expect(spec!.rules[1].examples[0].content[1].type).toBe("bad");
|
|
1829
1829
|
|
|
1830
1830
|
// 第二组
|
|
1831
|
-
expect(spec!.rules[1].examples[1].title).toBe("
|
|
1832
|
-
expect(spec!.rules[1].examples[1].description).toBe("
|
|
1831
|
+
expect(spec!.rules[1].examples[1].title).toBe("另一种场景");
|
|
1832
|
+
expect(spec!.rules[1].examples[1].description).toBe("");
|
|
1833
1833
|
expect(spec!.rules[1].examples[1].content).toHaveLength(2);
|
|
1834
1834
|
expect(spec!.rules[1].examples[1].content[0].type).toBe("good");
|
|
1835
1835
|
expect(spec!.rules[1].examples[1].content[1].type).toBe("bad");
|
|
1836
1836
|
});
|
|
1837
|
+
|
|
1838
|
+
it("should parse Example with title and description paragraph", () => {
|
|
1839
|
+
const mockContent = `# 基础代码规范 \`[JsTs.Base]\`
|
|
1840
|
+
|
|
1841
|
+
## 函数行数限制 \`[JsTs.Base.FuncLines]\`
|
|
1842
|
+
|
|
1843
|
+
- 函数不能太长
|
|
1844
|
+
|
|
1845
|
+
### Example: 函数行数
|
|
1846
|
+
|
|
1847
|
+
例子说明 desc
|
|
1848
|
+
|
|
1849
|
+
#### Good: 函数不超过 200 行
|
|
1850
|
+
|
|
1851
|
+
\`\`\`javascript
|
|
1852
|
+
function getUserInfo() {
|
|
1853
|
+
// ... 小于等于 200
|
|
1854
|
+
}
|
|
1855
|
+
\`\`\`
|
|
1856
|
+
|
|
1857
|
+
#### Bad: 函数超过 200 行
|
|
1858
|
+
|
|
1859
|
+
\`\`\`javascript
|
|
1860
|
+
function getUserInfo() {
|
|
1861
|
+
// ... 大于 200
|
|
1862
|
+
}
|
|
1863
|
+
\`\`\``;
|
|
1864
|
+
|
|
1865
|
+
const spec = service.parseSpecFile("js&ts.base.md", mockContent);
|
|
1866
|
+
expect(spec).not.toBeNull();
|
|
1867
|
+
expect(spec!.rules[1].examples).toHaveLength(1);
|
|
1868
|
+
expect(spec!.rules[1].examples[0].title).toBe("函数行数");
|
|
1869
|
+
expect(spec!.rules[1].examples[0].description).toBe("例子说明 desc");
|
|
1870
|
+
expect(spec!.rules[1].examples[0].content).toHaveLength(2);
|
|
1871
|
+
expect(spec!.rules[1].examples[0].content[0].type).toBe("good");
|
|
1872
|
+
expect(spec!.rules[1].examples[0].content[0].title).toBe("函数不超过 200 行");
|
|
1873
|
+
});
|
|
1837
1874
|
});
|
|
1838
1875
|
});
|
|
@@ -694,13 +694,18 @@ export class ReviewSpecService {
|
|
|
694
694
|
const trimmedGroup = groupSection.trim();
|
|
695
695
|
if (!trimmedGroup) continue;
|
|
696
696
|
|
|
697
|
-
//
|
|
697
|
+
// 提取分组标题和描述,如 "### Example: 函数行数"
|
|
698
698
|
let exampleTitle = "";
|
|
699
699
|
let exampleDescription = "";
|
|
700
700
|
const groupMatch = trimmedGroup.match(/^###\s+Example\s*[::]\s*(.+)/i);
|
|
701
701
|
if (groupMatch) {
|
|
702
|
-
exampleTitle =
|
|
703
|
-
|
|
702
|
+
exampleTitle = groupMatch[1].trim();
|
|
703
|
+
// 提取标题行和第一个 #### 之间的文本作为 description
|
|
704
|
+
const afterTitle = trimmedGroup.slice(trimmedGroup.indexOf("\n")).trim();
|
|
705
|
+
const firstSubIdx = afterTitle.search(/(?:^|\n)####\s+/);
|
|
706
|
+
if (firstSubIdx > 0) {
|
|
707
|
+
exampleDescription = afterTitle.slice(0, firstSubIdx).trim();
|
|
708
|
+
}
|
|
704
709
|
}
|
|
705
710
|
|
|
706
711
|
// 在分组内按 #### 提取 Good/Bad
|