patram 0.1.1 → 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/lib/build-graph-identity.js +57 -24
- package/lib/build-graph.js +383 -17
- package/lib/build-graph.types.ts +5 -2
- package/lib/check-directive-metadata.js +516 -0
- package/lib/check-directive-value.js +282 -0
- package/lib/check-graph.js +24 -5
- package/lib/cli-help-metadata.js +580 -0
- package/lib/derived-summary.js +280 -0
- package/lib/directive-diagnostics.js +38 -0
- package/lib/directive-type-rules.js +133 -0
- package/lib/discover-fields.js +427 -0
- package/lib/discover-fields.types.ts +52 -0
- package/lib/format-derived-summary-row.js +9 -0
- package/lib/format-node-header.js +21 -0
- package/lib/format-output-item-block.js +22 -0
- package/lib/format-output-metadata.js +54 -0
- package/lib/layout-stored-queries.js +96 -2
- package/lib/load-patram-config.js +754 -18
- package/lib/load-patram-config.types.ts +128 -2
- package/lib/load-project-graph.js +4 -1
- package/lib/output-view.types.ts +29 -6
- package/lib/parse-cli-arguments-helpers.js +263 -90
- package/lib/parse-cli-arguments.js +160 -8
- package/lib/parse-cli-arguments.types.ts +49 -4
- package/lib/parse-where-clause.js +670 -209
- package/lib/parse-where-clause.types.ts +72 -0
- package/lib/patram-cli.js +180 -21
- package/lib/patram-config.js +31 -31
- package/lib/patram-config.types.ts +10 -4
- package/lib/patram.js +6 -0
- package/lib/query-graph.js +444 -113
- package/lib/query-inspection.js +798 -0
- package/lib/render-check-output.js +1 -1
- package/lib/render-cli-help.js +419 -0
- package/lib/render-field-discovery.js +148 -0
- package/lib/render-json-output.js +66 -14
- package/lib/render-output-view.js +272 -22
- package/lib/render-plain-output.js +31 -86
- package/lib/render-rich-output.js +34 -87
- package/lib/resolve-patram-graph-config.js +15 -9
- package/lib/resolve-where-clause.js +18 -3
- package/lib/show-document.js +51 -7
- package/lib/tagged-fenced-block-error.js +17 -0
- package/lib/tagged-fenced-block-markdown.js +111 -0
- package/lib/tagged-fenced-block-metadata.js +97 -0
- package/lib/tagged-fenced-block-parser.js +292 -0
- package/lib/tagged-fenced-blocks.js +100 -0
- package/lib/tagged-fenced-blocks.types.ts +38 -0
- package/package.json +12 -7
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/** @import * as $k$$l$output$j$view$k$types$k$ts from './output-view.types.ts'; */
|
|
2
|
+
/* eslint-disable max-lines */
|
|
2
3
|
/**
|
|
3
|
-
* @import { GraphNode } from './build-graph.types.ts';
|
|
4
|
+
* @import { BuildGraphResult, GraphNode } from './build-graph.types.ts';
|
|
5
|
+
* @import { DerivedSummaryEvaluator } from './derived-summary.js';
|
|
6
|
+
* @import { PatramRepoConfig } from './load-patram-config.types.ts';
|
|
4
7
|
* @import { ParsedCliArguments } from './parse-cli-arguments.types.ts';
|
|
5
|
-
* @import { OutputStoredQueryItem, OutputView, ResolvedOutputMode, ShowOutputView } from './output-view.types.ts';
|
|
8
|
+
* @import { OutputMetadataField, OutputStoredQueryItem, OutputView, ResolvedOutputMode, ShowOutputView } from './output-view.types.ts';
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
11
|
import { renderJsonOutput } from './render-json-output.js';
|
|
@@ -29,7 +32,7 @@ import { renderRichOutput } from './render-rich-output.js';
|
|
|
29
32
|
*
|
|
30
33
|
* @param {'query' | 'queries'} command_name
|
|
31
34
|
* @param {GraphNode[] | { name: string, where: string }[]} command_items
|
|
32
|
-
* @param {{ hints?: string[], limit?: number, offset?: number, total_count?: number }=} command_options
|
|
35
|
+
* @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
|
|
33
36
|
* @returns {OutputView}
|
|
34
37
|
*/
|
|
35
38
|
export function createOutputView(command_name, command_items, command_options) {
|
|
@@ -53,17 +56,38 @@ export function createOutputView(command_name, command_items, command_options) {
|
|
|
53
56
|
* Create a shared output view for the show command.
|
|
54
57
|
*
|
|
55
58
|
* @param {{ path: string, rendered_source: string, resolved_links: Array<{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }>, source: string }} show_output
|
|
59
|
+
* @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }=} command_options
|
|
56
60
|
* @returns {ShowOutputView}
|
|
57
61
|
*/
|
|
58
|
-
export function createShowOutputView(show_output) {
|
|
62
|
+
export function createShowOutputView(show_output, command_options = {}) {
|
|
63
|
+
const shown_document_node =
|
|
64
|
+
command_options.graph_nodes?.[`doc:${show_output.path}`];
|
|
65
|
+
|
|
59
66
|
return {
|
|
60
67
|
command: 'show',
|
|
68
|
+
document: shown_document_node
|
|
69
|
+
? createOutputNodeItem(
|
|
70
|
+
shown_document_node,
|
|
71
|
+
command_options.derived_summary_evaluator?.evaluate(
|
|
72
|
+
shown_document_node,
|
|
73
|
+
) ?? null,
|
|
74
|
+
command_options.repo_config?.fields ?? {},
|
|
75
|
+
)
|
|
76
|
+
: undefined,
|
|
61
77
|
hints: [],
|
|
62
78
|
items: show_output.resolved_links.map((resolved_link) => ({
|
|
63
79
|
kind: 'resolved_link',
|
|
64
80
|
label: resolved_link.label,
|
|
65
81
|
reference: resolved_link.reference,
|
|
66
|
-
target: createResolvedLinkTarget(
|
|
82
|
+
target: createResolvedLinkTarget(
|
|
83
|
+
resolved_link.target,
|
|
84
|
+
command_options.repo_config?.fields ?? {},
|
|
85
|
+
command_options.graph_nodes?.[`doc:${resolved_link.target.path}`]
|
|
86
|
+
? (command_options.derived_summary_evaluator?.evaluate(
|
|
87
|
+
command_options.graph_nodes[`doc:${resolved_link.target.path}`],
|
|
88
|
+
) ?? null)
|
|
89
|
+
: null,
|
|
90
|
+
),
|
|
67
91
|
})),
|
|
68
92
|
path: show_output.path,
|
|
69
93
|
rendered_source: show_output.rendered_source,
|
|
@@ -104,7 +128,7 @@ export async function renderOutputView(
|
|
|
104
128
|
|
|
105
129
|
/**
|
|
106
130
|
* @param {GraphNode[]} graph_nodes
|
|
107
|
-
* @param {{ hints?: string[], limit?: number, offset?: number, total_count?: number }=} command_options
|
|
131
|
+
* @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
|
|
108
132
|
* @returns {OutputView}
|
|
109
133
|
*/
|
|
110
134
|
function createQueryOutputView(graph_nodes, command_options = {}) {
|
|
@@ -114,8 +138,14 @@ function createQueryOutputView(graph_nodes, command_options = {}) {
|
|
|
114
138
|
command: 'query',
|
|
115
139
|
hints:
|
|
116
140
|
command_options.hints ??
|
|
117
|
-
(total_count === 0 ? ['Try: patram query --where "
|
|
118
|
-
items: graph_nodes.map(
|
|
141
|
+
(total_count === 0 ? ['Try: patram query --where "$class=task"'] : []),
|
|
142
|
+
items: graph_nodes.map((graph_node) =>
|
|
143
|
+
createOutputNodeItem(
|
|
144
|
+
graph_node,
|
|
145
|
+
command_options.derived_summary_evaluator?.evaluate(graph_node) ?? null,
|
|
146
|
+
command_options.repo_config?.fields ?? {},
|
|
147
|
+
),
|
|
148
|
+
),
|
|
119
149
|
summary: {
|
|
120
150
|
count: graph_nodes.length,
|
|
121
151
|
kind: 'result_list',
|
|
@@ -148,46 +178,266 @@ function createStoredQueriesOutputView(stored_queries) {
|
|
|
148
178
|
|
|
149
179
|
/**
|
|
150
180
|
* @param {GraphNode} graph_node
|
|
181
|
+
* @param {import('./output-view.types.ts').OutputDerivedSummary | null} derived_summary
|
|
182
|
+
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
151
183
|
* @returns {$k$$l$output$j$view$k$types$k$ts.OutputNodeItem}
|
|
152
184
|
*/
|
|
153
|
-
function createOutputNodeItem(graph_node) {
|
|
154
|
-
const title =
|
|
155
|
-
|
|
185
|
+
function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
|
|
186
|
+
const title = getOutputNodeTitle(graph_node);
|
|
187
|
+
const path = getOutputNodePath(graph_node);
|
|
188
|
+
const node_class = getOutputNodeClass(graph_node);
|
|
189
|
+
const fields = collectOutputFields(graph_node, field_definitions);
|
|
190
|
+
const visible_fields = createVisibleOutputFields(fields, field_definitions);
|
|
156
191
|
|
|
157
|
-
if (!title || !
|
|
192
|
+
if (!title || !node_class) {
|
|
158
193
|
throw new Error(
|
|
159
194
|
`Expected graph node "${graph_node.id}" to have a title and path.`,
|
|
160
195
|
);
|
|
161
196
|
}
|
|
162
197
|
|
|
163
198
|
return {
|
|
164
|
-
|
|
199
|
+
derived_summary: derived_summary ?? undefined,
|
|
200
|
+
fields,
|
|
201
|
+
id: getOutputNodeId(graph_node),
|
|
165
202
|
kind: 'node',
|
|
166
|
-
node_kind:
|
|
167
|
-
path
|
|
168
|
-
status: graph_node.status,
|
|
203
|
+
node_kind: node_class,
|
|
204
|
+
path,
|
|
169
205
|
title,
|
|
206
|
+
visible_fields,
|
|
170
207
|
};
|
|
171
208
|
}
|
|
172
209
|
|
|
173
210
|
/**
|
|
174
211
|
* @param {{ kind?: string, path: string, status?: string, title: string }} target
|
|
212
|
+
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
213
|
+
* @param {import('./output-view.types.ts').OutputDerivedSummary | null} derived_summary
|
|
175
214
|
* @returns {$k$$l$output$j$view$k$types$k$ts.OutputResolvedLinkTarget}
|
|
176
215
|
*/
|
|
177
|
-
function createResolvedLinkTarget(target) {
|
|
216
|
+
function createResolvedLinkTarget(target, field_definitions, derived_summary) {
|
|
217
|
+
/** @type {Record<string, string | string[]>} */
|
|
218
|
+
const fields = {};
|
|
219
|
+
|
|
220
|
+
if (target.status) {
|
|
221
|
+
fields.status = target.status;
|
|
222
|
+
}
|
|
223
|
+
|
|
178
224
|
/** @type {$k$$l$output$j$view$k$types$k$ts.OutputResolvedLinkTarget} */
|
|
179
225
|
const resolved_target = {
|
|
226
|
+
derived_summary: derived_summary ?? undefined,
|
|
227
|
+
fields,
|
|
228
|
+
id: `doc:${target.path}`,
|
|
229
|
+
kind: target.kind ?? 'document',
|
|
180
230
|
path: target.path,
|
|
181
231
|
title: target.title,
|
|
232
|
+
visible_fields: createVisibleOutputFields(fields, field_definitions),
|
|
182
233
|
};
|
|
183
234
|
|
|
184
|
-
|
|
185
|
-
|
|
235
|
+
return resolved_target;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @param {string | string[] | undefined} field_value
|
|
240
|
+
* @returns {string | undefined}
|
|
241
|
+
*/
|
|
242
|
+
function getScalarGraphNodeField(field_value) {
|
|
243
|
+
if (Array.isArray(field_value)) {
|
|
244
|
+
return field_value[0];
|
|
186
245
|
}
|
|
187
246
|
|
|
188
|
-
|
|
189
|
-
|
|
247
|
+
return field_value;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {GraphNode} graph_node
|
|
252
|
+
* @returns {string | undefined}
|
|
253
|
+
*/
|
|
254
|
+
function getOutputNodeTitle(graph_node) {
|
|
255
|
+
return (
|
|
256
|
+
getScalarGraphNodeField(graph_node.title) ??
|
|
257
|
+
getScalarGraphNodeField(graph_node.label) ??
|
|
258
|
+
getOutputNodePath(graph_node) ??
|
|
259
|
+
getScalarGraphNodeField(graph_node.key)
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @param {GraphNode} graph_node
|
|
265
|
+
* @returns {string | undefined}
|
|
266
|
+
*/
|
|
267
|
+
function getOutputNodePath(graph_node) {
|
|
268
|
+
return getScalarGraphNodeField(graph_node.$path ?? graph_node.path);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @param {GraphNode} graph_node
|
|
273
|
+
* @returns {string | undefined}
|
|
274
|
+
*/
|
|
275
|
+
function getOutputNodeClass(graph_node) {
|
|
276
|
+
return getScalarGraphNodeField(graph_node.$class ?? graph_node.kind);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @param {GraphNode} graph_node
|
|
281
|
+
* @returns {string}
|
|
282
|
+
*/
|
|
283
|
+
function getOutputNodeId(graph_node) {
|
|
284
|
+
return (
|
|
285
|
+
getScalarGraphNodeField(graph_node.$id ?? graph_node.id) ?? graph_node.id
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @param {GraphNode} graph_node
|
|
291
|
+
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
292
|
+
* @returns {Record<string, string | string[]>}
|
|
293
|
+
*/
|
|
294
|
+
function collectOutputFields(graph_node, field_definitions) {
|
|
295
|
+
/** @type {Record<string, string | string[]>} */
|
|
296
|
+
const fields = {};
|
|
297
|
+
|
|
298
|
+
for (const [field_name, field_value] of Object.entries(graph_node)) {
|
|
299
|
+
const normalized_value = getCollectedOutputFieldValue(
|
|
300
|
+
graph_node,
|
|
301
|
+
field_name,
|
|
302
|
+
field_value,
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
if (normalized_value === undefined) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
fields[field_name] = normalized_value;
|
|
190
310
|
}
|
|
191
311
|
|
|
192
|
-
|
|
312
|
+
for (const field_name of Object.keys(field_definitions)) {
|
|
313
|
+
if (fields[field_name] !== undefined) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const field_value = normalizeOutputFieldValue(graph_node[field_name]);
|
|
318
|
+
|
|
319
|
+
if (field_value !== undefined) {
|
|
320
|
+
fields[field_name] = field_value;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return fields;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @param {GraphNode} graph_node
|
|
329
|
+
* @param {string} field_name
|
|
330
|
+
* @param {unknown} field_value
|
|
331
|
+
* @returns {string | string[] | undefined}
|
|
332
|
+
*/
|
|
333
|
+
function getCollectedOutputFieldValue(graph_node, field_name, field_value) {
|
|
334
|
+
if (isInternalOutputField(field_name)) {
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const normalized_value = normalizeOutputFieldValue(field_value);
|
|
339
|
+
|
|
340
|
+
if (normalized_value === undefined) {
|
|
341
|
+
return undefined;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (isLegacyMirrorOutputField(graph_node, field_name, normalized_value)) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return normalized_value;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @param {GraphNode} graph_node
|
|
353
|
+
* @param {string} field_name
|
|
354
|
+
* @param {string | string[]} normalized_value
|
|
355
|
+
* @returns {boolean}
|
|
356
|
+
*/
|
|
357
|
+
function isLegacyMirrorOutputField(graph_node, field_name, normalized_value) {
|
|
358
|
+
if (Array.isArray(normalized_value)) {
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (field_name === 'kind') {
|
|
363
|
+
return normalized_value === graph_node.$class;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (field_name === 'path') {
|
|
367
|
+
return normalized_value === graph_node.$path;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (field_name === 'id') {
|
|
371
|
+
return normalized_value === graph_node.$id;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* @param {Record<string, string | string[]>} fields
|
|
379
|
+
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
380
|
+
* @returns {OutputMetadataField[]}
|
|
381
|
+
*/
|
|
382
|
+
function createVisibleOutputFields(fields, field_definitions) {
|
|
383
|
+
return Object.entries(fields)
|
|
384
|
+
.filter(
|
|
385
|
+
([field_name]) => field_definitions[field_name]?.display?.hidden !== true,
|
|
386
|
+
)
|
|
387
|
+
.sort(([left_name], [right_name]) =>
|
|
388
|
+
compareOutputFieldNames(left_name, right_name, field_definitions),
|
|
389
|
+
)
|
|
390
|
+
.map(([name, value]) => ({ name, value }));
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* @param {string} field_name
|
|
395
|
+
* @returns {boolean}
|
|
396
|
+
*/
|
|
397
|
+
function isInternalOutputField(field_name) {
|
|
398
|
+
return (
|
|
399
|
+
field_name === '$class' ||
|
|
400
|
+
field_name === '$id' ||
|
|
401
|
+
field_name === '$path' ||
|
|
402
|
+
field_name === 'id' ||
|
|
403
|
+
field_name === 'key' ||
|
|
404
|
+
field_name === 'label' ||
|
|
405
|
+
field_name === 'path' ||
|
|
406
|
+
field_name === 'title'
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* @param {string} left_name
|
|
412
|
+
* @param {string} right_name
|
|
413
|
+
* @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
|
|
414
|
+
* @returns {number}
|
|
415
|
+
*/
|
|
416
|
+
function compareOutputFieldNames(left_name, right_name, field_definitions) {
|
|
417
|
+
const left_order =
|
|
418
|
+
field_definitions[left_name]?.display?.order ?? Number.MAX_SAFE_INTEGER;
|
|
419
|
+
const right_order =
|
|
420
|
+
field_definitions[right_name]?.display?.order ?? Number.MAX_SAFE_INTEGER;
|
|
421
|
+
|
|
422
|
+
if (left_order !== right_order) {
|
|
423
|
+
return left_order - right_order;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return left_name.localeCompare(right_name, 'en');
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* @param {unknown} field_value
|
|
431
|
+
* @returns {string | string[] | undefined}
|
|
432
|
+
*/
|
|
433
|
+
function normalizeOutputFieldValue(field_value) {
|
|
434
|
+
if (Array.isArray(field_value)) {
|
|
435
|
+
const string_values = field_value.flatMap((value) =>
|
|
436
|
+
typeof value === 'string' ? [value] : [],
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
return string_values.length > 0 ? string_values : undefined;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return typeof field_value === 'string' ? field_value : undefined;
|
|
193
443
|
}
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
* @import { OutputNodeItem, OutputResolvedLinkItem, OutputStoredQueryItem, OutputView, QueryOutputView, ShowOutputView } from './output-view.types.ts';
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
formatOutputNodeMetadataRows,
|
|
7
|
+
formatResolvedLinkMetadataRows,
|
|
8
|
+
} from './format-output-metadata.js';
|
|
9
|
+
import { formatNodeHeader } from './format-node-header.js';
|
|
10
|
+
import { formatOutputItemBlock } from './format-output-item-block.js';
|
|
5
11
|
import { layoutStoredQueries } from './layout-stored-queries.js';
|
|
6
12
|
|
|
7
13
|
/**
|
|
@@ -76,12 +82,24 @@ function renderPlainStoredQueries(output_items) {
|
|
|
76
82
|
*/
|
|
77
83
|
function renderPlainShowOutput(output_view) {
|
|
78
84
|
const rendered_source = trimTrailingLineBreaks(output_view.rendered_source);
|
|
85
|
+
const document_summary = output_view.document
|
|
86
|
+
? formatPlainNodeItem(output_view.document)
|
|
87
|
+
: '';
|
|
79
88
|
|
|
80
|
-
if (output_view.items.length === 0) {
|
|
89
|
+
if (document_summary.length === 0 && output_view.items.length === 0) {
|
|
81
90
|
return `${rendered_source}\n`;
|
|
82
91
|
}
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
/** @type {string[]} */
|
|
94
|
+
const summary_items = [];
|
|
95
|
+
|
|
96
|
+
if (document_summary.length > 0) {
|
|
97
|
+
summary_items.push(document_summary);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
summary_items.push(...output_view.items.map(formatPlainResolvedLinkItem));
|
|
101
|
+
|
|
102
|
+
return `${rendered_source}\n\n----------------\n${summary_items.join('\n\n')}\n`;
|
|
85
103
|
}
|
|
86
104
|
|
|
87
105
|
/**
|
|
@@ -89,17 +107,11 @@ function renderPlainShowOutput(output_view) {
|
|
|
89
107
|
* @returns {string}
|
|
90
108
|
*/
|
|
91
109
|
function formatPlainNodeItem(output_item) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
lines.push(metadata_row);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
lines.push('', ` ${output_item.title}`);
|
|
101
|
-
|
|
102
|
-
return lines.join('\n');
|
|
110
|
+
return formatOutputItemBlock({
|
|
111
|
+
header: formatNodeHeader(output_item),
|
|
112
|
+
metadata_rows: formatOutputNodeMetadataRows(output_item),
|
|
113
|
+
title: output_item.title,
|
|
114
|
+
});
|
|
103
115
|
}
|
|
104
116
|
|
|
105
117
|
/**
|
|
@@ -115,79 +127,12 @@ function formatPlainStoredQueryLine(line_segments) {
|
|
|
115
127
|
* @returns {string}
|
|
116
128
|
*/
|
|
117
129
|
function formatPlainResolvedLinkItem(output_item) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (metadata_row.length > 0) {
|
|
125
|
-
lines.push(` ${metadata_row}`);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
lines.push('', ` ${output_item.target.title}`);
|
|
129
|
-
|
|
130
|
-
return lines.join('\n');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @param {OutputNodeItem} output_item
|
|
135
|
-
* @returns {string}
|
|
136
|
-
*/
|
|
137
|
-
function formatMetadataRow(output_item) {
|
|
138
|
-
/** @type {string[]} */
|
|
139
|
-
const metadata_fields = [];
|
|
140
|
-
|
|
141
|
-
if (isDocumentNode(output_item)) {
|
|
142
|
-
metadata_fields.push(`kind: ${output_item.node_kind}`);
|
|
143
|
-
} else {
|
|
144
|
-
metadata_fields.push(`path: ${output_item.path}`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (output_item.status) {
|
|
148
|
-
metadata_fields.push(`status: ${output_item.status}`);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return metadata_fields.join(' ');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @param {OutputNodeItem} output_item
|
|
156
|
-
* @returns {string}
|
|
157
|
-
*/
|
|
158
|
-
function formatNodeHeader(output_item) {
|
|
159
|
-
if (isDocumentNode(output_item)) {
|
|
160
|
-
return `document ${output_item.path}`;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return `${output_item.node_kind} ${output_item.id}`;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @param {OutputNodeItem} output_item
|
|
168
|
-
* @returns {boolean}
|
|
169
|
-
*/
|
|
170
|
-
function isDocumentNode(output_item) {
|
|
171
|
-
return output_item.id === `doc:${output_item.path}`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @param {{ kind?: string, status?: string }} target
|
|
176
|
-
* @returns {string}
|
|
177
|
-
*/
|
|
178
|
-
function formatResolvedLinkMetadataRow(target) {
|
|
179
|
-
/** @type {string[]} */
|
|
180
|
-
const metadata_fields = [];
|
|
181
|
-
|
|
182
|
-
if (target.kind) {
|
|
183
|
-
metadata_fields.push(`kind: ${target.kind}`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (target.status) {
|
|
187
|
-
metadata_fields.push(`status: ${target.status}`);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return metadata_fields.join(' ');
|
|
130
|
+
return formatOutputItemBlock({
|
|
131
|
+
header: `[${output_item.reference}] ${output_item.target.kind} ${output_item.target.path ?? output_item.target.id}`,
|
|
132
|
+
metadata_rows: formatResolvedLinkMetadataRows(output_item.target),
|
|
133
|
+
metadata_indent: ' ',
|
|
134
|
+
title: output_item.target.title,
|
|
135
|
+
});
|
|
191
136
|
}
|
|
192
137
|
|
|
193
138
|
/**
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
import { Ansis } from 'ansis';
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
formatOutputNodeMetadataRows,
|
|
10
|
+
formatResolvedLinkMetadataRows,
|
|
11
|
+
} from './format-output-metadata.js';
|
|
12
|
+
import { formatNodeHeader } from './format-node-header.js';
|
|
13
|
+
import { formatOutputItemBlock } from './format-output-item-block.js';
|
|
8
14
|
import { layoutStoredQueries } from './layout-stored-queries.js';
|
|
9
15
|
import { renderRichSource } from './render-rich-source.js';
|
|
10
16
|
|
|
@@ -96,12 +102,26 @@ async function renderRichShowOutput(output_view, render_options, ansi) {
|
|
|
96
102
|
const rendered_source = trimTrailingLineBreaks(
|
|
97
103
|
await renderRichSource(output_view, render_options),
|
|
98
104
|
);
|
|
105
|
+
const document_summary = output_view.document
|
|
106
|
+
? formatRichNodeItem(output_view.document, ansi)
|
|
107
|
+
: '';
|
|
99
108
|
|
|
100
|
-
if (output_view.items.length === 0) {
|
|
109
|
+
if (document_summary.length === 0 && output_view.items.length === 0) {
|
|
101
110
|
return `${rendered_source}\n`;
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
|
|
113
|
+
/** @type {string[]} */
|
|
114
|
+
const summary_items = [];
|
|
115
|
+
|
|
116
|
+
if (document_summary.length > 0) {
|
|
117
|
+
summary_items.push(document_summary);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
summary_items.push(
|
|
121
|
+
...output_view.items.map((item) => formatRichResolvedLinkItem(item, ansi)),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return `${rendered_source}\n\n${ansi.gray(FULL_WIDTH_DIVIDER)}\n\n${summary_items.join('\n\n')}\n`;
|
|
105
125
|
}
|
|
106
126
|
|
|
107
127
|
/**
|
|
@@ -110,17 +130,11 @@ async function renderRichShowOutput(output_view, render_options, ansi) {
|
|
|
110
130
|
* @returns {string}
|
|
111
131
|
*/
|
|
112
132
|
function formatRichNodeItem(output_item, ansi) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
lines.push(metadata_row);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
lines.push('', ` ${output_item.title}`);
|
|
122
|
-
|
|
123
|
-
return lines.join('\n');
|
|
133
|
+
return formatOutputItemBlock({
|
|
134
|
+
header: ansi.green(formatNodeHeader(output_item)),
|
|
135
|
+
metadata_rows: formatOutputNodeMetadataRows(output_item),
|
|
136
|
+
title: output_item.title,
|
|
137
|
+
});
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
/**
|
|
@@ -140,59 +154,12 @@ function formatRichStoredQueryLine(line_segments, ansi) {
|
|
|
140
154
|
* @returns {string}
|
|
141
155
|
*/
|
|
142
156
|
function formatRichResolvedLinkItem(output_item, ansi) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (metadata_row.length > 0) {
|
|
150
|
-
lines.push(` ${metadata_row}`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
lines.push('', ` ${output_item.target.title}`);
|
|
154
|
-
|
|
155
|
-
return lines.join('\n');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* @param {OutputNodeItem} output_item
|
|
160
|
-
* @returns {string}
|
|
161
|
-
*/
|
|
162
|
-
function formatRichMetadataRow(output_item) {
|
|
163
|
-
/** @type {string[]} */
|
|
164
|
-
const metadata_fields = [];
|
|
165
|
-
|
|
166
|
-
if (isDocumentNode(output_item)) {
|
|
167
|
-
metadata_fields.push(`kind: ${output_item.node_kind}`);
|
|
168
|
-
} else {
|
|
169
|
-
metadata_fields.push(`path: ${output_item.path}`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (output_item.status) {
|
|
173
|
-
metadata_fields.push(`status: ${output_item.status}`);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return metadata_fields.join(' ');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @param {{ kind?: string, status?: string }} target
|
|
181
|
-
* @returns {string}
|
|
182
|
-
*/
|
|
183
|
-
function formatRichResolvedLinkMetadataRow(target) {
|
|
184
|
-
/** @type {string[]} */
|
|
185
|
-
const metadata_fields = [];
|
|
186
|
-
|
|
187
|
-
if (target.kind) {
|
|
188
|
-
metadata_fields.push(`kind: ${target.kind}`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (target.status) {
|
|
192
|
-
metadata_fields.push(`status: ${target.status}`);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return metadata_fields.join(' ');
|
|
157
|
+
return formatOutputItemBlock({
|
|
158
|
+
header: `${ansi.gray(`[${output_item.reference}]`)} ${ansi.green(`${output_item.target.kind} ${output_item.target.path ?? output_item.target.id}`)}`,
|
|
159
|
+
metadata_rows: formatResolvedLinkMetadataRows(output_item.target),
|
|
160
|
+
metadata_indent: ' ',
|
|
161
|
+
title: output_item.target.title,
|
|
162
|
+
});
|
|
196
163
|
}
|
|
197
164
|
|
|
198
165
|
/**
|
|
@@ -218,32 +185,12 @@ function styleStoredQuerySegment(line_segment, ansi) {
|
|
|
218
185
|
}
|
|
219
186
|
|
|
220
187
|
if (line_segment.kind === 'keyword') {
|
|
221
|
-
return ansi.
|
|
188
|
+
return ansi.gray(line_segment.text);
|
|
222
189
|
}
|
|
223
190
|
|
|
224
191
|
return line_segment.text;
|
|
225
192
|
}
|
|
226
193
|
|
|
227
|
-
/**
|
|
228
|
-
* @param {OutputNodeItem} output_item
|
|
229
|
-
* @returns {string}
|
|
230
|
-
*/
|
|
231
|
-
function formatNodeHeader(output_item) {
|
|
232
|
-
if (isDocumentNode(output_item)) {
|
|
233
|
-
return `document ${output_item.path}`;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return `${output_item.node_kind} ${output_item.id}`;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @param {OutputNodeItem} output_item
|
|
241
|
-
* @returns {boolean}
|
|
242
|
-
*/
|
|
243
|
-
function isDocumentNode(output_item) {
|
|
244
|
-
return output_item.id === `doc:${output_item.path}`;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
194
|
/**
|
|
248
195
|
* @param {string} value
|
|
249
196
|
* @returns {string}
|