@likec4/language-server 1.14.0 → 1.15.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/contrib/likec4.tmLanguage.json +1 -1
- package/dist/browser.cjs +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.mts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.mjs +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/likec4lib.cjs +0 -1
- package/dist/likec4lib.mjs +0 -1
- package/dist/model-graph/index.cjs +1 -1
- package/dist/model-graph/index.mjs +1 -1
- package/dist/shared/{language-server.CbDa016p.cjs → language-server.80ITEDo5.cjs} +272 -64
- package/dist/shared/{language-server.CITj0XN3.cjs → language-server.BUtiWTKg.cjs} +188 -30
- package/dist/shared/{language-server.DFLaUdYu.mjs → language-server.DXC9g4_f.mjs} +274 -66
- package/dist/shared/{language-server.CO6aEDQm.d.mts → language-server.DfMwkd2l.d.mts} +46 -15
- package/dist/shared/{language-server.Cqyh6-9S.d.cts → language-server.U2piOAVt.d.cts} +46 -15
- package/dist/shared/{language-server.BI99piRy.d.ts → language-server.j-ShR6as.d.ts} +46 -15
- package/dist/shared/{language-server.DZYziEuF.mjs → language-server.zY53FGJE.mjs} +189 -31
- package/package.json +9 -9
- package/src/ast.ts +1 -0
- package/src/generated/ast.ts +103 -19
- package/src/generated/grammar.ts +1 -1
- package/src/generated-lib/icons.ts +0 -1
- package/src/like-c4.langium +32 -9
- package/src/lsp/CompletionProvider.ts +70 -2
- package/src/model/model-builder.ts +0 -1
- package/src/model/model-parser.ts +71 -20
- package/src/model-graph/compute-view/__test__/fixture.ts +45 -4
- package/src/model-graph/compute-view/compute.ts +223 -40
- package/src/model-graph/compute-view/predicates.ts +12 -6
- package/src/model-graph/utils/applyCustomElementProperties.ts +18 -4
- package/src/model-graph/utils/applyCustomRelationProperties.ts +2 -1
- package/src/model-graph/utils/applyViewRuleStyles.ts +30 -25
- package/src/model-graph/utils/buildComputeNodes.ts +69 -17
- package/src/model-graph/utils/elementExpressionToPredicate.ts +3 -1
- package/src/model-graph/utils/sortNodes.ts +11 -7
- package/src/references/scope-computation.ts +3 -2
- package/src/validation/index.ts +2 -2
- package/src/validation/specification.ts +4 -4
package/src/like-c4.langium
CHANGED
|
@@ -197,7 +197,7 @@ MetadataAttribute:
|
|
|
197
197
|
ModelViews:
|
|
198
198
|
name='views' '{' (
|
|
199
199
|
views+=LikeC4ViewRule |
|
|
200
|
-
styles+=
|
|
200
|
+
styles+=ViewRuleStyleOrGlobalRef
|
|
201
201
|
)*
|
|
202
202
|
'}';
|
|
203
203
|
|
|
@@ -267,15 +267,27 @@ ViewLayoutDirection returns string:
|
|
|
267
267
|
|
|
268
268
|
ViewRule:
|
|
269
269
|
ViewRulePredicate |
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
ViewRuleGroup |
|
|
271
|
+
ViewRuleStyleOrGlobalRef |
|
|
272
272
|
ViewRuleAutoLayout
|
|
273
273
|
;
|
|
274
274
|
|
|
275
|
+
ViewRuleGroup:
|
|
276
|
+
'group' title=String? '{'
|
|
277
|
+
props+=(
|
|
278
|
+
ColorProperty |
|
|
279
|
+
BorderProperty |
|
|
280
|
+
OpacityProperty
|
|
281
|
+
)*
|
|
282
|
+
groupRules+=(
|
|
283
|
+
ViewRulePredicate |
|
|
284
|
+
ViewRuleGroup
|
|
285
|
+
)*
|
|
286
|
+
'}';
|
|
287
|
+
|
|
275
288
|
DynamicViewRule:
|
|
276
289
|
DynamicViewIncludePredicate |
|
|
277
|
-
|
|
278
|
-
ViewRuleGlobalStyle |
|
|
290
|
+
ViewRuleStyleOrGlobalRef |
|
|
279
291
|
ViewRuleAutoLayout
|
|
280
292
|
;
|
|
281
293
|
|
|
@@ -444,7 +456,10 @@ ViewRuleStyle:
|
|
|
444
456
|
'}';
|
|
445
457
|
|
|
446
458
|
ViewRuleGlobalStyle:
|
|
447
|
-
'global' 'style' style=[
|
|
459
|
+
'global' 'style' style=[GlobalStyleId];
|
|
460
|
+
|
|
461
|
+
ViewRuleStyleOrGlobalRef:
|
|
462
|
+
ViewRuleStyle | ViewRuleGlobalStyle;
|
|
448
463
|
|
|
449
464
|
ViewRuleAutoLayout:
|
|
450
465
|
'autoLayout' direction=ViewLayoutDirection (
|
|
@@ -491,18 +506,26 @@ RelationNavigateToProperty:
|
|
|
491
506
|
Globals:
|
|
492
507
|
name='global' '{'
|
|
493
508
|
(
|
|
494
|
-
styles+=GlobalStyle*
|
|
509
|
+
styles+=(GlobalStyle | GlobalStyleGroup)*
|
|
495
510
|
)*
|
|
496
511
|
'}';
|
|
497
512
|
|
|
513
|
+
GlobalStyleId:
|
|
514
|
+
name=IdTerminal;
|
|
515
|
+
|
|
498
516
|
GlobalStyle:
|
|
499
|
-
'style'
|
|
517
|
+
'style' id=GlobalStyleId target=ElementExpressionsIterator '{'
|
|
500
518
|
props+=(
|
|
501
519
|
StyleProperty |
|
|
502
520
|
NotationProperty
|
|
503
521
|
)*
|
|
504
522
|
'}';
|
|
505
523
|
|
|
524
|
+
GlobalStyleGroup:
|
|
525
|
+
'styleGroup' id=GlobalStyleId '{'
|
|
526
|
+
styles+=ViewRuleStyle*
|
|
527
|
+
'}';
|
|
528
|
+
|
|
506
529
|
// Common properties -------------------------------------
|
|
507
530
|
|
|
508
531
|
LinkProperty:
|
|
@@ -593,7 +616,7 @@ CustomColorId returns string:
|
|
|
593
616
|
IdTerminal | ElementShape | ArrowType | LineOptions | 'element' | 'model';
|
|
594
617
|
|
|
595
618
|
Id returns string:
|
|
596
|
-
IdTerminal | ElementShape | ThemeColor | ArrowType | LineOptions | 'element' | 'model';
|
|
619
|
+
IdTerminal | ElementShape | ThemeColor | ArrowType | LineOptions | 'element' | 'model' | 'group';
|
|
597
620
|
|
|
598
621
|
fragment EqOperator:
|
|
599
622
|
(
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { type GrammarAST, type MaybePromise } from 'langium'
|
|
1
|
+
import { AstUtils, type GrammarAST, type MaybePromise } from 'langium'
|
|
2
2
|
import {
|
|
3
3
|
type CompletionAcceptor,
|
|
4
4
|
type CompletionContext,
|
|
5
5
|
type CompletionProviderOptions,
|
|
6
6
|
DefaultCompletionProvider
|
|
7
7
|
} from 'langium/lsp'
|
|
8
|
+
import { anyPass } from 'remeda'
|
|
8
9
|
import { CompletionItemKind, InsertTextFormat } from 'vscode-languageserver-types'
|
|
10
|
+
import { ast } from '../ast'
|
|
9
11
|
|
|
10
12
|
export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
11
13
|
override readonly completionOptions = {
|
|
@@ -20,7 +22,15 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
20
22
|
if (!this.filterKeyword(context, keyword)) {
|
|
21
23
|
return
|
|
22
24
|
}
|
|
23
|
-
if (['
|
|
25
|
+
if (['title', 'description', 'technology'].includes(keyword.value)) {
|
|
26
|
+
return acceptor(context, {
|
|
27
|
+
label: keyword.value,
|
|
28
|
+
kind: CompletionItemKind.Property,
|
|
29
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
30
|
+
insertText: `${keyword.value} '\${0}'`
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
if (['views', 'specification', 'model', 'with'].includes(keyword.value)) {
|
|
24
34
|
return acceptor(context, {
|
|
25
35
|
label: keyword.value,
|
|
26
36
|
detail: `Insert ${keyword.value} block`,
|
|
@@ -29,6 +39,19 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
29
39
|
insertText: `${keyword.value} {\n\t$0\n}`
|
|
30
40
|
})
|
|
31
41
|
}
|
|
42
|
+
if (keyword.value === 'group') {
|
|
43
|
+
return acceptor(context, {
|
|
44
|
+
label: keyword.value,
|
|
45
|
+
detail: `Insert group block`,
|
|
46
|
+
kind: CompletionItemKind.Class,
|
|
47
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
48
|
+
insertText: [
|
|
49
|
+
'group \'${1:Title}\' {',
|
|
50
|
+
'\t$0',
|
|
51
|
+
'}'
|
|
52
|
+
].join('\n')
|
|
53
|
+
})
|
|
54
|
+
}
|
|
32
55
|
if (keyword.value === 'dynamic') {
|
|
33
56
|
return acceptor(context, {
|
|
34
57
|
label: keyword.value,
|
|
@@ -44,6 +67,51 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
|
|
|
44
67
|
].join('\n')
|
|
45
68
|
})
|
|
46
69
|
}
|
|
70
|
+
if (keyword.value === 'style' && context.node) {
|
|
71
|
+
if (AstUtils.hasContainerOfType(context.node, ast.isGlobalStyle)) {
|
|
72
|
+
return acceptor(context, {
|
|
73
|
+
label: keyword.value,
|
|
74
|
+
detail: `Insert ${keyword.value} block`,
|
|
75
|
+
kind: CompletionItemKind.Module,
|
|
76
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
77
|
+
insertText: `${keyword.value} \${1:name} \${2:*} {\n\t\${3|color,shape,border,opacity,icon|} \$0\n}`
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
if (AstUtils.hasContainerOfType(context.node, anyPass([ast.isModelViews, ast.isGlobalStyleGroup]))) {
|
|
81
|
+
return acceptor(context, {
|
|
82
|
+
label: keyword.value,
|
|
83
|
+
detail: `Insert ${keyword.value} block`,
|
|
84
|
+
kind: CompletionItemKind.Module,
|
|
85
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
86
|
+
insertText: `${keyword.value} \${1:*} {\n\t\${2|color,shape,border,opacity,icon|} \$0\n}`
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
return acceptor(context, {
|
|
90
|
+
label: keyword.value,
|
|
91
|
+
detail: `Insert ${keyword.value} block`,
|
|
92
|
+
kind: CompletionItemKind.Module,
|
|
93
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
94
|
+
insertText: `${keyword.value} {\n\t\${1|color,shape,border,opacity,icon|} \$0\n}`
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
if (keyword.value === 'extend') {
|
|
98
|
+
return acceptor(context, {
|
|
99
|
+
label: keyword.value,
|
|
100
|
+
detail: `Extend another view`,
|
|
101
|
+
kind: CompletionItemKind.Class,
|
|
102
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
103
|
+
insertText: 'extend ${1:element} {\n\t$0\n}'
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (keyword.value === 'autoLayout') {
|
|
108
|
+
return acceptor(context, {
|
|
109
|
+
label: keyword.value,
|
|
110
|
+
kind: CompletionItemKind.Class,
|
|
111
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
112
|
+
insertText: 'autoLayout ${1|TopBottom,BottomTop,LeftRight,RightLeft|}$0'
|
|
113
|
+
})
|
|
114
|
+
}
|
|
47
115
|
acceptor(context, {
|
|
48
116
|
label: keyword.value,
|
|
49
117
|
kind: this.getKeywordCompletionItemKind(keyword),
|
|
@@ -46,7 +46,6 @@ import { isParsedLikeC4LangiumDocument } from '../ast'
|
|
|
46
46
|
import { logError, logger, logWarnError } from '../logger'
|
|
47
47
|
import { computeDynamicView, computeView, LikeC4ModelGraph } from '../model-graph'
|
|
48
48
|
import type { LikeC4Services } from '../module'
|
|
49
|
-
import { printDocs } from '../utils/printDocs'
|
|
50
49
|
import { assignNavigateTo, resolveGlobalRules, resolveRelativePaths, resolveRulesExtendedViews } from '../view-utils'
|
|
51
50
|
|
|
52
51
|
function buildModel(services: LikeC4Services, docs: ParsedLikeC4LangiumDocument[]): c4.ParsedLikeC4Model {
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
ViewOps
|
|
31
31
|
} from '../ast'
|
|
32
32
|
import { elementRef, getFqnElementRef } from '../elementRef'
|
|
33
|
-
import { type NotationProperty } from '../generated/ast'
|
|
33
|
+
import { isGlobalStyle, isGlobalStyleGroup, type NotationProperty } from '../generated/ast'
|
|
34
34
|
import { logError, logger, logWarnError } from '../logger'
|
|
35
35
|
import type { LikeC4Services } from '../module'
|
|
36
36
|
import { stringHash } from '../utils'
|
|
@@ -291,7 +291,7 @@ export class LikeC4ModelParser {
|
|
|
291
291
|
const styles = globals.flatMap(r => r.styles.filter(isValid))
|
|
292
292
|
for (const style of styles) {
|
|
293
293
|
try {
|
|
294
|
-
const globalStyleId = style.name as c4.GlobalStyleID
|
|
294
|
+
const globalStyleId = style.id.name as c4.GlobalStyleID
|
|
295
295
|
if (!isTruthy(globalStyleId)) {
|
|
296
296
|
continue
|
|
297
297
|
}
|
|
@@ -299,15 +299,30 @@ export class LikeC4ModelParser {
|
|
|
299
299
|
logger.warn(`Global style named "${globalStyleId}" is already defined`)
|
|
300
300
|
continue
|
|
301
301
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
302
|
+
|
|
303
|
+
const styles = this.parseGlobalStyleOrGroup(style, isValid)
|
|
304
|
+
if (styles.length > 0) {
|
|
305
|
+
c4Globals.styles[globalStyleId] = styles as c4.NonEmptyArray<c4.ViewRuleStyle>
|
|
306
|
+
}
|
|
305
307
|
} catch (e) {
|
|
306
308
|
logWarnError(e)
|
|
307
309
|
}
|
|
308
310
|
}
|
|
309
311
|
}
|
|
310
312
|
|
|
313
|
+
private parseGlobalStyleOrGroup(
|
|
314
|
+
astRule: ast.GlobalStyle | ast.GlobalStyleGroup,
|
|
315
|
+
isValid: IsValidFn
|
|
316
|
+
): c4.ViewRuleStyle[] {
|
|
317
|
+
if (ast.isGlobalStyle(astRule)) {
|
|
318
|
+
return [this.parseGlobalStyle(astRule, isValid)]
|
|
319
|
+
}
|
|
320
|
+
if (ast.isGlobalStyleGroup(astRule)) {
|
|
321
|
+
return astRule.styles.map(s => this.parseViewRuleStyle(s, isValid))
|
|
322
|
+
}
|
|
323
|
+
nonexhaustive(astRule)
|
|
324
|
+
}
|
|
325
|
+
|
|
311
326
|
private parseGlobalStyle(astRule: ast.GlobalStyle, isValid: IsValidFn): c4.ViewRuleStyle {
|
|
312
327
|
const styleProps = astRule.props.filter(ast.isStyleProperty)
|
|
313
328
|
const targets = astRule.target
|
|
@@ -319,7 +334,7 @@ export class LikeC4ModelParser {
|
|
|
319
334
|
const viewBlocks = doc.parseResult.value.views.filter(v => isValid(v))
|
|
320
335
|
for (const viewBlock of viewBlocks) {
|
|
321
336
|
const localStyles = viewBlock.styles
|
|
322
|
-
.flatMap(s => this.
|
|
337
|
+
.flatMap(s => this.parseViewRuleStyleOrGlobalRef(s, isValid))
|
|
323
338
|
const stylesToApply = localStyles
|
|
324
339
|
|
|
325
340
|
for (const view of viewBlock.views) {
|
|
@@ -530,8 +545,11 @@ export class LikeC4ModelParser {
|
|
|
530
545
|
|
|
531
546
|
private parseRelationPredicate(astNode: ast.RelationPredicate, _isValid: IsValidFn): c4.RelationPredicateExpression {
|
|
532
547
|
if (ast.isRelationPredicateWith(astNode)) {
|
|
533
|
-
|
|
534
|
-
|
|
548
|
+
let relation = ast.isRelationPredicateWhere(astNode.subject)
|
|
549
|
+
? this.parseRelationPredicateWhere(astNode.subject)
|
|
550
|
+
: this.parseRelationExpr(astNode.subject)
|
|
551
|
+
|
|
552
|
+
return this.parseRelationPredicateWith(astNode, relation)
|
|
535
553
|
}
|
|
536
554
|
if (ast.isRelationPredicateWhere(astNode)) {
|
|
537
555
|
return this.parseRelationPredicateWhere(astNode)
|
|
@@ -558,9 +576,8 @@ export class LikeC4ModelParser {
|
|
|
558
576
|
|
|
559
577
|
private parseRelationPredicateWith(
|
|
560
578
|
astNode: ast.RelationPredicateWith,
|
|
561
|
-
|
|
579
|
+
relation: c4.RelationExpression | c4.RelationWhereExpr
|
|
562
580
|
): c4.CustomRelationExpr {
|
|
563
|
-
const relation = this.parseRelationExpr(subject)
|
|
564
581
|
const props = astNode.custom?.props ?? []
|
|
565
582
|
return props.reduce(
|
|
566
583
|
(acc, prop) => {
|
|
@@ -636,12 +653,22 @@ export class LikeC4ModelParser {
|
|
|
636
653
|
if (ast.isViewRulePredicate(astRule)) {
|
|
637
654
|
return this.parseViewRulePredicate(astRule, isValid)
|
|
638
655
|
}
|
|
639
|
-
if (ast.
|
|
640
|
-
return this.
|
|
656
|
+
if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
|
|
657
|
+
return this.parseViewRuleStyleOrGlobalRef(astRule, isValid)
|
|
641
658
|
}
|
|
642
659
|
if (ast.isViewRuleAutoLayout(astRule)) {
|
|
643
660
|
return toAutoLayout(astRule)
|
|
644
661
|
}
|
|
662
|
+
if (ast.isViewRuleGroup(astRule)) {
|
|
663
|
+
return this.parseViewRuleGroup(astRule, isValid)
|
|
664
|
+
}
|
|
665
|
+
nonexhaustive(astRule)
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
private parseViewRuleStyleOrGlobalRef(astRule: ast.ViewRuleStyleOrGlobalRef, isValid: IsValidFn): c4.ViewRuleStyleOrGlobalRef {
|
|
669
|
+
if (ast.isViewRuleStyle(astRule)) {
|
|
670
|
+
return this.parseViewRuleStyle(astRule, isValid)
|
|
671
|
+
}
|
|
645
672
|
if (ast.isViewRuleGlobalStyle(astRule)) {
|
|
646
673
|
return this.parseViewRuleGlobalStyle(astRule, isValid)
|
|
647
674
|
}
|
|
@@ -655,6 +682,33 @@ export class LikeC4ModelParser {
|
|
|
655
682
|
return this.parseRuleStyle(styleProps, targets, isValid, notation)
|
|
656
683
|
}
|
|
657
684
|
|
|
685
|
+
private parseViewRuleGroup(astNode: ast.ViewRuleGroup, _isValid: IsValidFn): c4.ViewRuleGroup {
|
|
686
|
+
const groupRules = [] as c4.ViewRuleGroup['groupRules']
|
|
687
|
+
for (const rule of astNode.groupRules) {
|
|
688
|
+
try {
|
|
689
|
+
if (!_isValid(rule)) {
|
|
690
|
+
continue
|
|
691
|
+
}
|
|
692
|
+
if (ast.isViewRulePredicate(rule)) {
|
|
693
|
+
groupRules.push(this.parseViewRulePredicate(rule, _isValid))
|
|
694
|
+
continue
|
|
695
|
+
}
|
|
696
|
+
if (ast.isViewRuleGroup(rule)) {
|
|
697
|
+
groupRules.push(this.parseViewRuleGroup(rule, _isValid))
|
|
698
|
+
continue
|
|
699
|
+
}
|
|
700
|
+
nonexhaustive(rule)
|
|
701
|
+
} catch (e) {
|
|
702
|
+
logWarnError(e)
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
title: toSingleLine(astNode.title) ?? null,
|
|
707
|
+
groupRules,
|
|
708
|
+
...toElementStyle(astNode.props, _isValid)
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
658
712
|
private parseRuleStyle(
|
|
659
713
|
styleProperties: ast.StyleProperty[],
|
|
660
714
|
elementExpressionsIterator: ast.ElementExpressionsIterator,
|
|
@@ -673,7 +727,7 @@ export class LikeC4ModelParser {
|
|
|
673
727
|
}
|
|
674
728
|
}
|
|
675
729
|
|
|
676
|
-
private parseViewRuleGlobalStyle(astRule: ast.ViewRuleGlobalStyle,
|
|
730
|
+
private parseViewRuleGlobalStyle(astRule: ast.ViewRuleGlobalStyle, _isValid: IsValidFn): c4.ViewRuleGlobalStyle {
|
|
677
731
|
return {
|
|
678
732
|
styleId: astRule.style.$refText as c4.GlobalStyleID
|
|
679
733
|
}
|
|
@@ -777,7 +831,7 @@ export class LikeC4ModelParser {
|
|
|
777
831
|
|
|
778
832
|
private parseElementView(
|
|
779
833
|
astNode: ast.ElementView,
|
|
780
|
-
additionalStyles: c4.
|
|
834
|
+
additionalStyles: c4.ViewRuleStyleOrGlobalRef[],
|
|
781
835
|
isValid: IsValidFn
|
|
782
836
|
): ParsedAstElementView {
|
|
783
837
|
const body = astNode.body
|
|
@@ -849,7 +903,7 @@ export class LikeC4ModelParser {
|
|
|
849
903
|
|
|
850
904
|
private parseDynamicElementView(
|
|
851
905
|
astNode: ast.DynamicView,
|
|
852
|
-
additionalStyles: c4.
|
|
906
|
+
additionalStyles: c4.ViewRuleStyleOrGlobalRef[],
|
|
853
907
|
isValid: IsValidFn
|
|
854
908
|
): ParsedAstDynamicView {
|
|
855
909
|
const body = astNode.body
|
|
@@ -917,15 +971,12 @@ export class LikeC4ModelParser {
|
|
|
917
971
|
if (ast.isDynamicViewIncludePredicate(astRule)) {
|
|
918
972
|
return this.parseDynamicViewIncludePredicate(astRule, isValid)
|
|
919
973
|
}
|
|
920
|
-
if (ast.
|
|
921
|
-
return this.
|
|
974
|
+
if (ast.isViewRuleStyleOrGlobalRef(astRule)) {
|
|
975
|
+
return this.parseViewRuleStyleOrGlobalRef(astRule, isValid)
|
|
922
976
|
}
|
|
923
977
|
if (ast.isViewRuleAutoLayout(astRule)) {
|
|
924
978
|
return toAutoLayout(astRule)
|
|
925
979
|
}
|
|
926
|
-
if (ast.isViewRuleGlobalStyle(astRule)) {
|
|
927
|
-
return this.parseViewRuleGlobalStyle(astRule, isValid)
|
|
928
|
-
}
|
|
929
980
|
nonexhaustive(astRule)
|
|
930
981
|
}
|
|
931
982
|
|
|
@@ -11,6 +11,10 @@ import {
|
|
|
11
11
|
type ElementWhereExpr,
|
|
12
12
|
type Expression as C4Expression,
|
|
13
13
|
type Fqn,
|
|
14
|
+
isElementRef,
|
|
15
|
+
isElementWhere,
|
|
16
|
+
isRelationExpression,
|
|
17
|
+
isRelationWhere,
|
|
14
18
|
type NonEmptyArray,
|
|
15
19
|
type Relation,
|
|
16
20
|
type RelationID,
|
|
@@ -20,6 +24,7 @@ import {
|
|
|
20
24
|
type Tag,
|
|
21
25
|
type ViewID,
|
|
22
26
|
type ViewRule,
|
|
27
|
+
type ViewRuleGroup,
|
|
23
28
|
type ViewRulePredicate,
|
|
24
29
|
type ViewRuleStyle,
|
|
25
30
|
type WhereOperator
|
|
@@ -362,8 +367,6 @@ export type Expression =
|
|
|
362
367
|
| IncomingExpr
|
|
363
368
|
| OutgoingExpr
|
|
364
369
|
| RelationExpr
|
|
365
|
-
| ElementWhereExpr
|
|
366
|
-
| RelationWhereExpr
|
|
367
370
|
|
|
368
371
|
export function $custom(
|
|
369
372
|
expr: ElementRefExpr,
|
|
@@ -465,9 +468,41 @@ export function $expr(expr: Expression | C4Expression): C4Expression {
|
|
|
465
468
|
}
|
|
466
469
|
}
|
|
467
470
|
|
|
468
|
-
|
|
471
|
+
type CustomProps = {
|
|
472
|
+
where?: WhereOperator<TestTag, string>
|
|
473
|
+
with?: {
|
|
474
|
+
title?: string
|
|
475
|
+
description?: string
|
|
476
|
+
technology?: string
|
|
477
|
+
shape?: ElementShape
|
|
478
|
+
color?: Color
|
|
479
|
+
border?: BorderStyle
|
|
480
|
+
icon?: string
|
|
481
|
+
opacity?: number
|
|
482
|
+
navigateTo?: string
|
|
483
|
+
} & Omit<C4CustomRelationExpr['customRelation'], 'relation' | 'navigateTo'>
|
|
484
|
+
}
|
|
485
|
+
export function $include(expr: Expression | C4Expression, props?: CustomProps): ViewRulePredicate {
|
|
486
|
+
let _expr = props?.where ? $where(expr, props.where) : $expr(expr)
|
|
487
|
+
if (props?.with) {
|
|
488
|
+
if (isRelationExpression(_expr) || isRelationWhere(_expr)) {
|
|
489
|
+
_expr = {
|
|
490
|
+
customRelation: {
|
|
491
|
+
relation: _expr,
|
|
492
|
+
...props.with as any
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
} else if (isElementRef(_expr) || isElementWhere(_expr)) {
|
|
496
|
+
_expr = {
|
|
497
|
+
custom: {
|
|
498
|
+
expr: _expr,
|
|
499
|
+
...props.with as any
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
469
504
|
return {
|
|
470
|
-
include: [
|
|
505
|
+
include: [_expr]
|
|
471
506
|
}
|
|
472
507
|
}
|
|
473
508
|
export function $exclude(expr: Expression | C4Expression): ViewRulePredicate {
|
|
@@ -475,6 +510,12 @@ export function $exclude(expr: Expression | C4Expression): ViewRulePredicate {
|
|
|
475
510
|
exclude: [$expr(expr)]
|
|
476
511
|
}
|
|
477
512
|
}
|
|
513
|
+
export function $group(groupRules: ViewRuleGroup['groupRules']): ViewRuleGroup {
|
|
514
|
+
return {
|
|
515
|
+
title: null,
|
|
516
|
+
groupRules
|
|
517
|
+
}
|
|
518
|
+
}
|
|
478
519
|
|
|
479
520
|
export function $style(element: ElementRefExpr, style: ViewRuleStyle['style']): ViewRuleStyle {
|
|
480
521
|
return {
|