patram 0.8.0 → 0.10.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/bin/patram.js +2 -2
- package/lib/cli/arguments.types.d.ts +63 -0
- package/lib/{parse-cli-color-options.js → cli/color-options.js} +2 -2
- package/lib/cli/command-helpers.js +35 -0
- package/lib/cli/commands/check.js +73 -0
- package/lib/cli/commands/fields.js +57 -0
- package/lib/cli/commands/queries.js +41 -0
- package/lib/cli/commands/query.js +242 -0
- package/lib/cli/commands/refs.js +72 -0
- package/lib/cli/commands/show.js +58 -0
- package/lib/{cli-help-metadata.js → cli/help-metadata.js} +7 -102
- package/lib/cli/main.js +76 -0
- package/lib/{parse-cli-arguments-helpers.js → cli/parse-arguments-helpers.js} +24 -12
- package/lib/{parse-cli-arguments.js → cli/parse-arguments.js} +12 -12
- package/lib/{parse-cli-query-pagination.js → cli/query-pagination.js} +2 -2
- package/lib/{render-cli-help.js → cli/render-help.js} +84 -3
- package/lib/{resolve-output-mode.js → cli/resolve-output-mode.js} +2 -2
- package/lib/cli/test-helpers.js +30 -0
- package/lib/config/defaults.d.ts +10 -0
- package/lib/config/defaults.js +80 -0
- package/lib/config/load-patram-config.d.ts +76 -0
- package/lib/config/load-patram-config.js +315 -0
- package/lib/config/load-patram-config.types.d.ts +45 -0
- package/lib/{patram-config.d.ts → config/patram-config.d.ts} +31 -31
- package/lib/{patram-config.js → config/patram-config.js} +3 -3
- package/lib/{patram-config.types.d.ts → config/patram-config.types.d.ts} +1 -1
- package/lib/{resolve-patram-graph-config.d.ts → config/resolve-patram-graph-config.d.ts} +2 -2
- package/lib/{resolve-patram-graph-config.js → config/resolve-patram-graph-config.js} +3 -3
- package/lib/{load-patram-config.d.ts → config/schema.d.ts} +149 -191
- package/lib/config/schema.js +328 -0
- package/lib/{source-file-defaults.d.ts → config/source-file-defaults.d.ts} +0 -1
- package/lib/{source-file-defaults.js → config/source-file-defaults.js} +1 -1
- package/lib/config/validation.d.ts +27 -0
- package/lib/config/validation.js +615 -0
- package/lib/directive-validation-test-helpers.js +1 -1
- package/lib/find-close-match.d.ts +8 -0
- package/lib/find-close-match.js +98 -0
- package/lib/{build-graph-identity.d.ts → graph/build-graph-identity.d.ts} +2 -2
- package/lib/{build-graph-identity.js → graph/build-graph-identity.js} +1 -1
- package/lib/{build-graph.d.ts → graph/build-graph.d.ts} +3 -3
- package/lib/{build-graph.js → graph/build-graph.js} +17 -13
- package/lib/{build-graph.types.d.ts → graph/build-graph.types.d.ts} +1 -1
- package/lib/graph/check-directive-metadata.d.ts +23 -0
- package/lib/{check-directive-metadata.js → graph/check-directive-metadata.js} +7 -7
- package/lib/graph/check-directive-path-target.d.ts +32 -0
- package/lib/{check-directive-path-target.js → graph/check-directive-path-target.js} +4 -4
- package/lib/graph/check-directive-value.d.ts +19 -0
- package/lib/{check-directive-value.js → graph/check-directive-value.js} +3 -3
- package/lib/graph/check-graph.d.ts +29 -0
- package/lib/{check-graph.js → graph/check-graph.js} +6 -6
- package/lib/graph/directive-diagnostics.d.ts +20 -0
- package/lib/{directive-diagnostics.js → graph/directive-diagnostics.js} +2 -2
- package/lib/graph/directive-type-rules.d.ts +18 -0
- package/lib/{directive-type-rules.js → graph/directive-type-rules.js} +3 -3
- package/lib/{document-node-identity.d.ts → graph/document-node-identity.d.ts} +2 -2
- package/lib/{document-node-identity.js → graph/document-node-identity.js} +2 -2
- package/lib/graph/inspect-reverse-references.d.ts +22 -0
- package/lib/{inspect-reverse-references.js → graph/inspect-reverse-references.js} +2 -2
- package/lib/{load-project-graph.d.ts → graph/load-project-graph.d.ts} +10 -10
- package/lib/{load-project-graph.js → graph/load-project-graph.js} +12 -12
- package/lib/{parse-where-clause.types.d.ts → graph/parse-where-clause.types.d.ts} +1 -1
- package/lib/{query-graph.d.ts → graph/query/execute.d.ts} +11 -11
- package/lib/{query-graph.js → graph/query/execute.js} +12 -12
- package/lib/{query-inspection.d.ts → graph/query/inspect.d.ts} +10 -8
- package/lib/{query-inspection.js → graph/query/inspect.js} +16 -17
- package/lib/{parse-where-clause.d.ts → graph/query/parse.d.ts} +6 -6
- package/lib/{parse-where-clause.js → graph/query/parse.js} +2 -2
- package/lib/graph/query/resolve.d.ts +28 -0
- package/lib/{resolve-where-clause.js → graph/query/resolve.js} +39 -5
- package/lib/graph/reverse-reference-test-helpers.d.ts +55 -0
- package/lib/{command-output.js → output/command-output.js} +5 -5
- package/lib/{derived-summary.js → output/derived-summary.js} +7 -7
- package/lib/{layout-incoming-references.js → output/layout-incoming-references.js} +4 -4
- package/lib/{layout-incoming-summary-lines.js → output/layout-incoming-summary-lines.js} +0 -5
- package/lib/{layout-stored-queries.js → output/layout-stored-queries.js} +27 -11
- package/lib/{list-queries.js → output/list-queries.js} +3 -2
- package/lib/{render-check-output.js → output/render-check-output.js} +1 -1
- package/lib/{render-field-discovery.js → output/render-field-discovery.js} +3 -3
- package/lib/output/render-output-view.js +56 -0
- package/lib/{render-json-output.js → output/renderers/json.js} +10 -6
- package/lib/{render-plain-output.js → output/renderers/plain.js} +34 -33
- package/lib/{render-rich-output.js → output/renderers/rich.js} +44 -32
- package/lib/{resolve-check-target.js → output/resolve-check-target.js} +1 -1
- package/lib/{render-rich-source.js → output/rich-source/render.js} +6 -6
- package/lib/{show-document.js → output/show-document.js} +12 -12
- package/lib/{render-output-view.js → output/view-model/index.js} +11 -70
- package/lib/{write-paged-output.js → output/write-paged-output.js} +9 -5
- package/lib/{claim-helpers.d.ts → parse/claim-helpers.d.ts} +2 -2
- package/lib/{parse-jsdoc-claims.d.ts → parse/jsdoc/parse-jsdoc-claims.d.ts} +2 -2
- package/lib/{parse-jsdoc-claims.js → parse/jsdoc/parse-jsdoc-claims.js} +9 -9
- package/lib/{parse-jsdoc-prose.d.ts → parse/jsdoc/parse-jsdoc-prose.d.ts} +1 -1
- package/lib/{parse-jsdoc-prose.js → parse/jsdoc/parse-jsdoc-prose.js} +1 -1
- package/lib/{parse-markdown-claims.d.ts → parse/markdown/parse-markdown-claims.d.ts} +3 -3
- package/lib/{parse-markdown-claims.js → parse/markdown/parse-markdown-claims.js} +8 -8
- package/lib/{parse-markdown-directives.d.ts → parse/markdown/parse-markdown-directives.d.ts} +2 -2
- package/lib/{parse-markdown-directives.js → parse/markdown/parse-markdown-directives.js} +3 -3
- package/lib/{parse-claims.d.ts → parse/parse-claims.d.ts} +4 -13
- package/lib/{parse-claims.js → parse/parse-claims.js} +18 -26
- package/lib/{parse-claims.types.d.ts → parse/parse-claims.types.d.ts} +1 -1
- package/lib/{tagged-fenced-block-error.d.ts → parse/tagged-fenced/tagged-fenced-block-error.d.ts} +2 -2
- package/lib/{tagged-fenced-block-parser.d.ts → parse/tagged-fenced/tagged-fenced-block-parser.d.ts} +3 -3
- package/lib/{tagged-fenced-blocks.d.ts → parse/tagged-fenced/tagged-fenced-blocks.d.ts} +7 -7
- package/lib/{tagged-fenced-blocks.js → parse/tagged-fenced/tagged-fenced-blocks.js} +3 -3
- package/lib/{parse-yaml-claims.d.ts → parse/yaml/parse-yaml-claims.d.ts} +4 -4
- package/lib/{parse-yaml-claims.js → parse/yaml/parse-yaml-claims.js} +22 -13
- package/lib/patram.d.ts +29 -28
- package/lib/patram.js +5 -6
- package/lib/{discover-fields.js → scan/discover-fields.js} +145 -18
- package/lib/scan/list-repo-files.d.ts +16 -0
- package/lib/{list-source-files.js → scan/list-repo-files.js} +2 -35
- package/lib/{list-source-files.d.ts → scan/list-source-files.d.ts} +4 -11
- package/lib/scan/list-source-files.js +45 -0
- package/package.json +8 -7
- package/lib/build-graph.types.ts +0 -27
- package/lib/discover-fields.types.ts +0 -52
- package/lib/load-patram-config.js +0 -1215
- package/lib/load-patram-config.types.d.ts +0 -45
- package/lib/load-patram-config.types.ts +0 -56
- package/lib/output-view.types.d.ts +0 -88
- package/lib/output-view.types.ts +0 -113
- package/lib/overlay-graph.d.ts +0 -43
- package/lib/overlay-graph.js +0 -191
- package/lib/parse-claims.types.ts +0 -41
- package/lib/parse-cli-arguments.types.ts +0 -75
- package/lib/parse-where-clause.types.ts +0 -87
- package/lib/patram-cli.js +0 -593
- package/lib/patram-config.types.ts +0 -22
- package/lib/tagged-fenced-blocks.types.ts +0 -38
- /package/lib/{reverse-reference-test-helpers.js → graph/reverse-reference-test-helpers.js} +0 -0
- /package/lib/{format-derived-summary-row.js → output/format-derived-summary-row.js} +0 -0
- /package/lib/{format-node-header.js → output/format-node-header.js} +0 -0
- /package/lib/{format-output-item-block.js → output/format-output-item-block.js} +0 -0
- /package/lib/{format-output-metadata.js → output/format-output-metadata.js} +0 -0
- /package/lib/{claim-helpers.js → parse/claim-helpers.js} +0 -0
- /package/lib/{parse-jsdoc-blocks.d.ts → parse/jsdoc/parse-jsdoc-blocks.d.ts} +0 -0
- /package/lib/{parse-jsdoc-blocks.js → parse/jsdoc/parse-jsdoc-blocks.js} +0 -0
- /package/lib/{tagged-fenced-block-error.js → parse/tagged-fenced/tagged-fenced-block-error.js} +0 -0
- /package/lib/{tagged-fenced-block-markdown.d.ts → parse/tagged-fenced/tagged-fenced-block-markdown.d.ts} +0 -0
- /package/lib/{tagged-fenced-block-markdown.js → parse/tagged-fenced/tagged-fenced-block-markdown.js} +0 -0
- /package/lib/{tagged-fenced-block-metadata.d.ts → parse/tagged-fenced/tagged-fenced-block-metadata.d.ts} +0 -0
- /package/lib/{tagged-fenced-block-metadata.js → parse/tagged-fenced/tagged-fenced-block-metadata.js} +0 -0
- /package/lib/{tagged-fenced-block-parser.js → parse/tagged-fenced/tagged-fenced-block-parser.js} +0 -0
- /package/lib/{tagged-fenced-blocks.types.d.ts → parse/tagged-fenced/tagged-fenced-blocks.types.d.ts} +0 -0
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* @import { OutputStoredQueryItem } from './output-view.types.ts';
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { parseWhereClause } from '
|
|
6
|
+
import { parseWhereClause } from '../graph/query/parse.js';
|
|
7
7
|
|
|
8
8
|
const MAX_STORED_QUERY_WIDTH = 100;
|
|
9
9
|
const MIN_TERM_COLUMN_WIDTH = 20;
|
|
10
10
|
const STORED_QUERY_COLUMN_GAP = 2;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @typedef {'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain'} StoredQuerySegmentKind
|
|
13
|
+
* @typedef {'description' | 'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain'} StoredQuerySegmentKind
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -56,7 +56,8 @@ function layoutStoredQuery(output_item, name_column_width, term_column_width) {
|
|
|
56
56
|
name_column_width + STORED_QUERY_COLUMN_GAP,
|
|
57
57
|
);
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
/** @type {StoredQuerySegment[][]} */
|
|
60
|
+
const output_lines = term_lines.map((line_segments, line_index) => {
|
|
60
61
|
if (line_index === 0) {
|
|
61
62
|
return [
|
|
62
63
|
{
|
|
@@ -79,6 +80,21 @@ function layoutStoredQuery(output_item, name_column_width, term_column_width) {
|
|
|
79
80
|
...line_segments,
|
|
80
81
|
];
|
|
81
82
|
});
|
|
83
|
+
|
|
84
|
+
if (output_item.description) {
|
|
85
|
+
for (const description_line of output_item.description.split('\n')) {
|
|
86
|
+
output_lines.push([
|
|
87
|
+
{
|
|
88
|
+
kind: 'description',
|
|
89
|
+
text: `${' '.repeat(name_column_width + STORED_QUERY_COLUMN_GAP)}${description_line}`,
|
|
90
|
+
},
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
output_lines.push([]);
|
|
96
|
+
|
|
97
|
+
return output_lines;
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
/**
|
|
@@ -96,7 +112,7 @@ function createStoredQueryPhrases(where_clause) {
|
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
/**
|
|
99
|
-
* @param {import('
|
|
115
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedExpression} expression
|
|
100
116
|
* @returns {StoredQuerySegment[][]}
|
|
101
117
|
*/
|
|
102
118
|
function createExpressionPhrases(expression) {
|
|
@@ -114,7 +130,7 @@ function createExpressionPhrases(expression) {
|
|
|
114
130
|
}
|
|
115
131
|
|
|
116
132
|
/**
|
|
117
|
-
* @param {import('
|
|
133
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedExpression} expression
|
|
118
134
|
* @param {'and' | 'or'} operator
|
|
119
135
|
* @param {boolean} should_prefix_operator
|
|
120
136
|
* @returns {StoredQuerySegment[]}
|
|
@@ -139,7 +155,7 @@ function createExpressionPhrase(expression, operator, should_prefix_operator) {
|
|
|
139
155
|
}
|
|
140
156
|
|
|
141
157
|
/**
|
|
142
|
-
* @param {import('
|
|
158
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedExpression} expression
|
|
143
159
|
* @param {number} parent_precedence
|
|
144
160
|
* @returns {StoredQuerySegment[]}
|
|
145
161
|
*/
|
|
@@ -159,7 +175,7 @@ function createExpressionSegments(expression, parent_precedence) {
|
|
|
159
175
|
}
|
|
160
176
|
|
|
161
177
|
/**
|
|
162
|
-
* @param {import('
|
|
178
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedExpression} expression
|
|
163
179
|
* @returns {StoredQuerySegment[]}
|
|
164
180
|
*/
|
|
165
181
|
function createRawExpressionSegments(expression) {
|
|
@@ -202,7 +218,7 @@ function createRawExpressionSegments(expression) {
|
|
|
202
218
|
}
|
|
203
219
|
|
|
204
220
|
/**
|
|
205
|
-
* @param {import('
|
|
221
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedExpression} expression
|
|
206
222
|
* @returns {number}
|
|
207
223
|
*/
|
|
208
224
|
function getExpressionPrecedence(expression) {
|
|
@@ -230,7 +246,7 @@ function getBooleanExpressionPrecedence(operator) {
|
|
|
230
246
|
}
|
|
231
247
|
|
|
232
248
|
/**
|
|
233
|
-
* @param {import('
|
|
249
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedTerm} term
|
|
234
250
|
* @returns {StoredQuerySegment[]}
|
|
235
251
|
*/
|
|
236
252
|
function createTermSegments(term) {
|
|
@@ -265,7 +281,7 @@ function createTermSegments(term) {
|
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
/**
|
|
268
|
-
* @param {import('
|
|
284
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedFieldSetTerm} term
|
|
269
285
|
* @returns {StoredQuerySegment[]}
|
|
270
286
|
*/
|
|
271
287
|
function createFieldSetSegments(term) {
|
|
@@ -281,7 +297,7 @@ function createFieldSetSegments(term) {
|
|
|
281
297
|
}
|
|
282
298
|
|
|
283
299
|
/**
|
|
284
|
-
* @param {import('
|
|
300
|
+
* @param {import('../graph/parse-where-clause.types.ts').ParsedAggregateTerm} term
|
|
285
301
|
* @returns {StoredQuerySegment[]}
|
|
286
302
|
*/
|
|
287
303
|
function createAggregateSegments(term) {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { StoredQueryConfig } from '
|
|
2
|
+
* @import { StoredQueryConfig } from '../config/load-patram-config.types.ts';
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* List stored queries in stable name order.
|
|
7
7
|
*
|
|
8
8
|
* @param {Record<string, StoredQueryConfig>} stored_queries
|
|
9
|
-
* @returns {{ name: string, where: string }[]}
|
|
9
|
+
* @returns {{ name: string, where: string, description?: string }[]}
|
|
10
10
|
*/
|
|
11
11
|
export function listQueries(stored_queries) {
|
|
12
12
|
return Object.entries(stored_queries)
|
|
13
13
|
.sort(([left_name], [right_name]) => left_name.localeCompare(right_name))
|
|
14
14
|
.map(([name, stored_query]) => ({
|
|
15
|
+
description: stored_query.description,
|
|
15
16
|
name,
|
|
16
17
|
where: stored_query.where,
|
|
17
18
|
}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { ResolvedOutputMode } from './output-view.types.ts';
|
|
3
|
-
* @import { FieldDiscoveryResult, FieldDiscoverySuggestion } from '
|
|
3
|
+
* @import { FieldDiscoveryResult, FieldDiscoverySuggestion } from '../scan/discover-fields.types.ts';
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Ansis } from 'ansis';
|
|
@@ -135,7 +135,7 @@ function formatTextFieldSuggestion(field_suggestion, render_options) {
|
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
137
|
* @param {string} section_title
|
|
138
|
-
* @param {import('
|
|
138
|
+
* @param {import('../scan/discover-fields.types.ts').FieldDiscoveryEvidenceReference[]} evidence_references
|
|
139
139
|
* @param {{ header: (value: string) => string, label: (value: string) => string }} render_options
|
|
140
140
|
* @returns {string[]}
|
|
141
141
|
*/
|
|
@@ -168,7 +168,7 @@ function formatTextEvidenceSection(
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* @param {import('
|
|
171
|
+
* @param {import('../scan/discover-fields.types.ts').FieldDiscoveryEvidenceReference} evidence_reference
|
|
172
172
|
* @returns {string}
|
|
173
173
|
*/
|
|
174
174
|
function formatEvidenceReference(evidence_reference) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { ParsedCliArguments } from '../cli/arguments.types.ts';
|
|
3
|
+
* @import { ResolvedOutputMode, OutputView } from './output-view.types.ts';
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { renderJsonOutput } from './renderers/json.js';
|
|
7
|
+
import { renderPlainOutput } from './renderers/plain.js';
|
|
8
|
+
import { renderRichOutput } from './renderers/rich.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Shared command output views.
|
|
12
|
+
*
|
|
13
|
+
* Normalizes `query`, `queries`, and `show` results into renderer-specific
|
|
14
|
+
* output models.
|
|
15
|
+
*
|
|
16
|
+
* Kind: output
|
|
17
|
+
* Status: active
|
|
18
|
+
* Tracked in: ../../docs/plans/v0/source-anchor-dogfooding.md
|
|
19
|
+
* Decided by: ../../docs/decisions/cli-output-architecture.md
|
|
20
|
+
* @patram
|
|
21
|
+
* @see {@link ./show-document.js}
|
|
22
|
+
* @see {@link ../../docs/decisions/cli-output-architecture.md}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
createOutputView,
|
|
27
|
+
createRefsOutputView,
|
|
28
|
+
createShowOutputView,
|
|
29
|
+
} from './view-model/index.js';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Render one shared output view through the resolved renderer.
|
|
33
|
+
*
|
|
34
|
+
* @param {OutputView} output_view
|
|
35
|
+
* @param {ResolvedOutputMode} output_mode
|
|
36
|
+
* @param {ParsedCliArguments} parsed_arguments
|
|
37
|
+
* @returns {Promise<string>}
|
|
38
|
+
*/
|
|
39
|
+
export async function renderOutputView(
|
|
40
|
+
output_view,
|
|
41
|
+
output_mode,
|
|
42
|
+
parsed_arguments,
|
|
43
|
+
) {
|
|
44
|
+
if (output_mode.renderer_name === 'json') {
|
|
45
|
+
return renderJsonOutput(output_view);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (output_mode.renderer_name === 'plain') {
|
|
49
|
+
return renderPlainOutput(output_view);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return renderRichOutput(output_view, {
|
|
53
|
+
color_enabled: output_mode.color_enabled,
|
|
54
|
+
color_mode: parsed_arguments.color_mode,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView } from '
|
|
2
|
+
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView } from '../output-view.types.ts';
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -92,9 +92,6 @@ function renderJsonRefsOutput(output_view) {
|
|
|
92
92
|
function renderJsonShowOutput(output_view) {
|
|
93
93
|
return `${JSON.stringify(
|
|
94
94
|
{
|
|
95
|
-
document: output_view.document
|
|
96
|
-
? formatJsonNodeItem(output_view.document)
|
|
97
|
-
: undefined,
|
|
98
95
|
incoming_summary: output_view.incoming_summary,
|
|
99
96
|
source: output_view.source,
|
|
100
97
|
resolved_links: output_view.items.map(formatJsonResolvedLink),
|
|
@@ -144,13 +141,20 @@ function formatJsonNodeItem(output_item) {
|
|
|
144
141
|
|
|
145
142
|
/**
|
|
146
143
|
* @param {OutputStoredQueryItem} output_item
|
|
147
|
-
* @returns {{ name: string, where: string }}
|
|
144
|
+
* @returns {{ name: string, where: string, description?: string }}
|
|
148
145
|
*/
|
|
149
146
|
function formatJsonStoredQuery(output_item) {
|
|
150
|
-
|
|
147
|
+
/** @type {{ description?: string, name: string, where: string }} */
|
|
148
|
+
const stored_query = {
|
|
151
149
|
name: output_item.name,
|
|
152
150
|
where: output_item.where,
|
|
153
151
|
};
|
|
152
|
+
|
|
153
|
+
if (output_item.description) {
|
|
154
|
+
stored_query.description = output_item.description;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return stored_query;
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
/**
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView, QueryOutputView, RefsOutputView, ShowOutputView } from '
|
|
2
|
+
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView, QueryOutputView, RefsOutputView, ShowOutputView } from '../output-view.types.ts';
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
formatOutputNodeMetadataRows,
|
|
7
7
|
formatResolvedLinkMetadataRows,
|
|
8
|
-
} from '
|
|
9
|
-
import { formatNodeHeader } from '
|
|
10
|
-
import { formatOutputItemBlock } from '
|
|
11
|
-
import { layoutIncomingReferenceLines } from '
|
|
12
|
-
import { layoutIncomingSummaryLines } from '
|
|
13
|
-
import { layoutStoredQueries } from '
|
|
8
|
+
} from '../format-output-metadata.js';
|
|
9
|
+
import { formatNodeHeader } from '../format-node-header.js';
|
|
10
|
+
import { formatOutputItemBlock } from '../format-output-item-block.js';
|
|
11
|
+
import { layoutIncomingReferenceLines } from '../layout-incoming-references.js';
|
|
12
|
+
import { layoutIncomingSummaryLines } from '../layout-incoming-summary-lines.js';
|
|
13
|
+
import { layoutStoredQueries } from '../layout-stored-queries.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Render the canonical plain output for one output view.
|
|
@@ -24,7 +24,7 @@ export function renderPlainOutput(output_view) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (output_view.command === 'queries') {
|
|
27
|
-
return renderPlainStoredQueries(output_view
|
|
27
|
+
return renderPlainStoredQueries(output_view);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
if (output_view.command === 'refs') {
|
|
@@ -69,17 +69,23 @@ function renderPlainEmptyQuery(footer) {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* @param {
|
|
72
|
+
* @param {Extract<OutputView, { command: 'queries' }>} output_view
|
|
73
73
|
* @returns {string}
|
|
74
74
|
*/
|
|
75
|
-
function renderPlainStoredQueries(
|
|
76
|
-
if (
|
|
75
|
+
function renderPlainStoredQueries(output_view) {
|
|
76
|
+
if (output_view.items.length === 0) {
|
|
77
77
|
return '';
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
const output_lines = layoutStoredQueries(output_view.items).map(
|
|
81
|
+
formatPlainStoredQueryLine,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
if (output_view.hints.length === 0) {
|
|
85
|
+
return `${output_lines.join('\n')}\n`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return `${output_lines.join('\n')}\n${output_view.hints.join('\n')}\n`;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
/**
|
|
@@ -88,29 +94,12 @@ function renderPlainStoredQueries(output_items) {
|
|
|
88
94
|
*/
|
|
89
95
|
function renderPlainShowOutput(output_view) {
|
|
90
96
|
const rendered_source = trimTrailingLineBreaks(output_view.rendered_source);
|
|
91
|
-
const document_summary = output_view.document
|
|
92
|
-
? formatPlainNodeItem(output_view.document)
|
|
93
|
-
: '';
|
|
94
97
|
const incoming_summary = renderPlainIncomingSummary(output_view);
|
|
95
98
|
|
|
96
|
-
if (
|
|
97
|
-
document_summary.length === 0 &&
|
|
98
|
-
output_view.items.length === 0 &&
|
|
99
|
-
incoming_summary.length === 0
|
|
100
|
-
) {
|
|
99
|
+
if (output_view.items.length === 0 && incoming_summary.length === 0) {
|
|
101
100
|
return `${rendered_source}\n`;
|
|
102
101
|
}
|
|
103
|
-
|
|
104
|
-
/** @type {string[]} */
|
|
105
|
-
const summary_items = [];
|
|
106
|
-
|
|
107
|
-
if (document_summary.length > 0) {
|
|
108
|
-
summary_items.push(document_summary);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
summary_items.push(...output_view.items.map(formatPlainResolvedLinkItem));
|
|
112
|
-
|
|
113
|
-
const summary_blocks = summary_items.filter((summary_item) => summary_item);
|
|
102
|
+
const summary_blocks = output_view.items.map(formatPlainResolvedLinkItem);
|
|
114
103
|
|
|
115
104
|
if (incoming_summary.length > 0) {
|
|
116
105
|
summary_blocks.push(incoming_summary);
|
|
@@ -172,12 +161,24 @@ function formatPlainResolvedLinkItem(output_item) {
|
|
|
172
161
|
* @returns {string}
|
|
173
162
|
*/
|
|
174
163
|
function renderPlainIncomingSummary(output_view) {
|
|
164
|
+
if (!hasIncomingSummary(output_view.incoming_summary)) {
|
|
165
|
+
return '';
|
|
166
|
+
}
|
|
167
|
+
|
|
175
168
|
const output_lines = layoutIncomingSummaryLines(output_view.incoming_summary);
|
|
176
169
|
output_lines.push('', `Hint: patram refs ${output_view.path}`);
|
|
177
170
|
|
|
178
171
|
return output_lines.join('\n');
|
|
179
172
|
}
|
|
180
173
|
|
|
174
|
+
/**
|
|
175
|
+
* @param {Record<string, number>} incoming_summary
|
|
176
|
+
* @returns {boolean}
|
|
177
|
+
*/
|
|
178
|
+
function hasIncomingSummary(incoming_summary) {
|
|
179
|
+
return Object.keys(incoming_summary).length > 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
181
182
|
/**
|
|
182
183
|
* @param {string} value
|
|
183
184
|
* @returns {string}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { CliColorMode } from '
|
|
3
|
-
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView, QueryOutputView, RefsOutputView, ShowOutputView } from '
|
|
2
|
+
* @import { CliColorMode } from '../../cli/arguments.types.ts';
|
|
3
|
+
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView, QueryOutputView, RefsOutputView, ShowOutputView } from '../output-view.types.ts';
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Ansis } from 'ansis';
|
|
@@ -8,13 +8,13 @@ import { Ansis } from 'ansis';
|
|
|
8
8
|
import {
|
|
9
9
|
formatOutputNodeMetadataRows,
|
|
10
10
|
formatResolvedLinkMetadataRows,
|
|
11
|
-
} from '
|
|
12
|
-
import { formatNodeHeader } from '
|
|
13
|
-
import { formatOutputItemBlock } from '
|
|
14
|
-
import { layoutIncomingReferenceLines } from '
|
|
15
|
-
import { layoutIncomingSummaryLines } from '
|
|
16
|
-
import { layoutStoredQueries } from '
|
|
17
|
-
import { renderRichSource } from '
|
|
11
|
+
} from '../format-output-metadata.js';
|
|
12
|
+
import { formatNodeHeader } from '../format-node-header.js';
|
|
13
|
+
import { formatOutputItemBlock } from '../format-output-item-block.js';
|
|
14
|
+
import { layoutIncomingReferenceLines } from '../layout-incoming-references.js';
|
|
15
|
+
import { layoutIncomingSummaryLines } from '../layout-incoming-summary-lines.js';
|
|
16
|
+
import { layoutStoredQueries } from '../layout-stored-queries.js';
|
|
17
|
+
import { renderRichSource } from '../rich-source/render.js';
|
|
18
18
|
|
|
19
19
|
const FULL_WIDTH_DIVIDER = ` ${'─'.repeat(78)} `;
|
|
20
20
|
|
|
@@ -33,7 +33,7 @@ export async function renderRichOutput(output_view, render_options) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (output_view.command === 'queries') {
|
|
36
|
-
return renderRichStoredQueries(output_view
|
|
36
|
+
return renderRichStoredQueries(output_view, ansi);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (output_view.command === 'refs') {
|
|
@@ -83,18 +83,24 @@ function renderRichEmptyQuery(footer, ansi) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* @param {
|
|
86
|
+
* @param {Extract<OutputView, { command: 'queries' }>} output_view
|
|
87
87
|
* @param {Ansis} ansi
|
|
88
88
|
* @returns {string}
|
|
89
89
|
*/
|
|
90
|
-
function renderRichStoredQueries(
|
|
91
|
-
if (
|
|
90
|
+
function renderRichStoredQueries(output_view, ansi) {
|
|
91
|
+
if (output_view.items.length === 0) {
|
|
92
92
|
return '';
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
const output_lines = layoutStoredQueries(output_view.items).map(
|
|
96
|
+
(line_segments) => formatRichStoredQueryLine(line_segments, ansi),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
if (output_view.hints.length === 0) {
|
|
100
|
+
return `${output_lines.join('\n')}\n`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `${output_lines.join('\n')}\n${output_view.hints.map((hint) => ansi.gray(hint)).join('\n')}\n`;
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
/**
|
|
@@ -107,20 +113,14 @@ async function renderRichShowOutput(output_view, render_options, ansi) {
|
|
|
107
113
|
const rendered_source = trimTrailingLineBreaks(
|
|
108
114
|
await renderRichSource(output_view, render_options),
|
|
109
115
|
);
|
|
110
|
-
const document_summary = output_view.document
|
|
111
|
-
? formatRichNodeItem(output_view.document, ansi)
|
|
112
|
-
: '';
|
|
113
116
|
const incoming_summary = renderRichIncomingSummary(output_view, ansi);
|
|
114
117
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (document_summary.length > 0) {
|
|
119
|
-
summary_items.push(document_summary);
|
|
118
|
+
if (output_view.items.length === 0 && incoming_summary.length === 0) {
|
|
119
|
+
return `${rendered_source}\n`;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
summary_items.
|
|
123
|
-
|
|
122
|
+
const summary_items = output_view.items.map((item) =>
|
|
123
|
+
formatRichResolvedLinkItem(item, ansi),
|
|
124
124
|
);
|
|
125
125
|
|
|
126
126
|
if (incoming_summary.length > 0) {
|
|
@@ -165,7 +165,7 @@ function formatRichNodeItem(output_item, ansi) {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
|
-
* @param {{ kind: 'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain', text: string }[]} line_segments
|
|
168
|
+
* @param {{ kind: 'description' | 'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain', text: string }[]} line_segments
|
|
169
169
|
* @param {Ansis} ansi
|
|
170
170
|
* @returns {string}
|
|
171
171
|
*/
|
|
@@ -195,18 +195,26 @@ function formatRichResolvedLinkItem(output_item, ansi) {
|
|
|
195
195
|
* @returns {string}
|
|
196
196
|
*/
|
|
197
197
|
function renderRichIncomingSummary(output_view, ansi) {
|
|
198
|
+
if (!hasIncomingSummary(output_view.incoming_summary)) {
|
|
199
|
+
return '';
|
|
200
|
+
}
|
|
201
|
+
|
|
198
202
|
const output_lines = layoutIncomingSummaryLines(output_view.incoming_summary);
|
|
199
203
|
output_lines[0] = ansi.bold(output_lines[0]);
|
|
200
204
|
|
|
201
|
-
if (Object.keys(output_view.incoming_summary).length === 0) {
|
|
202
|
-
output_lines[1] = ` ${ansi.gray('none')}`;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
205
|
output_lines.push('', ansi.gray(`Hint: patram refs ${output_view.path}`));
|
|
206
206
|
|
|
207
207
|
return output_lines.join('\n');
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
/**
|
|
211
|
+
* @param {Record<string, number>} incoming_summary
|
|
212
|
+
* @returns {boolean}
|
|
213
|
+
*/
|
|
214
|
+
function hasIncomingSummary(incoming_summary) {
|
|
215
|
+
return Object.keys(incoming_summary).length > 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
210
218
|
/**
|
|
211
219
|
* @param {boolean} color_enabled
|
|
212
220
|
* @returns {Ansis}
|
|
@@ -216,7 +224,7 @@ function createAnsi(color_enabled) {
|
|
|
216
224
|
}
|
|
217
225
|
|
|
218
226
|
/**
|
|
219
|
-
* @param {{ kind: 'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain', text: string }} line_segment
|
|
227
|
+
* @param {{ kind: 'description' | 'field_name' | 'keyword' | 'literal' | 'name' | 'operator' | 'plain', text: string }} line_segment
|
|
220
228
|
* @param {Ansis} ansi
|
|
221
229
|
* @returns {string}
|
|
222
230
|
*/
|
|
@@ -225,6 +233,10 @@ function styleStoredQuerySegment(line_segment, ansi) {
|
|
|
225
233
|
return ansi.green(line_segment.text);
|
|
226
234
|
}
|
|
227
235
|
|
|
236
|
+
if (line_segment.kind === 'description') {
|
|
237
|
+
return ansi.gray(line_segment.text);
|
|
238
|
+
}
|
|
239
|
+
|
|
228
240
|
if (line_segment.kind === 'operator') {
|
|
229
241
|
return ansi.gray(line_segment.text);
|
|
230
242
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @import { ComarkElement, ComarkNode } from 'md4x';
|
|
4
4
|
* @import { BundledLanguage } from 'shiki';
|
|
5
|
-
* @import { CliColorMode } from '
|
|
6
|
-
* @import { OutputResolvedLinkItem, ShowOutputView } from '
|
|
5
|
+
* @import { CliColorMode } from '../../cli/arguments.types.ts';
|
|
6
|
+
* @import { OutputResolvedLinkItem, ShowOutputView } from '../output-view.types.ts';
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { extname } from 'node:path';
|
|
@@ -969,8 +969,8 @@ function shouldRenderListItemGap(previous_item, next_item, has_blank_line_gap) {
|
|
|
969
969
|
}
|
|
970
970
|
|
|
971
971
|
return (
|
|
972
|
-
|
|
973
|
-
|
|
972
|
+
isSingleParagraphTopLevelListItem(previous_item) &&
|
|
973
|
+
isSingleParagraphTopLevelListItem(next_item)
|
|
974
974
|
);
|
|
975
975
|
}
|
|
976
976
|
|
|
@@ -978,7 +978,7 @@ function shouldRenderListItemGap(previous_item, next_item, has_blank_line_gap) {
|
|
|
978
978
|
* @param {ComarkElement} item_node
|
|
979
979
|
* @returns {boolean}
|
|
980
980
|
*/
|
|
981
|
-
function
|
|
981
|
+
function isSingleParagraphTopLevelListItem(item_node) {
|
|
982
982
|
const item_children = getElementChildren(item_node);
|
|
983
983
|
|
|
984
984
|
if (item_children.length !== 1) {
|
|
@@ -994,7 +994,7 @@ function isSimpleTopLevelListItem(item_node) {
|
|
|
994
994
|
return false;
|
|
995
995
|
}
|
|
996
996
|
|
|
997
|
-
return
|
|
997
|
+
return true;
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
1000
|
/**
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
/**
|
|
3
|
-
* @import { BuildGraphResult, GraphNode } from '
|
|
4
|
-
* @import { PatramClaim } from '
|
|
5
|
-
* @import { PatramDiagnostic } from '
|
|
3
|
+
* @import { BuildGraphResult, GraphNode } from '../graph/build-graph.types.ts';
|
|
4
|
+
* @import { PatramClaim } from '../parse/parse-claims.types.ts';
|
|
5
|
+
* @import { PatramDiagnostic } from '../config/load-patram-config.types.ts';
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { readFile } from 'node:fs/promises';
|
|
9
9
|
import { posix, relative, resolve } from 'node:path';
|
|
10
10
|
|
|
11
|
-
import { resolveDocumentNodeId } from '
|
|
12
|
-
import { inspectReverseReferences } from '
|
|
13
|
-
import { parseSourceFile } from '
|
|
11
|
+
import { resolveDocumentNodeId } from '../graph/build-graph-identity.js';
|
|
12
|
+
import { inspectReverseReferences } from '../graph/inspect-reverse-references.js';
|
|
13
|
+
import { parseSourceFile } from '../parse/parse-claims.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Show command document rendering.
|
|
@@ -20,12 +20,12 @@ import { parseSourceFile } from './parse-claims.js';
|
|
|
20
20
|
*
|
|
21
21
|
* Kind: output
|
|
22
22
|
* Status: active
|
|
23
|
-
* Tracked in:
|
|
24
|
-
* Decided by:
|
|
25
|
-
* Decided by:
|
|
23
|
+
* Tracked in: ../../docs/plans/v0/source-anchor-dogfooding.md
|
|
24
|
+
* Decided by: ../../docs/decisions/show-output.md
|
|
25
|
+
* Decided by: ../../docs/decisions/source-rendering.md
|
|
26
26
|
* @patram
|
|
27
27
|
* @see {@link ./render-output-view.js}
|
|
28
|
-
* @see {@link
|
|
28
|
+
* @see {@link ../../docs/decisions/show-output.md}
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -107,7 +107,7 @@ export async function loadShowOutput(
|
|
|
107
107
|
* @param {string} source_text
|
|
108
108
|
* @param {PatramClaim[]} claims
|
|
109
109
|
* @param {BuildGraphResult} graph
|
|
110
|
-
* @param {import('
|
|
110
|
+
* @param {import('../graph/build-graph.types.ts').BuildGraphResult['document_node_ids']} document_node_ids
|
|
111
111
|
* @param {Record<string, GraphNode>} graph_nodes
|
|
112
112
|
* @returns {{ incoming_summary: Record<string, number>, path: string, rendered_source: string, resolved_links: Array<{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }>, source: string }}
|
|
113
113
|
*/
|
|
@@ -219,7 +219,7 @@ function renderResolvedSourceLine(
|
|
|
219
219
|
* @param {string} source_file_path
|
|
220
220
|
* @param {PatramClaim} claim
|
|
221
221
|
* @param {number} reference
|
|
222
|
-
* @param {import('
|
|
222
|
+
* @param {import('../graph/build-graph.types.ts').BuildGraphResult['document_node_ids']} document_node_ids
|
|
223
223
|
* @param {Record<string, GraphNode>} graph_nodes
|
|
224
224
|
* @returns {{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }}
|
|
225
225
|
*/
|