docspec 0.1.0 → 0.3.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/README.md +69 -51
- package/dist/__tests__/changed.test.d.ts +2 -0
- package/dist/__tests__/changed.test.d.ts.map +1 -0
- package/dist/__tests__/changed.test.js +98 -0
- package/dist/__tests__/changed.test.js.map +1 -0
- package/dist/__tests__/cli.test.js +38 -158
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/__tests__/constants.test.js +8 -18
- package/dist/__tests__/constants.test.js.map +1 -1
- package/dist/__tests__/create.test.d.ts +2 -0
- package/dist/__tests__/create.test.d.ts.map +1 -0
- package/dist/__tests__/create.test.js +122 -0
- package/dist/__tests__/create.test.js.map +1 -0
- package/dist/__tests__/generate.test.d.ts +2 -0
- package/dist/__tests__/generate.test.d.ts.map +1 -0
- package/dist/__tests__/generate.test.js +113 -0
- package/dist/__tests__/generate.test.js.map +1 -0
- package/dist/__tests__/generator.test.js +36 -32
- package/dist/__tests__/generator.test.js.map +1 -1
- package/dist/__tests__/path-utils.test.d.ts +2 -0
- package/dist/__tests__/path-utils.test.d.ts.map +1 -0
- package/dist/__tests__/path-utils.test.js +49 -0
- package/dist/__tests__/path-utils.test.js.map +1 -0
- package/dist/__tests__/template.test.d.ts +2 -0
- package/dist/__tests__/template.test.d.ts.map +1 -0
- package/dist/__tests__/template.test.js +95 -0
- package/dist/__tests__/template.test.js.map +1 -0
- package/dist/__tests__/validator.test.js +50 -94
- package/dist/__tests__/validator.test.js.map +1 -1
- package/dist/changed.d.ts +25 -0
- package/dist/changed.d.ts.map +1 -0
- package/dist/changed.js +210 -0
- package/dist/changed.js.map +1 -0
- package/dist/cli.js +89 -73
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts +5 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +155 -40
- package/dist/constants.js.map +1 -1
- package/dist/create.d.ts +12 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +93 -0
- package/dist/create.js.map +1 -0
- package/dist/docspec-changed.d.ts +25 -0
- package/dist/docspec-changed.d.ts.map +1 -0
- package/dist/docspec-changed.js +210 -0
- package/dist/docspec-changed.js.map +1 -0
- package/dist/docspec-generate.d.ts +22 -0
- package/dist/docspec-generate.d.ts.map +1 -0
- package/dist/docspec-generate.js +171 -0
- package/dist/docspec-generate.js.map +1 -0
- package/dist/format-parser.d.ts +24 -0
- package/dist/format-parser.d.ts.map +1 -0
- package/dist/format-parser.js +205 -0
- package/dist/format-parser.js.map +1 -0
- package/dist/generate.d.ts +26 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +175 -0
- package/dist/generate.js.map +1 -0
- package/dist/generator.d.ts +6 -6
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +38 -26
- package/dist/generator.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +40 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +74 -0
- package/dist/logger.js.map +1 -0
- package/dist/path-utils.d.ts +17 -0
- package/dist/path-utils.d.ts.map +1 -0
- package/dist/path-utils.js +76 -0
- package/dist/path-utils.js.map +1 -0
- package/dist/template.d.ts +20 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +151 -0
- package/dist/template.js.map +1 -0
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +39 -1
- package/dist/validator.js.map +1 -1
- package/docspec-format.md +45 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# docspec
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Docspec is a specification format and toolchain for documentation that is maintained by agents. **Docspec does not run an LLM**—it produces prompt output that you feed into your own LLM CLI (e.g. Claude, Codex).
|
|
4
|
+
|
|
5
|
+
Docspec files live under **`.docspec/`**. For a markdown file `README.md` or `docs/deploy.md`, the docspec is `.docspec/README.docspec.md` or `.docspec/docs/deploy.docspec.md` respectively.
|
|
6
|
+
|
|
7
|
+
The **format template** is fully up to you: it lives at **`.docspec/docspec.md`**. If you run any docspec command and `.docspec/docspec.md` does not exist, it is seeded from the bundled default (the content of `docspec-format.md` in this repo). Edit `.docspec/docspec.md` to define your own structure.
|
|
8
|
+
|
|
9
|
+
## The Docspec Format
|
|
10
|
+
|
|
11
|
+
Each `*.docspec.md` file is a specification for another document. The **default** format (used when seeding) is defined in [`docspec-format.md`](docspec-format.md). After seeding, your project uses `.docspec/docspec.md`, which you can change.
|
|
12
|
+
|
|
13
|
+
The default includes 5 sections: Document Purpose, Update Triggers, Expected Structure, Editing Guidelines, Intentional Omissions. Customize the template in `.docspec/docspec.md` to match your needs.
|
|
4
14
|
|
|
5
15
|
## Installation
|
|
6
16
|
|
|
@@ -18,82 +28,91 @@ npm install -g docspec
|
|
|
18
28
|
|
|
19
29
|
### CLI Commands
|
|
20
30
|
|
|
21
|
-
####
|
|
31
|
+
#### Generate a docspec file (default)
|
|
22
32
|
|
|
23
|
-
|
|
33
|
+
Pass a markdown file path to create (or overwrite) its docspec under `.docspec/`:
|
|
24
34
|
|
|
25
35
|
```bash
|
|
26
|
-
docspec
|
|
36
|
+
docspec README.md
|
|
37
|
+
docspec docs/deploy.md
|
|
27
38
|
```
|
|
28
39
|
|
|
29
|
-
|
|
40
|
+
This creates `.docspec/README.docspec.md` and `.docspec/docs/deploy.docspec.md` using the template at `.docspec/docspec.md` (seeded from the default on first run).
|
|
30
41
|
|
|
31
|
-
|
|
32
|
-
docspec validate
|
|
33
|
-
```
|
|
42
|
+
#### docspec changed (prompt for syncing docs after changes)
|
|
34
43
|
|
|
35
|
-
|
|
44
|
+
Produce a prompt file that instructs an LLM to sync markdown files with their docspecs given a list of changed files or a git diff:
|
|
36
45
|
|
|
37
46
|
```bash
|
|
38
|
-
docspec
|
|
47
|
+
docspec changed --base <base_sha> --merge <merge_sha> --output prompt.txt
|
|
48
|
+
docspec changed --changed-files "src/foo.ts,README.md" --output prompt.txt
|
|
39
49
|
```
|
|
40
50
|
|
|
41
|
-
|
|
51
|
+
Options: `--max-docspecs`, `--max-diff-chars`. Default output file: `prompt.txt`.
|
|
52
|
+
|
|
53
|
+
#### docspec generate (docspec + prompt for LLM)
|
|
54
|
+
|
|
55
|
+
Generate a new docspec for a markdown file and write a prompt you can feed to your LLM to fill or improve it:
|
|
42
56
|
|
|
43
57
|
```bash
|
|
44
|
-
docspec generate
|
|
58
|
+
docspec generate README.md --output-prompt prompt.txt
|
|
59
|
+
docspec generate docs/deploy.md --overwrite --output-prompt prompt.txt
|
|
45
60
|
```
|
|
46
61
|
|
|
47
|
-
|
|
62
|
+
Use `--overwrite` to replace an existing docspec. Optionally `--output-plan <file>` to write a separate plan prompt.
|
|
48
63
|
|
|
49
|
-
|
|
50
|
-
import { validateDocspec, generateDocspec } from "docspec";
|
|
64
|
+
Add the `--verbose` flag to any command for detailed logging.
|
|
51
65
|
|
|
52
|
-
|
|
53
|
-
const result = await validateDocspec("path/to/file.docspec.md");
|
|
54
|
-
if (!result.valid) {
|
|
55
|
-
console.error("Validation errors:", result.errors);
|
|
56
|
-
}
|
|
66
|
+
### Library Usage
|
|
57
67
|
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
```typescript
|
|
69
|
+
import {
|
|
70
|
+
generateDocspec,
|
|
71
|
+
buildDocspecChangedPrompt,
|
|
72
|
+
buildDocspecGeneratePrompts,
|
|
73
|
+
markdownToDocspecPath,
|
|
74
|
+
docspecToMarkdownPath,
|
|
75
|
+
} from "docspec";
|
|
76
|
+
|
|
77
|
+
// Generate a docspec for a markdown file (writes to .docspec/<path>.docspec.md)
|
|
78
|
+
await generateDocspec("README.md");
|
|
79
|
+
|
|
80
|
+
// Build prompt for docspec changed (e.g. for CI)
|
|
81
|
+
const { prompt, outputPath } = await buildDocspecChangedPrompt({
|
|
82
|
+
base: "abc123",
|
|
83
|
+
merge: "def456",
|
|
84
|
+
outputPath: "prompt.txt",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Build prompts for docspec generate
|
|
88
|
+
const { implPrompt } = await buildDocspecGeneratePrompts({
|
|
89
|
+
markdownPath: "README.md",
|
|
90
|
+
outputPromptPath: "prompt.txt",
|
|
91
|
+
});
|
|
60
92
|
```
|
|
61
93
|
|
|
62
|
-
|
|
94
|
+
The library also exports: `generateDocspecContent()`, `REQUIRED_SECTIONS`, `SECTION_BOILERPLATE`, `logger`, `LogLevel`, `isDocspecPath`, and types `DocspecChangedOptions`, `DocspecGenerateOptions`.
|
|
63
95
|
|
|
64
|
-
|
|
96
|
+
## GitHub Actions
|
|
65
97
|
|
|
66
|
-
|
|
67
|
-
repos:
|
|
68
|
-
- repo: local
|
|
69
|
-
hooks:
|
|
70
|
-
- id: docspec-validate
|
|
71
|
-
name: Validate docspec files
|
|
72
|
-
entry: docspec validate
|
|
73
|
-
language: system
|
|
74
|
-
files: \.docspec\.md$
|
|
75
|
-
pass_filenames: true
|
|
76
|
-
```
|
|
98
|
+
Docspec’s actions **only produce prompt files**; they do not run an LLM or require API keys.
|
|
77
99
|
|
|
78
|
-
|
|
100
|
+
- **docspec-changed** (`.github/actions/docspec-check`) – Runs `docspec changed` and writes a prompt file. Outputs `prompt_file` and `has_prompt`.
|
|
101
|
+
- **docspec-generate** (`.github/actions/docspec-generate`) – Runs `docspec generate <markdown_file>` and writes a prompt file.
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
pre-commit install
|
|
82
|
-
```
|
|
103
|
+
### Example: run docspec changed then Claude
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
This repo’s [`.github/workflows/docspec-check.yml`](.github/workflows/docspec-check.yml) runs when a PR is merged: it prepares the prompt with `docspec changed`, then runs the [official Claude Code Action](https://github.com/anthropics/claude-code-action) with that prompt. Add `ANTHROPIC_API_KEY` to your repository secrets if you want the Claude step to run.
|
|
85
106
|
|
|
86
|
-
|
|
107
|
+
### Example: docspec generate (prompt only)
|
|
87
108
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Each section must be customized and cannot contain only the boilerplate template text.
|
|
109
|
+
```yaml
|
|
110
|
+
- uses: actions/checkout@v4
|
|
111
|
+
- uses: docspec-ai/docspec/.github/actions/docspec-generate@main
|
|
112
|
+
with:
|
|
113
|
+
markdown_file: README.md
|
|
114
|
+
overwrite: false
|
|
115
|
+
```
|
|
97
116
|
|
|
98
117
|
## Development
|
|
99
118
|
|
|
@@ -118,4 +137,3 @@ npm run build
|
|
|
118
137
|
## License
|
|
119
138
|
|
|
120
139
|
MIT
|
|
121
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changed.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/changed.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("fs/promises"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const changed_1 = require("../changed");
|
|
40
|
+
describe("changed", () => {
|
|
41
|
+
let tempDir;
|
|
42
|
+
let originalCwd;
|
|
43
|
+
beforeEach(async () => {
|
|
44
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "docspec-changed-test-"));
|
|
45
|
+
originalCwd = process.cwd();
|
|
46
|
+
process.chdir(tempDir);
|
|
47
|
+
});
|
|
48
|
+
afterEach(async () => {
|
|
49
|
+
process.chdir(originalCwd);
|
|
50
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
51
|
+
});
|
|
52
|
+
it("returns empty prompt when no docspecs match changed files", async () => {
|
|
53
|
+
await fs.mkdir(path.join(tempDir, ".docspec", "sub"), { recursive: true });
|
|
54
|
+
await fs.writeFile(path.join(tempDir, ".docspec", "sub", "bar.docspec.md"), "# DOCSPEC: bar\n\n## 1. Purpose\n\n", "utf-8");
|
|
55
|
+
await fs.mkdir(path.join(tempDir, "sub"), { recursive: true });
|
|
56
|
+
await fs.writeFile(path.join(tempDir, "sub", "bar.md"), "# Bar", "utf-8");
|
|
57
|
+
await fs.writeFile(path.join(tempDir, "root-only.js"), "code", "utf-8");
|
|
58
|
+
const { prompt } = await (0, changed_1.buildDocspecChangedPrompt)({
|
|
59
|
+
changedFiles: ["root-only.js"],
|
|
60
|
+
repoRoot: tempDir,
|
|
61
|
+
});
|
|
62
|
+
expect(prompt).toBe("");
|
|
63
|
+
});
|
|
64
|
+
it("builds prompt when changed file is the target markdown of a docspec", async () => {
|
|
65
|
+
await fs.mkdir(path.join(tempDir, ".docspec"), { recursive: true });
|
|
66
|
+
const docspecContent = "# DOCSPEC: [foo.md](/foo.md)\n\n## 1. Purpose\n\nDescribe foo.";
|
|
67
|
+
await fs.writeFile(path.join(tempDir, ".docspec", "foo.docspec.md"), docspecContent, "utf-8");
|
|
68
|
+
await fs.writeFile(path.join(tempDir, "foo.md"), "# Foo content", "utf-8");
|
|
69
|
+
const { prompt, outputPath } = await (0, changed_1.buildDocspecChangedPrompt)({
|
|
70
|
+
changedFiles: ["foo.md"],
|
|
71
|
+
repoRoot: tempDir,
|
|
72
|
+
});
|
|
73
|
+
expect(prompt).toContain("<diff>");
|
|
74
|
+
expect(prompt).toContain("## Docspec: .docspec/foo.docspec.md");
|
|
75
|
+
expect(prompt).toContain("Target markdown: foo.md");
|
|
76
|
+
expect(prompt).toContain("<docspec>");
|
|
77
|
+
expect(prompt).toContain(docspecContent);
|
|
78
|
+
expect(prompt).toContain("<markdown>");
|
|
79
|
+
expect(prompt).toContain("# Foo content");
|
|
80
|
+
expect(prompt).toContain("Task:");
|
|
81
|
+
expect(outputPath).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
it("writes prompt to outputPath when provided", async () => {
|
|
84
|
+
await fs.mkdir(path.join(tempDir, ".docspec"), { recursive: true });
|
|
85
|
+
await fs.writeFile(path.join(tempDir, ".docspec", "bar.docspec.md"), "# DOCSPEC: bar\n\n## 1. Purpose\n\n", "utf-8");
|
|
86
|
+
await fs.writeFile(path.join(tempDir, "bar.md"), "# Bar", "utf-8");
|
|
87
|
+
const { prompt, outputPath } = await (0, changed_1.buildDocspecChangedPrompt)({
|
|
88
|
+
changedFiles: ["bar.md"],
|
|
89
|
+
repoRoot: tempDir,
|
|
90
|
+
outputPath: "out/prompt.txt",
|
|
91
|
+
});
|
|
92
|
+
expect(prompt.length).toBeGreaterThan(0);
|
|
93
|
+
expect(outputPath).toBe(path.join(tempDir, "out", "prompt.txt"));
|
|
94
|
+
const written = await fs.readFile(path.join(tempDir, "out", "prompt.txt"), "utf-8");
|
|
95
|
+
expect(written).toBe(prompt);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=changed.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changed.test.js","sourceRoot":"","sources":["../../src/__tests__/changed.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,7 +38,6 @@ const path = __importStar(require("path"));
|
|
|
38
38
|
const os = __importStar(require("os"));
|
|
39
39
|
const child_process_1 = require("child_process");
|
|
40
40
|
const util_1 = require("util");
|
|
41
|
-
const generator_1 = require("../generator");
|
|
42
41
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
43
42
|
describe("CLI", () => {
|
|
44
43
|
let tempDir;
|
|
@@ -66,177 +65,57 @@ describe("CLI", () => {
|
|
|
66
65
|
};
|
|
67
66
|
}
|
|
68
67
|
};
|
|
69
|
-
describe("
|
|
70
|
-
it("should
|
|
71
|
-
const
|
|
72
|
-
const validContent = `---
|
|
73
|
-
|
|
74
|
-
# DOCSPEC: Test
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 1. Purpose of This Document
|
|
79
|
-
|
|
80
|
-
This document serves as a test case for the CLI validation command. It contains custom content that is different from the boilerplate template and sufficient to pass validation.
|
|
81
|
-
|
|
82
|
-
## 2. When This Document Should Be Updated
|
|
83
|
-
|
|
84
|
-
This document should be updated when testing CLI validation functionality. The content is meaningful and customized for testing purposes.
|
|
85
|
-
|
|
86
|
-
## 3. Structure & Required Sections
|
|
87
|
-
|
|
88
|
-
This section describes the structure of the test document. It includes all required sections with adequate content to pass validation checks.
|
|
89
|
-
|
|
90
|
-
## 4. Style & Editing Guidelines
|
|
91
|
-
|
|
92
|
-
The style for this test document is straightforward and technical. It focuses on clarity and precision in describing test scenarios. Do: Ensure all sections have adequate content. Don't: Use boilerplate text or leave sections empty. Always provide meaningful test data.
|
|
93
|
-
|
|
94
|
-
## 5. Known Gaps or Intentional Omissions
|
|
95
|
-
|
|
96
|
-
There are no known gaps in this test document. All sections are complete and properly formatted with sufficient content.
|
|
97
|
-
`;
|
|
98
|
-
await fs.writeFile(filePath, validContent, "utf-8");
|
|
99
|
-
const result = await runCli(`validate ${filePath}`);
|
|
68
|
+
describe("default command (docspec <markdown_path>)", () => {
|
|
69
|
+
it("should seed .docspec/docspec.md from default when missing", async () => {
|
|
70
|
+
const result = await runCli("seed-test.md");
|
|
100
71
|
expect(result.code).toBe(0);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
expect(result.code).toBe(1);
|
|
108
|
-
const output = result.stdout + result.stderr;
|
|
109
|
-
expect(output).toContain("❌");
|
|
110
|
-
expect(output).toContain("boilerplate");
|
|
111
|
-
});
|
|
112
|
-
it("should validate multiple files", async () => {
|
|
113
|
-
const file1 = path.join(tempDir, "file1.docspec.md");
|
|
114
|
-
const file2 = path.join(tempDir, "file2.docspec.md");
|
|
115
|
-
const validContent = `---
|
|
116
|
-
|
|
117
|
-
# DOCSPEC: Test
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## 1. Purpose of This Document
|
|
122
|
-
|
|
123
|
-
This document serves as a test case for validating multiple docspec files. It contains custom content that is different from the boilerplate template.
|
|
124
|
-
|
|
125
|
-
## 2. When This Document Should Be Updated
|
|
126
|
-
|
|
127
|
-
This document should be updated when testing multiple file validation. The content is meaningful and customized for testing purposes.
|
|
128
|
-
|
|
129
|
-
## 3. Structure & Required Sections
|
|
130
|
-
|
|
131
|
-
This section describes the structure of the test document. It includes all required sections with adequate content to pass validation checks.
|
|
132
|
-
|
|
133
|
-
## 4. Style & Editing Guidelines
|
|
134
|
-
|
|
135
|
-
The style for this test document is straightforward and technical. It focuses on clarity and precision in describing test scenarios. Do: Ensure all sections have adequate content. Don't: Use boilerplate text or leave sections empty. Always provide meaningful test data.
|
|
136
|
-
|
|
137
|
-
## 5. Known Gaps or Intentional Omissions
|
|
138
|
-
|
|
139
|
-
There are no known gaps in this test document. All sections are complete and properly formatted with sufficient content.
|
|
140
|
-
`;
|
|
141
|
-
await fs.writeFile(file1, validContent, "utf-8");
|
|
142
|
-
await fs.writeFile(file2, validContent, "utf-8");
|
|
143
|
-
const result = await runCli(`validate ${file1} ${file2}`);
|
|
144
|
-
expect(result.code).toBe(0);
|
|
145
|
-
expect(result.stdout).toContain("file1.docspec.md");
|
|
146
|
-
expect(result.stdout).toContain("file2.docspec.md");
|
|
72
|
+
const templatePath = path.join(tempDir, ".docspec", "docspec.md");
|
|
73
|
+
const templateExists = await fs.access(templatePath).then(() => true).catch(() => false);
|
|
74
|
+
expect(templateExists).toBe(true);
|
|
75
|
+
const content = await fs.readFile(templatePath, "utf-8");
|
|
76
|
+
expect(content).toContain("Document Purpose");
|
|
77
|
+
expect(content).toContain("{{TARGET_FILE}}");
|
|
147
78
|
});
|
|
148
|
-
it("should
|
|
149
|
-
const
|
|
150
|
-
const file2 = path.join(tempDir, "nested", "file2.docspec.md");
|
|
151
|
-
await fs.mkdir(path.join(tempDir, "nested"), { recursive: true });
|
|
152
|
-
const validContent = `---
|
|
153
|
-
|
|
154
|
-
# DOCSPEC: Test
|
|
155
|
-
|
|
156
|
-
---
|
|
157
|
-
|
|
158
|
-
## 1. Purpose of This Document
|
|
159
|
-
|
|
160
|
-
This document serves as a test case for validating multiple docspec files. It contains custom content that is different from the boilerplate template.
|
|
161
|
-
|
|
162
|
-
## 2. When This Document Should Be Updated
|
|
163
|
-
|
|
164
|
-
This document should be updated when testing multiple file validation. The content is meaningful and customized for testing purposes.
|
|
165
|
-
|
|
166
|
-
## 3. Structure & Required Sections
|
|
167
|
-
|
|
168
|
-
This section describes the structure of the test document. It includes all required sections with adequate content to pass validation checks.
|
|
169
|
-
|
|
170
|
-
## 4. Style & Editing Guidelines
|
|
171
|
-
|
|
172
|
-
The style for this test document is straightforward and technical. It focuses on clarity and precision in describing test scenarios. Do: Ensure all sections have adequate content. Don't: Use boilerplate text or leave sections empty. Always provide meaningful test data.
|
|
173
|
-
|
|
174
|
-
## 5. Known Gaps or Intentional Omissions
|
|
175
|
-
|
|
176
|
-
There are no known gaps in this test document. All sections are complete and properly formatted with sufficient content.
|
|
177
|
-
`;
|
|
178
|
-
await fs.writeFile(file1, validContent, "utf-8");
|
|
179
|
-
await fs.writeFile(file2, validContent, "utf-8");
|
|
180
|
-
const result = await runCli("validate");
|
|
181
|
-
expect(result.code).toBe(0);
|
|
182
|
-
expect(result.stdout).toContain("file1.docspec.md");
|
|
183
|
-
expect(result.stdout).toContain("file2.docspec.md");
|
|
184
|
-
});
|
|
185
|
-
it("should handle non-existent files gracefully", async () => {
|
|
186
|
-
const result = await runCli("validate nonexistent.docspec.md");
|
|
187
|
-
expect(result.code).toBe(1);
|
|
188
|
-
const output = result.stdout + result.stderr;
|
|
189
|
-
expect(output).toContain("Failed to read file");
|
|
190
|
-
});
|
|
191
|
-
it("should skip node_modules and .git directories", async () => {
|
|
192
|
-
await fs.mkdir(path.join(tempDir, "node_modules"), { recursive: true });
|
|
193
|
-
await fs.mkdir(path.join(tempDir, ".git"), { recursive: true });
|
|
194
|
-
const fileInNodeModules = path.join(tempDir, "node_modules", "test.docspec.md");
|
|
195
|
-
const fileInGit = path.join(tempDir, ".git", "test.docspec.md");
|
|
196
|
-
await fs.writeFile(fileInNodeModules, "test", "utf-8");
|
|
197
|
-
await fs.writeFile(fileInGit, "test", "utf-8");
|
|
198
|
-
const result = await runCli("validate");
|
|
199
|
-
// Should not find files in node_modules or .git
|
|
200
|
-
expect(result.stdout).not.toContain("node_modules");
|
|
201
|
-
expect(result.stdout).not.toContain(".git");
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
describe("generate command", () => {
|
|
205
|
-
it("should generate a new docspec file", async () => {
|
|
206
|
-
const filePath = path.join(tempDir, "new.docspec.md");
|
|
207
|
-
const result = await runCli(`generate ${filePath} --name "Test Document"`);
|
|
79
|
+
it("should generate a new docspec file under .docspec/ for markdown path", async () => {
|
|
80
|
+
const result = await runCli("new.md");
|
|
208
81
|
expect(result.code).toBe(0);
|
|
209
82
|
expect(result.stdout).toContain("✅");
|
|
210
|
-
expect(result.stdout).toContain("new.docspec.md");
|
|
83
|
+
expect(result.stdout).toContain(".docspec/new.docspec.md");
|
|
84
|
+
const filePath = path.join(tempDir, ".docspec", "new.docspec.md");
|
|
211
85
|
const exists = await fs.access(filePath).then(() => true).catch(() => false);
|
|
212
86
|
expect(exists).toBe(true);
|
|
213
87
|
});
|
|
214
88
|
it("should generate file with correct content", async () => {
|
|
215
|
-
|
|
216
|
-
|
|
89
|
+
await runCli("test.md");
|
|
90
|
+
const filePath = path.join(tempDir, ".docspec", "test.docspec.md");
|
|
217
91
|
const content = await fs.readFile(filePath, "utf-8");
|
|
218
|
-
expect(content).toContain("# DOCSPEC:
|
|
219
|
-
expect(content).toContain("Purpose
|
|
220
|
-
});
|
|
221
|
-
it("should auto-append .docspec.md if not present", async () => {
|
|
222
|
-
const filePath = path.join(tempDir, "test");
|
|
223
|
-
await runCli(`generate ${filePath} --name "Test"`);
|
|
224
|
-
const fullPath = filePath + ".docspec.md";
|
|
225
|
-
const exists = await fs.access(fullPath).then(() => true).catch(() => false);
|
|
226
|
-
expect(exists).toBe(true);
|
|
92
|
+
expect(content).toContain("# DOCSPEC: [test.md](/test.md)");
|
|
93
|
+
expect(content).toContain("Document Purpose");
|
|
227
94
|
});
|
|
228
|
-
it("should create nested directories", async () => {
|
|
229
|
-
const
|
|
230
|
-
const result = await runCli(`generate ${filePath} --name "Test"`);
|
|
95
|
+
it("should create nested directories under .docspec/", async () => {
|
|
96
|
+
const result = await runCli("nested/deep/test.md");
|
|
231
97
|
expect(result.code).toBe(0);
|
|
98
|
+
const filePath = path.join(tempDir, ".docspec", "nested", "deep", "test.docspec.md");
|
|
232
99
|
const exists = await fs.access(filePath).then(() => true).catch(() => false);
|
|
233
100
|
expect(exists).toBe(true);
|
|
234
101
|
});
|
|
235
|
-
it("should
|
|
236
|
-
|
|
237
|
-
|
|
102
|
+
it("should generate link to target markdown file", async () => {
|
|
103
|
+
await runCli("my-awesome-doc.md");
|
|
104
|
+
const filePath = path.join(tempDir, ".docspec", "my-awesome-doc.docspec.md");
|
|
238
105
|
const content = await fs.readFile(filePath, "utf-8");
|
|
239
|
-
expect(content).toContain("# DOCSPEC:
|
|
106
|
+
expect(content).toContain("# DOCSPEC: [my-awesome-doc.md](/my-awesome-doc.md)");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("generate subcommand (file + prompt)", () => {
|
|
110
|
+
it("should generate docspec and write prompt file", async () => {
|
|
111
|
+
await fs.writeFile(path.join(tempDir, "README.md"), "# Hello", "utf-8");
|
|
112
|
+
const result = await runCli("generate README.md --output-prompt prompt.txt");
|
|
113
|
+
expect(result.code).toBe(0);
|
|
114
|
+
expect(result.stdout).toContain(".docspec/README.docspec.md");
|
|
115
|
+
expect(result.stdout).toContain("prompt");
|
|
116
|
+
const promptPath = path.join(tempDir, "prompt.txt");
|
|
117
|
+
const exists = await fs.access(promptPath).then(() => true).catch(() => false);
|
|
118
|
+
expect(exists).toBe(true);
|
|
240
119
|
});
|
|
241
120
|
});
|
|
242
121
|
describe("help and version", () => {
|
|
@@ -244,8 +123,9 @@ There are no known gaps in this test document. All sections are complete and pro
|
|
|
244
123
|
const result = await runCli("--help");
|
|
245
124
|
expect(result.code).toBe(0);
|
|
246
125
|
expect(result.stdout).toContain("Usage:");
|
|
247
|
-
expect(result.stdout).toContain("
|
|
126
|
+
expect(result.stdout).toContain("changed");
|
|
248
127
|
expect(result.stdout).toContain("generate");
|
|
128
|
+
expect(result.stdout).toContain("markdown_path");
|
|
249
129
|
});
|
|
250
130
|
it("should show version", async () => {
|
|
251
131
|
const result = await runCli("--version");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAkC;AAClC,2CAA6B;AAC7B,uCAAyB;AACzB,iDAAqC;AACrC,+BAAiC;
|
|
1
|
+
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,11 +8,11 @@ describe("constants", () => {
|
|
|
8
8
|
});
|
|
9
9
|
it("should contain all expected section names", () => {
|
|
10
10
|
const expectedSections = [
|
|
11
|
-
"Purpose
|
|
12
|
-
"
|
|
13
|
-
"Structure
|
|
14
|
-
"
|
|
15
|
-
"
|
|
11
|
+
"Document Purpose",
|
|
12
|
+
"Update Triggers",
|
|
13
|
+
"Expected Structure",
|
|
14
|
+
"Editing Guidelines",
|
|
15
|
+
"Intentional Omissions",
|
|
16
16
|
];
|
|
17
17
|
expectedSections.forEach((section) => {
|
|
18
18
|
expect(constants_1.REQUIRED_SECTIONS).toContain(section);
|
|
@@ -28,9 +28,9 @@ describe("constants", () => {
|
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
describe("getDocspecTemplate", () => {
|
|
31
|
-
it("should generate a template with
|
|
32
|
-
const template = (0, constants_1.getDocspecTemplate)("
|
|
33
|
-
expect(template).toContain("# DOCSPEC:
|
|
31
|
+
it("should generate a template with link to target file", () => {
|
|
32
|
+
const template = (0, constants_1.getDocspecTemplate)("README.md");
|
|
33
|
+
expect(template).toContain("# DOCSPEC: [README.md](/README.md)");
|
|
34
34
|
});
|
|
35
35
|
it("should include all 5 required sections", () => {
|
|
36
36
|
const template = (0, constants_1.getDocspecTemplate)("Test");
|
|
@@ -52,16 +52,6 @@ describe("constants", () => {
|
|
|
52
52
|
expect(template).toContain(boilerplate.split("\n")[0]);
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
|
-
it("should include separators between sections", () => {
|
|
56
|
-
const template = (0, constants_1.getDocspecTemplate)("Test");
|
|
57
|
-
// Should have separators for 5 sections
|
|
58
|
-
const separatorCount = (template.match(/^---$/gm) || []).length;
|
|
59
|
-
expect(separatorCount).toBeGreaterThanOrEqual(2); // At least front matter and between sections
|
|
60
|
-
});
|
|
61
|
-
it("should have proper front matter format", () => {
|
|
62
|
-
const template = (0, constants_1.getDocspecTemplate)("Test");
|
|
63
|
-
expect(template).toMatch(/^---\n/);
|
|
64
|
-
});
|
|
65
55
|
});
|
|
66
56
|
});
|
|
67
57
|
//# sourceMappingURL=constants.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.test.js","sourceRoot":"","sources":["../../src/__tests__/constants.test.ts"],"names":[],"mappings":";;AAAA,4CAA0F;AAE1F,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,CAAC,6BAAiB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,gBAAgB,GAAG;gBACvB,
|
|
1
|
+
{"version":3,"file":"constants.test.js","sourceRoot":"","sources":["../../src/__tests__/constants.test.ts"],"names":[],"mappings":";;AAAA,4CAA0F;AAE1F,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,CAAC,6BAAiB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,gBAAgB,GAAG;gBACvB,kBAAkB;gBAClB,iBAAiB;gBACjB,oBAAoB;gBACpB,oBAAoB;gBACpB,uBAAuB;aACxB,CAAC;YAEF,gBAAgB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACnC,MAAM,CAAC,6BAAiB,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,6BAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACpC,MAAM,CAAC,+BAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACnD,MAAM,CAAC,+BAAmB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,QAAQ,GAAG,IAAA,8BAAkB,EAAC,WAAW,CAAC,CAAC;YACjD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,QAAQ,GAAG,IAAA,8BAAkB,EAAC,MAAM,CAAC,CAAC;YAC5C,6BAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACpC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,QAAQ,GAAG,IAAA,8BAAkB,EAAC,MAAM,CAAC,CAAC;YAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,QAAQ,GAAG,IAAA,8BAAkB,EAAC,MAAM,CAAC,CAAC;YAC5C,6BAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACpC,MAAM,WAAW,GAAG,+BAAmB,CAAC,OAAO,CAAC,CAAC;gBACjD,yDAAyD;gBACzD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IAEL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/create.test.ts"],"names":[],"mappings":""}
|