@likec4/generators 0.37.1 → 0.41.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/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@likec4/generators",
3
- "version": "0.37.1",
3
+ "version": "0.41.0",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
7
7
  "author": "Denis Davydkov <denis@davydkov.com>",
8
8
  "files": [
9
- "dist",
10
- "!dist/__mocks__/**",
9
+ "src",
10
+ "!**/__mocks__/**",
11
11
  "!**/*.spec.*",
12
12
  "!**/*.map"
13
13
  ],
@@ -16,37 +16,36 @@
16
16
  "url": "https://github.com/likec4/likec4.git",
17
17
  "directory": "packages/generators"
18
18
  },
19
- "main": "./dist/index.js",
20
- "module": "./dist/index.js",
21
- "types": "./dist/index.d.ts",
22
19
  "type": "module",
23
20
  "sideEffects": false,
21
+ "exports": {
22
+ ".": "./src/index.ts"
23
+ },
24
24
  "publishConfig": {
25
25
  "registry": "https://registry.npmjs.org",
26
- "access": "public",
27
- "main": "./dist/index.js",
28
- "module": "./dist/index.js",
29
- "types": "./dist/index.d.ts"
26
+ "access": "public"
30
27
  },
31
28
  "scripts": {
32
- "compile": "tsc --noEmit",
33
- "build": "tsc",
34
- "dev": "tsc --watch",
29
+ "typecheck": "tsc --noEmit",
30
+ "build": "unbuild",
35
31
  "lint": "run -T eslint src/ --fix",
36
32
  "clean": "run -T rimraf dist",
37
- "test": "run -T vitest run",
38
- "test:watch": "run -T vitest"
33
+ "test": "run -T vitest run"
39
34
  },
40
35
  "dependencies": {
41
- "@likec4/core": "0.37.1",
36
+ "@likec4/core": "0.41.0",
42
37
  "json5": "^2.2.3",
43
38
  "langium": "^2.0.2",
44
39
  "rambdax": "^9.1.1"
45
40
  },
46
41
  "devDependencies": {
47
- "@types/node": "^18.15.11",
42
+ "@types/node": "^20.8.7",
48
43
  "typescript": "^5.2.2",
49
- "vitest": "^0.34.4"
44
+ "unbuild": "^2.0.0",
45
+ "vitest": "^0.34.6"
50
46
  },
51
- "packageManager": "yarn@3.6.3"
47
+ "packageManager": "yarn@3.6.4",
48
+ "volta": {
49
+ "extends": "../../package.json"
50
+ }
52
51
  }
