@joshski/dust 0.1.95 → 0.1.97
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/dist/artifacts/ideas.d.ts +17 -0
- package/dist/artifacts/index.d.ts +4 -3
- package/dist/artifacts.js +127 -29
- package/dist/audits/index.d.ts +4 -3
- package/dist/audits.js +272 -228
- package/dist/bucket/repository-lifecycle.d.ts +38 -0
- package/dist/bucket/repository.d.ts +4 -4
- package/dist/dust.js +1156 -797
- package/dist/loop/git-pull.d.ts +2 -2
- package/dist/types.d.ts +1 -1
- package/dist/validation.js +154 -101
- package/package.json +1 -1
|
@@ -14,6 +14,11 @@ export interface Idea {
|
|
|
14
14
|
content: string;
|
|
15
15
|
openQuestions: IdeaOpenQuestion[];
|
|
16
16
|
}
|
|
17
|
+
export interface ParsedIdeaContent {
|
|
18
|
+
title: string | null;
|
|
19
|
+
body: string;
|
|
20
|
+
openQuestions: IdeaOpenQuestion[];
|
|
21
|
+
}
|
|
17
22
|
/**
|
|
18
23
|
* Parses the ## Open Questions section from idea markdown content.
|
|
19
24
|
* Extracts each ### question heading and its #### option children.
|
|
@@ -23,3 +28,15 @@ export declare function parseOpenQuestions(content: string): IdeaOpenQuestion[];
|
|
|
23
28
|
* Parses an idea markdown file into a structured Idea object.
|
|
24
29
|
*/
|
|
25
30
|
export declare function parseIdea(fileSystem: ReadableFileSystem, dustPath: string, slug: string): Promise<Idea>;
|
|
31
|
+
/**
|
|
32
|
+
* Parses idea markdown into a structured object that can be bound to a UI
|
|
33
|
+
* and serialized back to markdown.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseIdeaContent(markdown: string): ParsedIdeaContent;
|
|
36
|
+
/**
|
|
37
|
+
* Serializes a ParsedIdeaContent back to markdown.
|
|
38
|
+
* Open Questions are appended as the last section.
|
|
39
|
+
*/
|
|
40
|
+
export declare function ideaContentToMarkdown(content: ParsedIdeaContent, options?: {
|
|
41
|
+
includeOpenQuestions?: boolean;
|
|
42
|
+
}): string;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { FileSystem, ReadableFileSystem } from '../filesystem/types';
|
|
2
2
|
import { type Fact } from './facts';
|
|
3
|
-
import { type Idea, type IdeaOpenQuestion, type IdeaOption, parseOpenQuestions } from './ideas';
|
|
3
|
+
import { type Idea, type IdeaOpenQuestion, type IdeaOption, type ParsedIdeaContent, ideaContentToMarkdown, parseIdeaContent, parseOpenQuestions } from './ideas';
|
|
4
|
+
import { extractTitle } from '../markdown/markdown-utilities';
|
|
4
5
|
import { type Principle } from './principles';
|
|
5
6
|
import { type Task } from './tasks';
|
|
6
7
|
import { type AllWorkflowTasks, CAPTURE_IDEA_PREFIX, type CreateIdeaTransitionTaskResult, type DecomposeIdeaOptions, findAllWorkflowTasks, type IdeaInProgress, type OpenQuestionResponse, type ParsedCaptureIdeaTask, parseResolvedQuestions, type WorkflowTaskMatch, type WorkflowTaskType } from './workflow-tasks';
|
|
7
|
-
export type { AllWorkflowTasks, CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, Fact, Idea, IdeaOpenQuestion, IdeaOption, OpenQuestionResponse, ParsedCaptureIdeaTask, Principle, Task, WorkflowTaskMatch, WorkflowTaskType, };
|
|
8
|
+
export type { AllWorkflowTasks, CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, Fact, Idea, IdeaOpenQuestion, IdeaOption, OpenQuestionResponse, ParsedCaptureIdeaTask, ParsedIdeaContent, Principle, Task, WorkflowTaskMatch, WorkflowTaskType, };
|
|
8
9
|
export interface TaskGraphNode {
|
|
9
10
|
task: Task;
|
|
10
11
|
workflowType: WorkflowTaskType | null;
|
|
@@ -16,7 +17,7 @@ export interface TaskGraph {
|
|
|
16
17
|
to: string;
|
|
17
18
|
}>;
|
|
18
19
|
}
|
|
19
|
-
export { CAPTURE_IDEA_PREFIX, findAllWorkflowTasks, parseOpenQuestions, parseResolvedQuestions, };
|
|
20
|
+
export { CAPTURE_IDEA_PREFIX, extractTitle, findAllWorkflowTasks, ideaContentToMarkdown, parseIdeaContent, parseOpenQuestions, parseResolvedQuestions, };
|
|
20
21
|
export type { IdeaInProgress };
|
|
21
22
|
export type ArtifactType = 'ideas' | 'tasks' | 'principles' | 'facts';
|
|
22
23
|
export interface ReadOnlyArtifactsRepository {
|
package/dist/artifacts.js
CHANGED
|
@@ -4,50 +4,68 @@ function extractTitle(content) {
|
|
|
4
4
|
return match ? match[1].trim() : null;
|
|
5
5
|
}
|
|
6
6
|
var MARKDOWN_LINK_PATTERN = /\[([^\]]+)\]\(([^)]+)\)/;
|
|
7
|
-
function
|
|
8
|
-
const lines = content.split(`
|
|
9
|
-
`);
|
|
10
|
-
let h1Index = -1;
|
|
7
|
+
function findH1Index(lines) {
|
|
11
8
|
for (let i = 0;i < lines.length; i++) {
|
|
12
9
|
if (lines[i].match(/^#\s+.+$/)) {
|
|
13
|
-
|
|
14
|
-
break;
|
|
10
|
+
return i;
|
|
15
11
|
}
|
|
16
12
|
}
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
return -1;
|
|
14
|
+
}
|
|
15
|
+
function findFirstNonBlankLineAfter(lines, startIndex) {
|
|
16
|
+
for (let i = startIndex + 1;i < lines.length; i++) {
|
|
17
|
+
if (lines[i].trim() !== "") {
|
|
18
|
+
return i;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return -1;
|
|
22
|
+
}
|
|
23
|
+
var LIST_ITEM_PREFIXES = ["-", "*", "+"];
|
|
24
|
+
var STRUCTURAL_PREFIXES = ["#", "```", ">"];
|
|
25
|
+
function isStructuralElement(line) {
|
|
26
|
+
if (STRUCTURAL_PREFIXES.some((prefix) => line.startsWith(prefix))) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (LIST_ITEM_PREFIXES.some((prefix) => line.startsWith(prefix))) {
|
|
30
|
+
return true;
|
|
19
31
|
}
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
return /^\d+\./.test(line);
|
|
33
|
+
}
|
|
34
|
+
function isBlockBreak(line) {
|
|
35
|
+
return STRUCTURAL_PREFIXES.some((prefix) => line.startsWith(prefix));
|
|
36
|
+
}
|
|
37
|
+
function collectParagraph(lines, startIndex) {
|
|
38
|
+
const parts = [];
|
|
39
|
+
for (let i = startIndex;i < lines.length; i++) {
|
|
22
40
|
const line = lines[i].trim();
|
|
23
|
-
if (line
|
|
24
|
-
paragraphStart = i;
|
|
41
|
+
if (line === "" || isBlockBreak(line)) {
|
|
25
42
|
break;
|
|
26
43
|
}
|
|
44
|
+
parts.push(line);
|
|
27
45
|
}
|
|
28
|
-
|
|
46
|
+
return parts.join(" ");
|
|
47
|
+
}
|
|
48
|
+
function extractFirstSentence(paragraph) {
|
|
49
|
+
const match = paragraph.match(/^(.+?[.?!])(?:\s|$)/);
|
|
50
|
+
return match ? match[1] : null;
|
|
51
|
+
}
|
|
52
|
+
function extractOpeningSentence(content) {
|
|
53
|
+
const lines = content.split(`
|
|
54
|
+
`);
|
|
55
|
+
const h1Index = findH1Index(lines);
|
|
56
|
+
if (h1Index === -1) {
|
|
29
57
|
return null;
|
|
30
58
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
if (trimmedFirstLine.startsWith("#") || trimmedFirstLine.startsWith("-") || trimmedFirstLine.startsWith("*") || trimmedFirstLine.startsWith("+") || trimmedFirstLine.match(/^\d+\./) || trimmedFirstLine.startsWith("```") || trimmedFirstLine.startsWith(">")) {
|
|
59
|
+
const paragraphStart = findFirstNonBlankLineAfter(lines, h1Index);
|
|
60
|
+
if (paragraphStart === -1) {
|
|
34
61
|
return null;
|
|
35
62
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const line = lines[i].trim();
|
|
39
|
-
if (line === "")
|
|
40
|
-
break;
|
|
41
|
-
if (line.startsWith("#") || line.startsWith("```") || line.startsWith(">")) {
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
paragraph += (paragraph ? " " : "") + line;
|
|
45
|
-
}
|
|
46
|
-
const sentenceMatch = paragraph.match(/^(.+?[.?!])(?:\s|$)/);
|
|
47
|
-
if (!sentenceMatch) {
|
|
63
|
+
const trimmedFirstLine = lines[paragraphStart].trim();
|
|
64
|
+
if (isStructuralElement(trimmedFirstLine)) {
|
|
48
65
|
return null;
|
|
49
66
|
}
|
|
50
|
-
|
|
67
|
+
const paragraph = collectParagraph(lines, paragraphStart);
|
|
68
|
+
return extractFirstSentence(paragraph);
|
|
51
69
|
}
|
|
52
70
|
|
|
53
71
|
// lib/artifacts/facts.ts
|
|
@@ -162,6 +180,83 @@ async function parseIdea(fileSystem, dustPath, slug) {
|
|
|
162
180
|
openQuestions
|
|
163
181
|
};
|
|
164
182
|
}
|
|
183
|
+
function stripOpenQuestionsSection(content) {
|
|
184
|
+
const lines = content.split(`
|
|
185
|
+
`);
|
|
186
|
+
const result = [];
|
|
187
|
+
let inOpenQuestions = false;
|
|
188
|
+
let inCodeFence = false;
|
|
189
|
+
for (const line of lines) {
|
|
190
|
+
if (line.startsWith("```")) {
|
|
191
|
+
inCodeFence = !inCodeFence;
|
|
192
|
+
if (!inOpenQuestions)
|
|
193
|
+
result.push(line);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (inCodeFence) {
|
|
197
|
+
if (!inOpenQuestions)
|
|
198
|
+
result.push(line);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (line.startsWith("## ")) {
|
|
202
|
+
inOpenQuestions = line.trimEnd() === "## Open Questions";
|
|
203
|
+
if (!inOpenQuestions)
|
|
204
|
+
result.push(line);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (!inOpenQuestions) {
|
|
208
|
+
result.push(line);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
while (result.length > 0 && result[result.length - 1].trim() === "") {
|
|
212
|
+
result.pop();
|
|
213
|
+
}
|
|
214
|
+
return result.join(`
|
|
215
|
+
`) + `
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
function stripTitle(content) {
|
|
219
|
+
const match = content.match(/^#\s+.+\n+/);
|
|
220
|
+
if (!match)
|
|
221
|
+
return content;
|
|
222
|
+
return content.slice(match[0].length);
|
|
223
|
+
}
|
|
224
|
+
function parseIdeaContent(markdown) {
|
|
225
|
+
const title = extractTitle(markdown);
|
|
226
|
+
const openQuestions = parseOpenQuestions(markdown);
|
|
227
|
+
const body = stripTitle(stripOpenQuestionsSection(markdown));
|
|
228
|
+
return { title, body, openQuestions };
|
|
229
|
+
}
|
|
230
|
+
function ideaContentToMarkdown(content, options) {
|
|
231
|
+
const includeOQ = options?.includeOpenQuestions ?? true;
|
|
232
|
+
const parts = [];
|
|
233
|
+
if (content.title) {
|
|
234
|
+
parts.push(`# ${content.title}`);
|
|
235
|
+
parts.push("");
|
|
236
|
+
}
|
|
237
|
+
if (content.body) {
|
|
238
|
+
parts.push(content.body.trimEnd());
|
|
239
|
+
parts.push("");
|
|
240
|
+
}
|
|
241
|
+
if (includeOQ && content.openQuestions.length > 0) {
|
|
242
|
+
parts.push("## Open Questions");
|
|
243
|
+
parts.push("");
|
|
244
|
+
for (const q of content.openQuestions) {
|
|
245
|
+
parts.push(`### ${q.question}`);
|
|
246
|
+
parts.push("");
|
|
247
|
+
for (const o of q.options) {
|
|
248
|
+
parts.push(`#### ${o.name}`);
|
|
249
|
+
parts.push("");
|
|
250
|
+
if (o.description) {
|
|
251
|
+
parts.push(o.description);
|
|
252
|
+
parts.push("");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return parts.join(`
|
|
258
|
+
`);
|
|
259
|
+
}
|
|
165
260
|
|
|
166
261
|
// lib/artifacts/principles.ts
|
|
167
262
|
function extractLinksFromSection(content, sectionHeading) {
|
|
@@ -765,7 +860,10 @@ function buildReadOnlyArtifactsRepository(fileSystem, dustPath) {
|
|
|
765
860
|
export {
|
|
766
861
|
parseResolvedQuestions,
|
|
767
862
|
parseOpenQuestions,
|
|
863
|
+
parseIdeaContent,
|
|
864
|
+
ideaContentToMarkdown,
|
|
768
865
|
findAllWorkflowTasks,
|
|
866
|
+
extractTitle,
|
|
769
867
|
buildReadOnlyArtifactsRepository,
|
|
770
868
|
buildArtifactsRepository,
|
|
771
869
|
CAPTURE_IDEA_PREFIX
|
package/dist/audits/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface AuditsRepository {
|
|
|
26
26
|
}): Promise<Audit>;
|
|
27
27
|
createAuditTask(options: {
|
|
28
28
|
name: string;
|
|
29
|
+
comment?: string;
|
|
29
30
|
}): Promise<CreateAuditTaskResult>;
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
@@ -34,8 +35,8 @@ export interface AuditsRepository {
|
|
|
34
35
|
*/
|
|
35
36
|
export declare function transformAuditContent(content: string): string;
|
|
36
37
|
/**
|
|
37
|
-
* Injects
|
|
38
|
-
* The
|
|
38
|
+
* Injects a Comments section after the opening description, before ## Scope.
|
|
39
|
+
* The comment is passed through without validation.
|
|
39
40
|
*/
|
|
40
|
-
export declare function
|
|
41
|
+
export declare function injectComment(content: string, comment: string): string;
|
|
41
42
|
export declare function buildAuditsRepository(fileSystem: FileSystem, dustPath: string): AuditsRepository;
|