@reqlan/analytical 0.4.0 → 0.5.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 +164 -0
- package/README.template.md +33 -0
- package/out/analysis-api.d.ts +8 -0
- package/out/analysis-api.js +21 -0
- package/out/analysis-api.js.map +1 -1
- package/out/core/application-memory.d.ts +11 -0
- package/out/core/application-memory.js +26 -0
- package/out/core/application-memory.js.map +1 -0
- package/out/create-runtime.d.ts +1 -0
- package/out/create-runtime.js +2 -3
- package/out/create-runtime.js.map +1 -1
- package/out/export/build-export-snapshot.js +52 -30
- package/out/export/build-export-snapshot.js.map +1 -1
- package/out/export/export-html.d.ts +4 -0
- package/out/export/export-html.js +8 -0
- package/out/export/export-html.js.map +1 -0
- package/out/export/html-export-assets.d.ts +2 -2
- package/out/export/html-export-assets.js +187 -17
- package/out/export/html-export-assets.js.map +1 -1
- package/out/export/html-export-template.d.ts +2 -1
- package/out/export/html-export-template.js +230 -120
- package/out/export/html-export-template.js.map +1 -1
- package/out/export/html-export-utils.d.ts +13 -2
- package/out/export/html-export-utils.js +167 -52
- package/out/export/html-export-utils.js.map +1 -1
- package/out/export/secret-rq.d.ts +2 -0
- package/out/export/secret-rq.js +9 -0
- package/out/export/secret-rq.js.map +1 -0
- package/out/export/types.d.ts +25 -0
- package/out/export/write-html-export.js +7 -1
- package/out/export/write-html-export.js.map +1 -1
- package/out/headless-index-service.js +2 -1
- package/out/headless-index-service.js.map +1 -1
- package/out/index-store/idea-extractor.js +42 -7
- package/out/index-store/idea-extractor.js.map +1 -1
- package/out/index-store/webview-graph-queries.d.ts +12 -0
- package/out/index-store/webview-graph-queries.js +37 -3
- package/out/index-store/webview-graph-queries.js.map +1 -1
- package/out/index.d.ts +5 -2
- package/out/index.js +4 -1
- package/out/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/littletuna4/reqlan/HEAD/packages/extension/media/logo.png" alt="reqlan logo" width="128" height="128">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @reqlan/analytical
|
|
6
|
+
|
|
7
|
+
Shared requirement graph index and analysers for reqlan
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Headless requirement graph index (sql.js) over parsed `.rq` workspaces
|
|
12
|
+
- Shared application memory under `<workspace>/.reqlan` (ideas-index.sqlite) for extension, CLI, and MCP
|
|
13
|
+
- Analysers for semantic search, file context, local graphs, and completion status
|
|
14
|
+
- `AnalysisApi` façade shared by the CLI and MCP server
|
|
15
|
+
- Context-model helpers for composing focused requirement context
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @reqlan/analytical
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Links
|
|
24
|
+
|
|
25
|
+
- [Site](https://tony.is-a.dev/reqlan)
|
|
26
|
+
- [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=reqlan.reqlan-extension)
|
|
27
|
+
- [Open VSX](https://open-vsx.org/extension/reqlan/reqlan-extension)
|
|
28
|
+
- [GitHub repository](https://github.com/littletuna4/reqlan)
|
|
29
|
+
- [Contact](mailto:reqlan@tony.is-a.dev)
|
|
30
|
+
|
|
31
|
+
## Changelog
|
|
32
|
+
|
|
33
|
+
### 0.5.0
|
|
34
|
+
|
|
35
|
+
#### Minor Changes
|
|
36
|
+
|
|
37
|
+
- 627d502: updates to cli, site export, site (showing spec), replace welcome screen, temp remove old extension name.
|
|
38
|
+
|
|
39
|
+
#### Patch Changes
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [627d502]
|
|
42
|
+
- @reqlan/language@1.5.0
|
|
43
|
+
|
|
44
|
+
### 0.4.1
|
|
45
|
+
|
|
46
|
+
#### Patch Changes
|
|
47
|
+
|
|
48
|
+
- 1790ce1: Update the landers.
|
|
49
|
+
- Updated dependencies [1790ce1]
|
|
50
|
+
- @reqlan/language@1.4.1
|
|
51
|
+
|
|
52
|
+
### 0.4.0
|
|
53
|
+
|
|
54
|
+
#### Minor Changes
|
|
55
|
+
|
|
56
|
+
- 8ac3f82: Minor site showcase fixes, extension search functinoality, cli init.
|
|
57
|
+
|
|
58
|
+
#### Patch Changes
|
|
59
|
+
|
|
60
|
+
- Updated dependencies [8ac3f82]
|
|
61
|
+
- @reqlan/language@1.4.0
|
|
62
|
+
|
|
63
|
+
### 0.3.0
|
|
64
|
+
|
|
65
|
+
#### Minor Changes
|
|
66
|
+
|
|
67
|
+
- 4b9d33b: brevity improvements in activitybar. graph interactivity improvements. various syntactic fixes
|
|
68
|
+
|
|
69
|
+
#### Patch Changes
|
|
70
|
+
|
|
71
|
+
- Updated dependencies [4b9d33b]
|
|
72
|
+
- @reqlan/language@1.3.0
|
|
73
|
+
|
|
74
|
+
### 0.2.1
|
|
75
|
+
|
|
76
|
+
#### Patch Changes
|
|
77
|
+
|
|
78
|
+
- Updated dependencies [e5389ba]
|
|
79
|
+
- @reqlan/language@1.2.0
|
|
80
|
+
|
|
81
|
+
### 0.2.0
|
|
82
|
+
|
|
83
|
+
#### Minor Changes
|
|
84
|
+
|
|
85
|
+
- e56ac74: onboarding, index corruption recovery, syntax edge case support, inlay hint development
|
|
86
|
+
|
|
87
|
+
#### Patch Changes
|
|
88
|
+
|
|
89
|
+
- Updated dependencies [e56ac74]
|
|
90
|
+
- @reqlan/language@1.1.0
|
|
91
|
+
|
|
92
|
+
### 0.1.4
|
|
93
|
+
|
|
94
|
+
#### Patch Changes
|
|
95
|
+
|
|
96
|
+
- b8a50cd: minor fixes
|
|
97
|
+
- Updated dependencies [b8a50cd]
|
|
98
|
+
- @reqlan/language@1.0.1
|
|
99
|
+
|
|
100
|
+
### 0.1.3
|
|
101
|
+
|
|
102
|
+
#### Patch Changes
|
|
103
|
+
|
|
104
|
+
- Updated dependencies [931fc87]
|
|
105
|
+
- @reqlan/language@1.0.0
|
|
106
|
+
|
|
107
|
+
### 0.1.2
|
|
108
|
+
|
|
109
|
+
#### Patch Changes
|
|
110
|
+
|
|
111
|
+
- fcb99a0: Various vibed changes
|
|
112
|
+
- Updated dependencies [fcb99a0]
|
|
113
|
+
- @reqlan/language@0.1.2
|
|
114
|
+
|
|
115
|
+
### 0.1.1
|
|
116
|
+
|
|
117
|
+
#### Patch Changes
|
|
118
|
+
|
|
119
|
+
- d9f43be: remove :memory:
|
|
120
|
+
- Updated dependencies [d9f43be]
|
|
121
|
+
- @reqlan/language@0.1.1
|
|
122
|
+
|
|
123
|
+
### 0.1.0
|
|
124
|
+
|
|
125
|
+
#### Minor Changes
|
|
126
|
+
|
|
127
|
+
- 65840f4: update to extension activity bar; update to the syntax. addition of testing. bidirectional references.
|
|
128
|
+
|
|
129
|
+
#### Patch Changes
|
|
130
|
+
|
|
131
|
+
- Updated dependencies [65840f4]
|
|
132
|
+
- @reqlan/language@0.1.0
|
|
133
|
+
|
|
134
|
+
### 0.0.5
|
|
135
|
+
|
|
136
|
+
#### Patch Changes
|
|
137
|
+
|
|
138
|
+
- a6c2066: Branding change
|
|
139
|
+
- Updated dependencies [a6c2066]
|
|
140
|
+
- @reqlan/language@0.0.5
|
|
141
|
+
|
|
142
|
+
### 0.0.4
|
|
143
|
+
|
|
144
|
+
#### Patch Changes
|
|
145
|
+
|
|
146
|
+
- Updated dependencies [020cd59]
|
|
147
|
+
- @reqlan/language@0.0.4
|
|
148
|
+
|
|
149
|
+
### 0.0.3
|
|
150
|
+
|
|
151
|
+
#### Patch Changes
|
|
152
|
+
|
|
153
|
+
- Updated dependencies [66e5027]
|
|
154
|
+
- @reqlan/language@0.0.3
|
|
155
|
+
|
|
156
|
+
### 0.0.2
|
|
157
|
+
|
|
158
|
+
#### Patch Changes
|
|
159
|
+
|
|
160
|
+
- f6bae00: rebase the semver to the manual version
|
|
161
|
+
- d50f988: test increment of \*
|
|
162
|
+
- Updated dependencies [f6bae00]
|
|
163
|
+
- Updated dependencies [d50f988]
|
|
164
|
+
- @reqlan/language@0.0.2
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="{{LOGO_URL}}" alt="reqlan logo" width="128" height="128">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# {{PACKAGE_NAME}}
|
|
6
|
+
|
|
7
|
+
{{DESCRIPTION}}
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Headless requirement graph index (sql.js) over parsed `.rq` workspaces
|
|
12
|
+
- Shared application memory under `<workspace>/.reqlan` (ideas-index.sqlite) for extension, CLI, and MCP
|
|
13
|
+
- Analysers for semantic search, file context, local graphs, and completion status
|
|
14
|
+
- `AnalysisApi` façade shared by the CLI and MCP server
|
|
15
|
+
- Context-model helpers for composing focused requirement context
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @reqlan/analytical
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Links
|
|
24
|
+
|
|
25
|
+
- [{{SITE_LABEL}}]({{SITE_URL}})
|
|
26
|
+
- [{{VSC_LABEL}}]({{VSC_URL}})
|
|
27
|
+
- [{{OPENVSX_LABEL}}]({{OPENVSX_URL}})
|
|
28
|
+
- [GitHub repository]({{GITHUB_URL}})
|
|
29
|
+
- [Contact]({{EMAIL_URL}})
|
|
30
|
+
|
|
31
|
+
## Changelog
|
|
32
|
+
|
|
33
|
+
{{CHANGELOG}}
|
package/out/analysis-api.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CompletionSummary, DeprecationImpact, FileRelatedRequirements, GraphSlice, IdeaSummary } from './core/types.js';
|
|
2
2
|
import type { AnalysisRuntime } from './create-runtime.js';
|
|
3
|
+
import type { ExportRequest, ExportResult } from './export/types.js';
|
|
3
4
|
export interface RequirementMatch {
|
|
4
5
|
idea: IdeaSummary;
|
|
5
6
|
score?: number;
|
|
@@ -21,6 +22,13 @@ export declare class AnalysisApi {
|
|
|
21
22
|
summarizeSubtree(requirementName: string, depth?: number): Promise<GraphSlice | undefined>;
|
|
22
23
|
getCompletionStatus(): Promise<CompletionSummary>;
|
|
23
24
|
getDeprecationImpact(): Promise<DeprecationImpact[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Export the indexed requirement graph as a multi-file static HTML site.
|
|
27
|
+
* Headless entry point shared by CLI and site build.
|
|
28
|
+
*/
|
|
29
|
+
exportHtml(request: Omit<ExportRequest, 'workspaceRoot'> & {
|
|
30
|
+
workspaceRoot?: string;
|
|
31
|
+
}): Promise<ExportResult>;
|
|
24
32
|
resolveRequirementReference(name?: string): Promise<IdeaSummary[]>;
|
|
25
33
|
resolveFileReference(pathPrefix?: string): Promise<Array<{
|
|
26
34
|
path: string;
|
package/out/analysis-api.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { exportHtml } from './export/export-html.js';
|
|
1
2
|
export class AnalysisApi {
|
|
2
3
|
constructor(runtime) {
|
|
3
4
|
this.runtime = runtime;
|
|
@@ -54,6 +55,17 @@ export class AnalysisApi {
|
|
|
54
55
|
await this.ensureReady();
|
|
55
56
|
return this.runtime.analysers.run(this.runtime.makeContext(), 'deprecation_impact_analysis', undefined);
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Export the indexed requirement graph as a multi-file static HTML site.
|
|
60
|
+
* Headless entry point shared by CLI and site build.
|
|
61
|
+
*/
|
|
62
|
+
async exportHtml(request) {
|
|
63
|
+
await this.ensureReady();
|
|
64
|
+
return exportHtml(this.runtime.index.indexStore, {
|
|
65
|
+
...request,
|
|
66
|
+
workspaceRoot: request.workspaceRoot ?? this.runtime.workspaceRoot
|
|
67
|
+
});
|
|
68
|
+
}
|
|
57
69
|
async resolveRequirementReference(name) {
|
|
58
70
|
await this.ensureReady();
|
|
59
71
|
const query = name?.trim() ?? '';
|
|
@@ -119,6 +131,15 @@ export class AnalysisApi {
|
|
|
119
131
|
description: 'Summarise completion and deprecation status across the workspace graph.',
|
|
120
132
|
parameters: {}
|
|
121
133
|
},
|
|
134
|
+
{
|
|
135
|
+
name: 'export_html',
|
|
136
|
+
description: 'Export the requirement graph as a multi-file static HTML site.',
|
|
137
|
+
parameters: {
|
|
138
|
+
outputDir: 'Parent directory for the export folder',
|
|
139
|
+
exportName: 'Export folder name',
|
|
140
|
+
excludeSecretFiles: 'Optional: omit *.secret.rq files'
|
|
141
|
+
}
|
|
142
|
+
},
|
|
122
143
|
{
|
|
123
144
|
name: 'list_interactions',
|
|
124
145
|
description: 'Discover available requirement graph interactions and parameters.',
|
package/out/analysis-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-api.js","sourceRoot":"","sources":["../src/analysis-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analysis-api.js","sourceRoot":"","sources":["../src/analysis-api.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAerD,MAAM,OAAO,WAAW;IACpB,YAA6B,OAAwB;QAAxB,YAAO,GAAP,OAAO,CAAiB;IAAG,CAAC;IAEzD,KAAK,CAAC,WAAW;QACb,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC7B,OAAO;QACX,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAa,EAAE,KAAK,GAAG,CAAC;QAC7C,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC5C,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,mBAAmB,EACnB,EAAE,KAAK,EAAE,KAAK,EAAE,CACnB,CAAC;QACF,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACzB,CAAC,CAAC,CAAC;IACR,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAK,GAAG,EAAE;QAC7B,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC1C,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,gBAAgB,EAChB,SAAS,CACZ,CAAC;QACF,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACjC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,2BAA2B,EAC3B,EAAE,OAAO,EAAE,CACd,CAAC;IACN,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,KAAK,GAAG,CAAC;QAC3C,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,sBAAsB,EACtB,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,CACjC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,eAAuB,EAAE,KAAK,GAAG,CAAC;QACrD,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,sBAAsB,EACtB,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,CACjC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,mBAAmB;QACrB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,qBAAqB,EACrB,SAAS,CACZ,CAAC;IACN,CAAC;IAED,KAAK,CAAC,oBAAoB;QACtB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAC7B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAC1B,6BAA6B,EAC7B,SAAS,CACZ,CAAC;IACN,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,OAEhB;QACG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE;YAC7C,GAAG,OAAO;YACV,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa;SACrE,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,2BAA2B,CAAC,IAAa;QAC3C,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACjC,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAmB;QAC1C,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAExE,MAAM,OAAO,GAAkD,EAAE,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC;gBACT,IAAI;gBACJ,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;aAChD,CAAC,CAAC;QACP,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,gBAAgB;QACZ,OAAO;YACH;gBACI,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EAAE,+EAA+E;gBAC5F,UAAU,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,oCAAoC,EAAE;aACpF;YACD;gBACI,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,6CAA6C;gBAC1D,UAAU,EAAE,EAAE,KAAK,EAAE,yCAAyC,EAAE;aACnE;YACD;gBACI,IAAI,EAAE,cAAc;gBACpB,WAAW,EAAE,gEAAgE;gBAC7E,UAAU,EAAE,EAAE,QAAQ,EAAE,yCAAyC,EAAE;aACtE;YACD;gBACI,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,yEAAyE;gBACtF,UAAU,EAAE,EAAE,QAAQ,EAAE,yCAAyC,EAAE,KAAK,EAAE,oBAAoB,EAAE;aACnG;YACD;gBACI,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,gEAAgE;gBAC7E,UAAU,EAAE,EAAE,eAAe,EAAE,iCAAiC,EAAE,KAAK,EAAE,oBAAoB,EAAE;aAClG;YACD;gBACI,IAAI,EAAE,uBAAuB;gBAC7B,WAAW,EAAE,gEAAgE;gBAC7E,UAAU,EAAE,EAAE,IAAI,EAAE,0CAA0C,EAAE;aACnE;YACD;gBACI,IAAI,EAAE,gBAAgB;gBACtB,WAAW,EAAE,qDAAqD;gBAClE,UAAU,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;aACxD;YACD;gBACI,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,yEAAyE;gBACtF,UAAU,EAAE,EAAE;aACjB;YACD;gBACI,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,gEAAgE;gBAC7E,UAAU,EAAE;oBACR,SAAS,EAAE,wCAAwC;oBACnD,UAAU,EAAE,oBAAoB;oBAChC,kBAAkB,EAAE,kCAAkC;iBACzD;aACJ;YACD;gBACI,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,mEAAmE;gBAChF,UAAU,EAAE,EAAE;aACjB;SACJ,CAAC;IACN,CAAC;IAED,UAAU,CAAC,IAAiB;QACxB,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,MAAM,IAAI,CAAC,OAAO,IAAI,cAAc,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;IAC/F,CAAC;CACJ"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Directory name under the workspace root for shared application memory. */
|
|
2
|
+
export declare const APPLICATION_MEMORY_DIR = ".reqlan";
|
|
3
|
+
/** Default SQLite filename for the ideas graph index inside application memory. */
|
|
4
|
+
export declare const IDEAS_INDEX_FILENAME = "ideas-index.sqlite";
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the application-memory directory for a workspace.
|
|
7
|
+
* Override with an absolute or relative `storagePath` when set (e.g. tests / REQLAN_INDEX_PATH).
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveApplicationMemoryPath(workspaceRoot: string, storagePath?: string): string;
|
|
10
|
+
/** Full path to the ideas-index SQLite file under application memory. */
|
|
11
|
+
export declare function resolveIdeasIndexDbPath(workspaceRoot: string, storagePath?: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace-local application memory for reqlan tools.
|
|
3
|
+
*
|
|
4
|
+
* The ideas index SQLite database lives under `<workspace>/.reqlan/` so the
|
|
5
|
+
* extension, CLI, and MCP share one on-disk store — not VS Code globalStorage.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
/** Directory name under the workspace root for shared application memory. */
|
|
9
|
+
export const APPLICATION_MEMORY_DIR = '.reqlan';
|
|
10
|
+
/** Default SQLite filename for the ideas graph index inside application memory. */
|
|
11
|
+
export const IDEAS_INDEX_FILENAME = 'ideas-index.sqlite';
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the application-memory directory for a workspace.
|
|
14
|
+
* Override with an absolute or relative `storagePath` when set (e.g. tests / REQLAN_INDEX_PATH).
|
|
15
|
+
*/
|
|
16
|
+
export function resolveApplicationMemoryPath(workspaceRoot, storagePath) {
|
|
17
|
+
if (storagePath?.trim()) {
|
|
18
|
+
return storagePath.trim();
|
|
19
|
+
}
|
|
20
|
+
return join(workspaceRoot, APPLICATION_MEMORY_DIR);
|
|
21
|
+
}
|
|
22
|
+
/** Full path to the ideas-index SQLite file under application memory. */
|
|
23
|
+
export function resolveIdeasIndexDbPath(workspaceRoot, storagePath) {
|
|
24
|
+
return join(resolveApplicationMemoryPath(workspaceRoot, storagePath), IDEAS_INDEX_FILENAME);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=application-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application-memory.js","sourceRoot":"","sources":["../../src/core/application-memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAEhD,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,aAAqB,EAAE,WAAoB;IACpF,IAAI,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACtB,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;AACvD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,uBAAuB,CAAC,aAAqB,EAAE,WAAoB;IAC/E,OAAO,IAAI,CAAC,4BAA4B,CAAC,aAAa,EAAE,WAAW,CAAC,EAAE,oBAAoB,CAAC,CAAC;AAChG,CAAC"}
|
package/out/create-runtime.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AnalyserRegistry } from './analysis/analyser-registry.js';
|
|
|
3
3
|
import { HeadlessIndexService } from './headless-index-service.js';
|
|
4
4
|
export interface AnalysisRuntimeOptions {
|
|
5
5
|
workspaceRoot: string;
|
|
6
|
+
/** Override application-memory directory; default is `<workspace>/.reqlan`. */
|
|
6
7
|
storagePath?: string;
|
|
7
8
|
}
|
|
8
9
|
export interface AnalysisRuntime {
|
package/out/create-runtime.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { join } from 'node:path';
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
3
1
|
import { createAnalyticalStore } from './core/analytical-store.js';
|
|
2
|
+
import { resolveApplicationMemoryPath } from './core/application-memory.js';
|
|
4
3
|
import { AnalyserRegistry } from './analysis/analyser-registry.js';
|
|
5
4
|
import { listAllIdeasAnalyser } from './analysis/list-ideas-analyser.js';
|
|
6
5
|
import { fileRelatedAnalyser } from './analysis/file-related-analyser.js';
|
|
@@ -12,7 +11,7 @@ import { semanticSearchAnalyser } from './analysis/semantic-search-analyser.js';
|
|
|
12
11
|
import { HeadlessIndexService } from './headless-index-service.js';
|
|
13
12
|
export function createAnalysisRuntime(options) {
|
|
14
13
|
const store = createAnalyticalStore();
|
|
15
|
-
const storagePath = options.
|
|
14
|
+
const storagePath = resolveApplicationMemoryPath(options.workspaceRoot, options.storagePath);
|
|
16
15
|
const index = new HeadlessIndexService(store, storagePath, options.workspaceRoot);
|
|
17
16
|
const analysers = new AnalyserRegistry();
|
|
18
17
|
analysers.register(listAllIdeasAnalyser);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-runtime.js","sourceRoot":"","sources":["../src/create-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"create-runtime.js","sourceRoot":"","sources":["../src/create-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAwB,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAoBnE,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACjE,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,4BAA4B,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7F,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAClF,MAAM,SAAS,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAEzC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAC9C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC;IAC/C,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IAE3C,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CAAC;QACvB,KAAK,EAAE,KAAK,CAAC,UAAU;QACvB,UAAU,EAAE,KAAK;QACjB,aAAa,EAAE,OAAO,CAAC,aAAa;KACvC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAAwB;IAClE,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,OAAwB;IACpE,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IACjC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { parseAttributes } from '../core/types.js';
|
|
2
|
-
import { buildGraphViewSlice } from '../index-store/webview-graph-queries.js';
|
|
3
|
-
import { formatAttributeValue, slugAttributeKey } from './html-export-utils.js';
|
|
2
|
+
import { buildGraphSliceForIdeaIds, buildGraphViewSlice, GRAPH_MAX_NODES } from '../index-store/webview-graph-queries.js';
|
|
3
|
+
import { formatAttributeValue, normalizeUrlBase, slugAttributeKey } from './html-export-utils.js';
|
|
4
|
+
import { isSecretRqPath } from './secret-rq.js';
|
|
4
5
|
export async function buildExportSnapshot(store, request) {
|
|
5
6
|
const title = buildExportTitle(request);
|
|
6
7
|
const runtimeMode = request.runtimeMode ?? 'interactive';
|
|
7
8
|
const clusterStrategy = request.clusterStrategy ?? 'hybrid';
|
|
9
|
+
const urlBase = normalizeUrlBase(request.urlBase);
|
|
10
|
+
const headerLink = normalizeHeaderLink(request.headerLink);
|
|
8
11
|
const pageOptions = {
|
|
9
12
|
includeIdeaPages: request.includeIdeaPages !== false,
|
|
10
13
|
includeFilePages: request.includeFilePages !== false,
|
|
11
14
|
includeCodeFilePages: request.includeCodeFilePages !== false,
|
|
12
15
|
includeClusterPages: request.includeClusterPages !== false,
|
|
16
|
+
includeAttributePages: request.includeAttributePages !== false,
|
|
13
17
|
includePrintPages: request.includePrintPages !== false,
|
|
14
18
|
includeRequirementsPage: request.includeRequirementsPage,
|
|
15
19
|
includeGraphPage: request.includeGraphPage
|
|
16
20
|
};
|
|
17
21
|
const manifest = buildManifest(request);
|
|
18
|
-
const
|
|
22
|
+
const scopedIdeas = request.scope === 'currentFile'
|
|
19
23
|
? await buildScopedIdeas(store, request)
|
|
20
24
|
: await store.listAllIdeas();
|
|
25
|
+
const baseIdeas = request.excludeSecretFiles
|
|
26
|
+
? scopedIdeas.filter(idea => !isSecretRqPath(idea.fileUri))
|
|
27
|
+
: scopedIdeas;
|
|
21
28
|
const byStatus = rollupStatuses(baseIdeas);
|
|
22
29
|
const byTag = rollupTags(baseIdeas);
|
|
23
30
|
const allFiles = [...new Set(baseIdeas.map(idea => idea.fileUri))].sort();
|
|
@@ -42,10 +49,14 @@ export async function buildExportSnapshot(store, request) {
|
|
|
42
49
|
runtimeMode,
|
|
43
50
|
clusterStrategy,
|
|
44
51
|
pageOptions,
|
|
52
|
+
urlBase,
|
|
53
|
+
headerLink,
|
|
45
54
|
manifest,
|
|
46
55
|
counts: {
|
|
47
56
|
ideas: ideaRecords.length,
|
|
48
|
-
edges: request.scope === 'currentFile'
|
|
57
|
+
edges: request.scope === 'currentFile' || request.excludeSecretFiles
|
|
58
|
+
? graphs.workspace.edges.length
|
|
59
|
+
: counts.edges,
|
|
49
60
|
files: fileRecords.length,
|
|
50
61
|
clusters: clusterRecords.length
|
|
51
62
|
},
|
|
@@ -59,6 +70,7 @@ export async function buildExportSnapshot(store, request) {
|
|
|
59
70
|
clusters: clusterRecords,
|
|
60
71
|
clustersById: Object.fromEntries(clusterRecords.map(cluster => [cluster.id, cluster])),
|
|
61
72
|
attributes: attributeRecords,
|
|
73
|
+
attributesByKey: Object.fromEntries(attributeRecords.map(attribute => [attribute.key, attribute])),
|
|
62
74
|
graphs,
|
|
63
75
|
searchDocuments,
|
|
64
76
|
byStatus,
|
|
@@ -229,27 +241,24 @@ function finalizeClusterCounts(clusters, ideasById) {
|
|
|
229
241
|
}
|
|
230
242
|
}
|
|
231
243
|
async function buildGraphCatalog(store, request, ideas, files, clusters) {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
includeIndirect: true,
|
|
236
|
-
maxNodes: request.maxGraphNodes
|
|
237
|
-
});
|
|
244
|
+
const neighborhoodBudget = request.maxGraphNodes ?? GRAPH_MAX_NODES;
|
|
245
|
+
// Workspace graph must mirror the export idea list (blocks, oneliners, and ideasets).
|
|
246
|
+
const workspace = await buildGraphSliceForIdeaIds(store, ideas.map(idea => idea.id), { maxNodes: Math.max(neighborhoodBudget, ideas.length) });
|
|
238
247
|
const byIdeaId = Object.fromEntries(await Promise.all(ideas.map(async (idea) => [
|
|
239
248
|
idea.id,
|
|
240
249
|
await buildGraphViewSlice(store, {
|
|
241
250
|
centerId: idea.id,
|
|
242
251
|
includeIndirect: true,
|
|
243
|
-
maxNodes:
|
|
252
|
+
maxNodes: neighborhoodBudget
|
|
244
253
|
})
|
|
245
254
|
])));
|
|
246
255
|
const byFileId = Object.fromEntries(await Promise.all(files.map(async (file) => [
|
|
247
256
|
file.id,
|
|
248
|
-
await buildGraphSliceForIdeas(store, request, file.ideas.map(idea => idea.id))
|
|
257
|
+
await buildGraphSliceForIdeas(store, request, file.ideas.map(idea => idea.id), neighborhoodBudget)
|
|
249
258
|
])));
|
|
250
259
|
const byClusterId = Object.fromEntries(await Promise.all(clusters.map(async (cluster) => [
|
|
251
260
|
cluster.id,
|
|
252
|
-
await buildGraphSliceForIdeas(store, request, cluster.ideaIds)
|
|
261
|
+
await buildGraphSliceForIdeas(store, request, cluster.ideaIds, neighborhoodBudget)
|
|
253
262
|
])));
|
|
254
263
|
return { workspace, byIdeaId, byFileId, byClusterId };
|
|
255
264
|
}
|
|
@@ -258,15 +267,16 @@ function buildExportTitle(request) {
|
|
|
258
267
|
? `${request.exportName} (${request.sourceFileUri})`
|
|
259
268
|
: request.exportName;
|
|
260
269
|
}
|
|
261
|
-
async function buildGraphSliceForIdeas(store, request, ideaIds) {
|
|
270
|
+
async function buildGraphSliceForIdeas(store, request, ideaIds, maxNodes = request.maxGraphNodes ?? GRAPH_MAX_NODES) {
|
|
262
271
|
const slices = await Promise.all(ideaIds.map(ideaId => buildGraphViewSlice(store, {
|
|
263
272
|
centerId: ideaId,
|
|
264
273
|
includeIndirect: true,
|
|
265
|
-
maxNodes
|
|
274
|
+
maxNodes,
|
|
275
|
+
ignoreHardCap: maxNodes > GRAPH_MAX_NODES
|
|
266
276
|
})));
|
|
267
|
-
return mergeGraphSlices(slices,
|
|
277
|
+
return mergeGraphSlices(slices, Math.max(maxNodes, ideaIds.length));
|
|
268
278
|
}
|
|
269
|
-
function mergeGraphSlices(slices, maxNodes =
|
|
279
|
+
function mergeGraphSlices(slices, maxNodes = GRAPH_MAX_NODES) {
|
|
270
280
|
const nodes = new Map();
|
|
271
281
|
const edges = new Map();
|
|
272
282
|
let depth = 0;
|
|
@@ -383,7 +393,7 @@ function buildSearchDocuments(ideas, files, codeFiles, clusters, attributes) {
|
|
|
383
393
|
title: attribute.key,
|
|
384
394
|
kind: 'attribute',
|
|
385
395
|
summary: `${attribute.ideaCount} ideas · ${attribute.values.length} values`,
|
|
386
|
-
url:
|
|
396
|
+
url: attribute.page.url,
|
|
387
397
|
tags: ['attribute'],
|
|
388
398
|
pathTokens: [attribute.key],
|
|
389
399
|
keywords: attribute.values.map(value => value.value)
|
|
@@ -405,18 +415,22 @@ function buildAttributeRecords(ideas) {
|
|
|
405
415
|
}
|
|
406
416
|
}
|
|
407
417
|
return [...byKey.entries()]
|
|
408
|
-
.map(([key, bucket]) =>
|
|
409
|
-
key
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
.
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
418
|
+
.map(([key, bucket]) => {
|
|
419
|
+
const slug = slugAttributeKey(key);
|
|
420
|
+
return {
|
|
421
|
+
key,
|
|
422
|
+
ideaCount: bucket.ideaIds.size,
|
|
423
|
+
ideaIds: [...bucket.ideaIds].sort(),
|
|
424
|
+
values: [...bucket.values.entries()]
|
|
425
|
+
.map(([value, ideaIds]) => ({
|
|
426
|
+
value,
|
|
427
|
+
count: ideaIds.size,
|
|
428
|
+
ideaIds: [...ideaIds].sort()
|
|
429
|
+
}))
|
|
430
|
+
.sort((left, right) => right.count - left.count || left.value.localeCompare(right.value)),
|
|
431
|
+
page: buildPageInfo(key, `attributes/${slug}.html`)
|
|
432
|
+
};
|
|
433
|
+
})
|
|
420
434
|
.sort((left, right) => right.ideaCount - left.ideaCount || left.key.localeCompare(right.key));
|
|
421
435
|
}
|
|
422
436
|
function collectAttributeKeywords(attributes) {
|
|
@@ -570,4 +584,12 @@ function ensureHtmlFileName(value) {
|
|
|
570
584
|
const trimmed = value.trim();
|
|
571
585
|
return trimmed.toLowerCase().endsWith('.html') ? trimmed : `${trimmed}.html`;
|
|
572
586
|
}
|
|
587
|
+
function normalizeHeaderLink(link) {
|
|
588
|
+
const href = link?.href?.trim();
|
|
589
|
+
const label = link?.label?.trim();
|
|
590
|
+
if (!href || !label) {
|
|
591
|
+
return undefined;
|
|
592
|
+
}
|
|
593
|
+
return { href, label };
|
|
594
|
+
}
|
|
573
595
|
//# sourceMappingURL=build-export-snapshot.js.map
|