@@ -0,0 +1,107 @@
1
+ import type { ComputedEdge, ComputedNode, ComputedView, NodeId } from '@likec4/core'
2
+ import { CompositeGeneratorNode, NL, joinToNode, toString } from 'langium'
3
+ import { isNil } from 'rambdax'
4
+
5
+ const capitalizeFirstLetter = (value: string) =>
6
+ value.charAt(0).toLocaleUpperCase() + value.slice(1)
7
+
8
+ const fqnName = (nodeId: string): string => nodeId.split('.').map(capitalizeFirstLetter).join('')
9
+
10
+ const nodeName = (node: ComputedNode): string => {
11
+ return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id)
12
+ }
13
+
14
+ const d2direction = ({ autoLayout }: ComputedView) => {
15
+ switch (autoLayout) {
16
+ case 'TB': {
17
+ return 'down'
18
+ }
19
+ case 'BT': {
20
+ return 'up'
21
+ }
22
+ case 'LR': {
23
+ return 'right'
24
+ }
25
+ case 'RL': {
26
+ return 'left'
27
+ }
28
+ }
29
+ }
30
+
31
+ const d2shape = ({ shape }: ComputedNode) => {
32
+ switch (shape) {
33
+ case 'queue':
34
+ case 'cylinder':
35
+ case 'rectangle':
36
+ case 'person': {
37
+ return shape
38
+ }
39
+ case 'storage': {
40
+ return 'stored_data' as const
41
+ }
42
+ case 'mobile':
43
+ case 'browser': {
44
+ return 'rectangle' as const
45
+ }
46
+ }
47
+ }
48
+
49
+ export function generateD2<V extends ComputedView>(view: V) {
50
+ const { nodes, edges } = view
51
+ const names = new Map<NodeId, string>()
52
+
53
+ const printNode = (node: ComputedNode, parentName?: string): CompositeGeneratorNode => {
54
+ const name = nodeName(node)
55
+ const fqnName = (parentName ? parentName + '.' : '') + name
56
+ names.set(node.id, fqnName)
57
+
58
+ const label = node.title.replaceAll('\n', '\\n')
59
+ const shape = d2shape(node)
60
+
61
+ return new CompositeGeneratorNode()
62
+ .append(name, ': {', NL)
63
+ .indent({
64
+ indentedChildren: indent =>
65
+ indent
66
+ .append('label: "', label, '"', NL)
67
+ .appendIf(shape !== 'rectangle', 'shape: ', shape, NL)
68
+ .appendIf(
69
+ node.children.length > 0,
70
+ NL,
71
+ joinToNode(
72
+ nodes.filter(n => n.parent === node.id),
73
+ n => printNode(n, fqnName)
74
+ )
75
+ ),
76
+ indentation: 2
77
+ })
78
+ .append('}', NL)
79
+ }
80
+ // return `${names.get(edge.source)} -> ${names.get(edge.target)}${edge.label ? ': ' + edge.label : ''}`
81
+ const printEdge = (edge: ComputedEdge): CompositeGeneratorNode => {
82
+ return new CompositeGeneratorNode()
83
+ .append(names.get(edge.source), ' -> ', names.get(edge.target))
84
+ .append(out => edge.label && out.append(': ', edge.label.replaceAll('\n', '\\n')))
85
+ }
86
+
87
+ return toString(
88
+ new CompositeGeneratorNode()
89
+ .append('direction: ', d2direction(view), NL, NL)
90
+ .append(
91
+ joinToNode(
92
+ nodes.filter(n => isNil(n.parent)),
93
+ n => printNode(n),
94
+ {
95
+ appendNewLineIfNotEmpty: true
96
+ }
97
+ )
98
+ )
99
+ .appendIf(
100
+ edges.length > 0,
101
+ NL,
102
+ joinToNode(edges, e => printEdge(e), {
103
+ appendNewLineIfNotEmpty: true
104
+ })
105
+ )
106
+ )
107
+ }
@@ -0,0 +1 @@
1
+ export * from './generate-d2'
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { generateReact } from './react/generate-react'
2
+ export { generateD2 } from './d2/generate-d2'
3
+ export { generateMermaid } from './mmd/generate-mmd'
4
+ export { generateViewsDataTs, generateViewsDataJs } from './views-data-ts/generate-views-data'
@@ -0,0 +1,106 @@
1
+ import type { ComputedEdge, ComputedNode, ComputedView, NodeId } from '@likec4/core'
2
+ import { CompositeGeneratorNode, NL, joinToNode, toString } from 'langium'
3
+ import { isNil } from 'rambdax'
4
+
5
+ const capitalizeFirstLetter = (value: string) =>
6
+ value.charAt(0).toLocaleUpperCase() + value.slice(1)
7
+
8
+ const fqnName = (nodeId: string): string => nodeId.split('.').map(capitalizeFirstLetter).join('')
9
+
10
+ const nodeName = (node: ComputedNode): string => {
11
+ return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id)
12
+ }
13
+
14
+ const mmdshape = ({ shape }: ComputedNode): [start: string, end: string] => {
15
+ switch (shape) {
16
+ case 'queue':
17
+ case 'cylinder':
18
+ return ['[(', ')]']
19
+ case 'person': {
20
+ return ['[fa:fa-user ', ']']
21
+ }
22
+ case 'storage':
23
+ return ['([', '])']
24
+ case 'mobile':
25
+ case 'browser':
26
+ case 'rectangle': {
27
+ return ['[', ']']
28
+ }
29
+ }
30
+ }
31
+
32
+ export function generateMermaid<V extends ComputedView>(view: V) {
33
+ const { nodes, edges } = view
34
+ const names = new Map<NodeId, string>()
35
+
36
+ const printNode = (node: ComputedNode, parentName?: string): CompositeGeneratorNode => {
37
+ const name = nodeName(node)
38
+ const fqnName = (parentName ? parentName + '.' : '') + name
39
+ names.set(node.id, fqnName)
40
+
41
+ const label = node.title.replaceAll('\n', '\\n')
42
+ const shape = mmdshape(node)
43
+
44
+ const baseNode = new CompositeGeneratorNode()
45
+ if (node.children.length > 0) {
46
+ baseNode
47
+ .append('subgraph ', fqnName, '["', label, '"]', NL)
48
+ .indent({
49
+ indentedChildren: indent =>
50
+ indent.appendIf(
51
+ node.children.length > 0,
52
+ NL,
53
+ joinToNode(
54
+ nodes.filter(n => n.parent === node.id),
55
+ n => printNode(n, fqnName)
56
+ )
57
+ ),
58
+ indentation: 2
59
+ })
60
+ .append('end', NL)
61
+ } else {
62
+ baseNode.append(fqnName, shape[0], label, shape[1], NL)
63
+ }
64
+ return baseNode
65
+ }
66
+ // return `${names.get(edge.source)} -> ${names.get(edge.target)}${edge.label ? ': ' + edge.label : ''}`
67
+ const printEdge = (edge: ComputedEdge): CompositeGeneratorNode => {
68
+ return new CompositeGeneratorNode().append(
69
+ names.get(edge.source),
70
+ ' --',
71
+ edge.label ? '"' + edge.label.replaceAll('\n', '\\n') + '"--' : '',
72
+ '> ',
73
+ names.get(edge.target)
74
+ )
75
+ }
76
+
77
+ return toString(
78
+ new CompositeGeneratorNode()
79
+ .appendIf(
80
+ view.title !== null && view.title.length > 0,
81
+ '---',
82
+ NL,
83
+ `title: ${view.title}`,
84
+ NL,
85
+ '---',
86
+ NL
87
+ )
88
+ .append('graph ', view.autoLayout, NL, NL)
89
+ .append(
90
+ joinToNode(
91
+ nodes.filter(n => isNil(n.parent)),
92
+ n => printNode(n),
93
+ {
94
+ appendNewLineIfNotEmpty: true
95
+ }
96
+ )
97
+ )
98
+ .appendIf(
99
+ edges.length > 0,
100
+ NL,
101
+ joinToNode(edges, e => printEdge(e), {
102
+ appendNewLineIfNotEmpty: true
103
+ })
104
+ )
105
+ )
106
+ }
@@ -0,0 +1 @@
1
+ export * from './generate-mmd'
@@ -0,0 +1,111 @@
1
+ import type { DiagramView } from '@likec4/core'
2
+ import JSON5 from 'json5'
3
+ import { CompositeGeneratorNode, NL, expandToNode, joinToNode, toString } from 'langium'
4
+
5
+ const componentName = (value: string): string => {
6
+ if (!value.charAt(0).match(/[a-zA-Z]/)) {
7
+ value = 'View' + value
8
+ }
9
+ value = value.replaceAll('_', '')
10
+ return value.charAt(0).toLocaleUpperCase() + value.slice(1)
11
+ }
12
+
13
+ export const generateViewId = (views: DiagramView[]) =>
14
+ joinToNode(views, view => expandToNode`'${view.id}'`, {
15
+ separator: ' | '
16
+ })
17
+
18
+ export function generateReact(views: DiagramView[]) {
19
+ const components = views.map(({ id }) => {
20
+ return {
21
+ id,
22
+ name: componentName(id)
23
+ }
24
+ })
25
+
26
+ const out = new CompositeGeneratorNode()
27
+ out.appendTemplate`
28
+ /******************************************************************************
29
+ * This file was generated
30
+ * DO NOT EDIT MANUALLY!
31
+ ******************************************************************************/
32
+ /* eslint-disable */
33
+
34
+ import type { DiagramView } from '@likec4/diagrams'
35
+ import { LikeC4 } from '@likec4/diagrams'
36
+ `.append(NL, NL)
37
+
38
+ if (components.length == 0) {
39
+ out.append('export {}', NL)
40
+ return toString(out)
41
+ }
42
+
43
+ out.appendTemplate`
44
+ export type LikeC4ViewId = ${generateViewId(views)};
45
+ export const LikeC4Views = {
46
+ `
47
+ .indent({
48
+ indentation: 2,
49
+ indentedChildren(indented) {
50
+ indented.appendNewLineIf(views.length > 1).append(
51
+ joinToNode(
52
+ views,
53
+ view =>
54
+ expandToNode`${JSON5.stringify(view.id)}: (${JSON5.stringify(
55
+ view
56
+ )} as unknown) as DiagramView`,
57
+ {
58
+ separator: ',',
59
+ appendNewLineIfNotEmpty: true
60
+ }
61
+ )
62
+ )
63
+ }
64
+ })
65
+ .append('} as const satisfies Record<LikeC4ViewId, DiagramView>', NL, NL).appendTemplate`
66
+ export type LikeC4Views = typeof LikeC4Views
67
+
68
+ export const {
69
+ // guard
70
+ isViewId,
71
+ // React hook to use location hash for ViewId
72
+ useViewId,
73
+ // React component to display diagram
74
+ Diagram,
75
+ // React component to display diagram in responsive container
76
+ Responsive,
77
+ // React component to display diagram in fullscreen container
78
+ Fullscreen,
79
+ // React component to embed diagram and open browser on click
80
+ Embedded,
81
+ // React component to browse diagrams in fullscreen container
82
+ Browser,
83
+ } = LikeC4.create<LikeC4ViewId>(LikeC4Views)
84
+
85
+ export type DiagramProps = LikeC4.DiagramProps<LikeC4ViewId>
86
+ export type ResponsiveProps = LikeC4.ResponsiveProps<LikeC4ViewId>
87
+ export type FullscreenProps = LikeC4.FullscreenProps<LikeC4ViewId>
88
+ export type EmbeddedProps = LikeC4.EmbeddedProps<LikeC4ViewId>
89
+ export type BrowserProps = LikeC4.BrowserProps<LikeC4ViewId>
90
+
91
+ // Re-export types
92
+ export type {
93
+ DiagramApi,
94
+ Fqn,
95
+ Element,
96
+ RelationID,
97
+ Relation,
98
+ NodeId,
99
+ EdgeId,
100
+ ViewID,
101
+ ComputedView,
102
+ LikeC4Theme,
103
+ DiagramNode,
104
+ DiagramEdge,
105
+ DiagramLabel,
106
+ DiagramView
107
+ } from '@likec4/diagrams'
108
+ `.append(NL)
109
+
110
+ return toString(out)
111
+ }
@@ -0,0 +1 @@
1
+ export * from './generate-react'
@@ -0,0 +1,121 @@
1
+ import type { DiagramView } from '@likec4/core'
2
+ import JSON5 from 'json5'
3
+ import { CompositeGeneratorNode, NL, expandToNode, joinToNode, toString } from 'langium'
4
+ import { generateViewId } from '../react/generate-react'
5
+
6
+ export function generateViewsDataJs(views: DiagramView[]) {
7
+ const out = new CompositeGeneratorNode()
8
+ out.appendTemplate`
9
+ /******************************************************************************
10
+ * This file was generated
11
+ * DO NOT EDIT MANUALLY!
12
+ ******************************************************************************/
13
+ /* eslint-disable */
14
+
15
+ `.append(NL, NL)
16
+
17
+ if (views.length == 0) {
18
+ out.append('export const LikeC4Views = {}', NL)
19
+ return toString(out)
20
+ }
21
+
22
+ out.appendTemplate`
23
+ export const LikeC4Views = {
24
+ `
25
+ .indent({
26
+ indentation: 2,
27
+ indentedChildren(indented) {
28
+ indented.appendNewLineIf(views.length > 1).append(
29
+ joinToNode(
30
+ views,
31
+ view => expandToNode`${JSON5.stringify(view.id)}: ${JSON5.stringify(view)}`,
32
+ {
33
+ separator: ',',
34
+ appendNewLineIfNotEmpty: true
35
+ }
36
+ )
37
+ )
38
+ }
39
+ })
40
+ .append('}', NL, NL).appendTemplate`
41
+
42
+ export function isLikeC4ViewId(value) {
43
+ return (
44
+ value != null &&
45
+ typeof value === 'string' &&
46
+ Object.prototype.hasOwnProperty.call(LikeC4Views, value)
47
+ )
48
+ }
49
+ `.append(NL, NL)
50
+ return toString(out)
51
+ }
52
+
53
+ export function generateViewsDataTs(views: DiagramView[]) {
54
+ const out = new CompositeGeneratorNode()
55
+ out.appendTemplate`
56
+ /******************************************************************************
57
+ * This file was generated
58
+ * DO NOT EDIT MANUALLY!
59
+ ******************************************************************************/
60
+ /* eslint-disable */
61
+
62
+ import type { DiagramView } from '@likec4/core'
63
+ `.append(NL, NL)
64
+
65
+ if (views.length == 0) {
66
+ out.append('export {}', NL)
67
+ return toString(out)
68
+ }
69
+
70
+ out.appendTemplate`
71
+ export type LikeC4ViewId = ${generateViewId(views)};
72
+ export const LikeC4Views = {
73
+ `
74
+ .indent({
75
+ indentation: 2,
76
+ indentedChildren(indented) {
77
+ indented.appendNewLineIf(views.length > 1).append(
78
+ joinToNode(
79
+ views,
80
+ view =>
81
+ expandToNode`${JSON5.stringify(view.id)}: (${JSON5.stringify(
82
+ view
83
+ )} as unknown) as DiagramView`,
84
+ {
85
+ separator: ',',
86
+ appendNewLineIfNotEmpty: true
87
+ }
88
+ )
89
+ )
90
+ }
91
+ })
92
+ .append('} as const satisfies Record<LikeC4ViewId, DiagramView>', NL, NL).appendTemplate`
93
+ export type LikeC4Views = typeof LikeC4Views
94
+
95
+ export function isLikeC4ViewId(value: unknown): value is LikeC4ViewId {
96
+ return (
97
+ value != null &&
98
+ typeof value === 'string' &&
99
+ Object.prototype.hasOwnProperty.call(LikeC4Views, value)
100
+ )
101
+ }
102
+
103
+ // Re-export types
104
+ export type {
105
+ Fqn,
106
+ Element,
107
+ RelationID,
108
+ Relation,
109
+ NodeId,
110
+ EdgeId,
111
+ ComputedNode,
112
+ ComputedEdge,
113
+ ComputedView,
114
+ DiagramView,
115
+ DiagramNode,
116
+ DiagramEdge,
117
+ DiagramLabel
118
+ } from '@likec4/core'
119
+ `.append(NL, NL)
120
+ return toString(out)
121
+ }
@@ -0,0 +1 @@
1
+ export * from './generate-views-data'
@@ -1,3 +0,0 @@
1
- import type { ComputedView } from '@likec4/core/types';
2
- export declare function generateD2<V extends ComputedView>(view: V): string;
3
- //# sourceMappingURL=generate-d2.d.ts.map
@@ -1,75 +0,0 @@
1
- import { CompositeGeneratorNode, NL, joinToNode, toString } from 'langium';
2
- import { isNil } from 'rambdax';
3
- const capitalizeFirstLetter = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
4
- const fqnName = (nodeId) => nodeId.split('.').map(capitalizeFirstLetter).join('');
5
- const nodeName = (node) => {
6
- return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
7
- };
8
- const d2direction = ({ autoLayout }) => {
9
- switch (autoLayout) {
10
- case 'TB': {
11
- return 'down';
12
- }
13
- case 'BT': {
14
- return 'up';
15
- }
16
- case 'LR': {
17
- return 'right';
18
- }
19
- case 'RL': {
20
- return 'left';
21
- }
22
- }
23
- };
24
- const d2shape = ({ shape }) => {
25
- switch (shape) {
26
- case 'queue':
27
- case 'cylinder':
28
- case 'rectangle':
29
- case 'person': {
30
- return shape;
31
- }
32
- case 'storage': {
33
- return 'stored_data';
34
- }
35
- case 'mobile':
36
- case 'browser': {
37
- return 'rectangle';
38
- }
39
- }
40
- };
41
- export function generateD2(view) {
42
- const { nodes, edges } = view;
43
- const names = new Map();
44
- const printNode = (node, parentName) => {
45
- const name = nodeName(node);
46
- const fqnName = (parentName ? parentName + '.' : '') + name;
47
- names.set(node.id, fqnName);
48
- const label = node.title.replaceAll('\n', '\\n');
49
- const shape = d2shape(node);
50
- return new CompositeGeneratorNode()
51
- .append(name, ': {', NL)
52
- .indent({
53
- indentedChildren: indent => indent
54
- .append('label: "', label, '"', NL)
55
- .appendIf(shape !== 'rectangle', 'shape: ', shape, NL)
56
- .appendIf(node.children.length > 0, NL, joinToNode(nodes.filter(n => n.parent === node.id), n => printNode(n, fqnName))),
57
- indentation: 2
58
- })
59
- .append('}', NL);
60
- };
61
- // return `${names.get(edge.source)} -> ${names.get(edge.target)}${edge.label ? ': ' + edge.label : ''}`
62
- const printEdge = (edge) => {
63
- return new CompositeGeneratorNode()
64
- .append(names.get(edge.source), ' -> ', names.get(edge.target))
65
- .append(out => edge.label && out.append(': ', edge.label.replaceAll('\n', '\\n')));
66
- };
67
- return toString(new CompositeGeneratorNode()
68
- .append('direction: ', d2direction(view), NL, NL)
69
- .append(joinToNode(nodes.filter(n => isNil(n.parent)), n => printNode(n), {
70
- appendNewLineIfNotEmpty: true
71
- }))
72
- .appendIf(edges.length > 0, NL, joinToNode(edges, e => printEdge(e), {
73
- appendNewLineIfNotEmpty: true
74
- })));
75
- }
@@ -1,2 +0,0 @@
1
- export * from './generate-d2';
2
- //# sourceMappingURL=index.d.ts.map
package/dist/d2/index.js DELETED
@@ -1 +0,0 @@
1
- export * from './generate-d2';
package/dist/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export { generateReact } from './react/generate-react';
2
- export { generateD2 } from './d2/generate-d2';
3
- export { generateMermaid } from './mmd/generate-mmd';
4
- export { generateViewsDataTs } from './views-data-ts/generate-views-data';
5
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js DELETED
@@ -1,4 +0,0 @@
1
- export { generateReact } from './react/generate-react';
2
- export { generateD2 } from './d2/generate-d2';
3
- export { generateMermaid } from './mmd/generate-mmd';
4
- export { generateViewsDataTs } from './views-data-ts/generate-views-data';
@@ -1,3 +0,0 @@
1
- import type { ComputedView } from '@likec4/core/types';
2
- export declare function generateMermaid<V extends ComputedView>(view: V): string;
3
- //# sourceMappingURL=generate-mmd.d.ts.map
@@ -1,62 +0,0 @@
1
- import { CompositeGeneratorNode, NL, joinToNode, toString } from 'langium';
2
- import { isNil } from 'rambdax';
3
- const capitalizeFirstLetter = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
4
- const fqnName = (nodeId) => nodeId.split('.').map(capitalizeFirstLetter).join('');
5
- const nodeName = (node) => {
6
- return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
7
- };
8
- const mmdshape = ({ shape }) => {
9
- switch (shape) {
10
- case 'queue':
11
- case 'cylinder':
12
- return ['[(', ')]'];
13
- case 'person': {
14
- return ['[fa:fa-user ', ']'];
15
- }
16
- case 'storage':
17
- return ['([', '])'];
18
- case 'mobile':
19
- case 'browser':
20
- case 'rectangle': {
21
- return ['[', ']'];
22
- }
23
- }
24
- };
25
- export function generateMermaid(view) {
26
- const { nodes, edges } = view;
27
- const names = new Map();
28
- const printNode = (node, parentName) => {
29
- const name = nodeName(node);
30
- const fqnName = (parentName ? parentName + '.' : '') + name;
31
- names.set(node.id, fqnName);
32
- const label = node.title.replaceAll('\n', '\\n');
33
- const shape = mmdshape(node);
34
- const baseNode = new CompositeGeneratorNode();
35
- if (node.children.length > 0) {
36
- baseNode
37
- .append('subgraph ', fqnName, '["', label, '"]', NL)
38
- .indent({
39
- indentedChildren: indent => indent.appendIf(node.children.length > 0, NL, joinToNode(nodes.filter(n => n.parent === node.id), n => printNode(n, fqnName))),
40
- indentation: 2
41
- })
42
- .append('end', NL);
43
- }
44
- else {
45
- baseNode.append(fqnName, shape[0], label, shape[1], NL);
46
- }
47
- return baseNode;
48
- };
49
- // return `${names.get(edge.source)} -> ${names.get(edge.target)}${edge.label ? ': ' + edge.label : ''}`
50
- const printEdge = (edge) => {
51
- return new CompositeGeneratorNode().append(names.get(edge.source), ' --', edge.label ? '"' + edge.label.replaceAll('\n', '\\n') + '"--' : '', '> ', names.get(edge.target));
52
- };
53
- return toString(new CompositeGeneratorNode()
54
- .appendIf(view.title !== null && view.title.length > 0, '---', NL, `title: ${view.title}`, NL, '---', NL)
55
- .append('graph ', view.autoLayout, NL, NL)
56
- .append(joinToNode(nodes.filter(n => isNil(n.parent)), n => printNode(n), {
57
- appendNewLineIfNotEmpty: true
58
- }))
59
- .appendIf(edges.length > 0, NL, joinToNode(edges, e => printEdge(e), {
60
- appendNewLineIfNotEmpty: true
61
- })));
62
- }
@@ -1,2 +0,0 @@
1
- export * from './generate-mmd';
2
- //# sourceMappingURL=index.d.ts.map
package/dist/mmd/index.js DELETED
@@ -1 +0,0 @@
1
- export * from './generate-mmd';
@@ -1,5 +0,0 @@
1
- import type { DiagramView } from '@likec4/core';
2
- import { CompositeGeneratorNode } from 'langium';
3
- export declare const generateViewId: (views: DiagramView[]) => CompositeGeneratorNode | undefined;
4
- export declare function generateReact(views: DiagramView[]): string;
5
- //# sourceMappingURL=generate-react.d.ts.map
@@ -1,87 +0,0 @@
1
- import JSON5 from 'json5';
2
- import { CompositeGeneratorNode, NL, expandToNode, joinToNode, toString } from 'langium';
3
- const componentName = (value) => {
4
- if (!value.charAt(0).match(/[a-zA-Z]/)) {
5
- value = 'View' + value;
6
- }
7
- value = value.replaceAll('_', '');
8
- return value.charAt(0).toLocaleUpperCase() + value.slice(1);
9
- };
10
- export const generateViewId = (views) => joinToNode(views, view => expandToNode `'${view.id}'`, {
11
- separator: ' | '
12
- });
13
- export function generateReact(views) {
14
- const components = views.map(({ id }) => {
15
- return {
16
- id,
17
- name: componentName(id)
18
- };
19
- });
20
- const out = new CompositeGeneratorNode();
21
- out.appendTemplate `
22
- /******************************************************************************
23
- * This file was generated
24
- * DO NOT EDIT MANUALLY!
25
- ******************************************************************************/
26
- /* eslint-disable */
27
-
28
- import type { DiagramView } from '@likec4/diagrams'
29
- import { LikeC4 } from '@likec4/diagrams'
30
- `.append(NL, NL);
31
- if (components.length == 0) {
32
- out.append('export {}', NL);
33
- return toString(out);
34
- }
35
- out.appendTemplate `
36
-
37
- export type LikeC4ViewId = ${generateViewId(views)};
38
- export const LikeC4Views = {
39
- `
40
- .indent({
41
- indentation: 2,
42
- indentedChildren(indented) {
43
- indented.appendNewLineIf(views.length > 1).append(joinToNode(views, view => expandToNode `${JSON5.stringify(view.id)}: (${JSON5.stringify(view)} as unknown) as DiagramView`, {
44
- separator: ',',
45
- appendNewLineIfNotEmpty: true
46
- }));
47
- }
48
- })
49
- .append('} as const satisfies Record<LikeC4ViewId, DiagramView>', NL, NL).appendTemplate `
50
- export type LikeC4Views = typeof LikeC4Views
51
-
52
- export const {
53
- isViewId,
54
- useViewId,
55
- Diagram,
56
- Responsive,
57
- Fullscreen,
58
- Embedded,
59
- Browser,
60
- } = LikeC4.create<LikeC4ViewId>(LikeC4Views)
61
-
62
- export type DiagramProps = LikeC4.DiagramProps<LikeC4ViewId>
63
- export type ResponsiveProps = LikeC4.ResponsiveProps<LikeC4ViewId>
64
- export type FullscreenProps = LikeC4.FullscreenProps<LikeC4ViewId>
65
- export type EmbeddedProps = LikeC4.EmbeddedProps<LikeC4ViewId>
66
- export type BrowserProps = LikeC4.BrowserProps<LikeC4ViewId>
67
-
68
- // Re-export types
69
- export type {
70
- DiagramApi,
71
- Fqn,
72
- Element,
73
- RelationID,
74
- Relation,
75
- NodeId,
76
- EdgeId,
77
- ViewID,
78
- ComputedView,
79
- LikeC4Theme,
80
- DiagramNode,
81
- DiagramEdge,
82
- DiagramLabel,
83
- DiagramView
84
- } from '@likec4/diagrams'
85
- `.append(NL, NL);
86
- return toString(out);
87
- }
@@ -1,2 +0,0 @@
1
- export * from './generate-react';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- export * from './generate-react';
@@ -1,3 +0,0 @@
1
- import type { DiagramView } from '@likec4/core';
2
- export declare function generateViewsDataTs(views: DiagramView[]): string;
3
- //# sourceMappingURL=generate-views-data.d.ts.map
@@ -1,61 +0,0 @@
1
- import JSON5 from 'json5';
2
- import { CompositeGeneratorNode, NL, expandToNode, joinToNode, toString } from 'langium';
3
- import { generateViewId } from '../react/generate-react';
4
- export function generateViewsDataTs(views) {
5
- const out = new CompositeGeneratorNode();
6
- out.appendTemplate `
7
- /******************************************************************************
8
- * This file was generated
9
- * DO NOT EDIT MANUALLY!
10
- ******************************************************************************/
11
- /* eslint-disable */
12
-
13
- import type { DiagramView } from '@likec4/core'
14
- `.append(NL, NL);
15
- if (views.length == 0) {
16
- out.append('export {}', NL);
17
- return toString(out);
18
- }
19
- out.appendTemplate `
20
- export type LikeC4ViewId = ${generateViewId(views)};
21
- export const LikeC4Views = {
22
- `
23
- .indent({
24
- indentation: 2,
25
- indentedChildren(indented) {
26
- indented.appendNewLineIf(views.length > 1).append(joinToNode(views, view => expandToNode `${JSON5.stringify(view.id)}: (${JSON5.stringify(view)} as unknown) as DiagramView`, {
27
- separator: ',',
28
- appendNewLineIfNotEmpty: true
29
- }));
30
- }
31
- })
32
- .append('} as const satisfies Record<LikeC4ViewId, DiagramView>', NL, NL).appendTemplate `
33
- export type LikeC4Views = typeof LikeC4Views
34
-
35
- export function isLikeC4ViewId(value: unknown): value is LikeC4ViewId {
36
- return (
37
- value != null &&
38
- typeof value === 'string' &&
39
- Object.prototype.hasOwnProperty.call(LikeC4Views, value)
40
- )
41
- }
42
-
43
- // Re-export types
44
- export type {
45
- Fqn,
46
- Element,
47
- RelationID,
48
- Relation,
49
- NodeId,
50
- EdgeId,
51
- ComputedNode,
52
- ComputedEdge,
53
- ComputedView,
54
- DiagramView,
55
- DiagramNode,
56
- DiagramEdge,
57
- DiagramLabel
58
- } from '@likec4/core'
59
- `.append(NL, NL);
60
- return toString(out);
61
- }
@@ -1,2 +0,0 @@
1
- export * from './generate-views-data';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- export * from './generate-views-data';