@openpowershift/logic-diagram-language 0.1.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/examples.d.ts +2 -0
  4. package/dist/examples.js +469 -0
  5. package/dist/export-image.d.ts +10 -0
  6. package/dist/export-image.js +47 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.html +13 -0
  9. package/dist/index.js +18 -0
  10. package/dist/parser/ast.d.ts +118 -0
  11. package/dist/parser/ast.js +79 -0
  12. package/dist/parser/index.d.ts +3 -0
  13. package/dist/parser/index.js +2 -0
  14. package/dist/parser/parser.d.ts +2 -0
  15. package/dist/parser/parser.js +635 -0
  16. package/dist/renderer/astar-router.d.ts +16 -0
  17. package/dist/renderer/astar-router.js +532 -0
  18. package/dist/renderer/gates.d.ts +19 -0
  19. package/dist/renderer/gates.js +92 -0
  20. package/dist/renderer/graph.d.ts +31 -0
  21. package/dist/renderer/graph.js +403 -0
  22. package/dist/renderer/layout.d.ts +76 -0
  23. package/dist/renderer/layout.js +3121 -0
  24. package/dist/renderer/math-renderer.d.ts +16 -0
  25. package/dist/renderer/math-renderer.js +119 -0
  26. package/dist/renderer/svg-renderer.d.ts +3 -0
  27. package/dist/renderer/svg-renderer.js +599 -0
  28. package/dist/renderer/wires.d.ts +5 -0
  29. package/dist/renderer/wires.js +12 -0
  30. package/dist/theme/themes.d.ts +58 -0
  31. package/dist/theme/themes.js +104 -0
  32. package/docs/api.adoc +196 -0
  33. package/docs/ldl-for-llms.md +163 -0
  34. package/docs/user-guide.adoc +318 -0
  35. package/package.json +78 -0
  36. package/spec/render.sh +22 -0
  37. package/spec/sections/attributes.adoc +80 -0
  38. package/spec/sections/connections.adoc +39 -0
  39. package/spec/sections/examples.adoc +212 -0
  40. package/spec/sections/expressions.adoc +182 -0
  41. package/spec/sections/file-extension.adoc +5 -0
  42. package/spec/sections/function-blocks.adoc +120 -0
  43. package/spec/sections/grammar.adoc +64 -0
  44. package/spec/sections/hyperlinks.adoc +18 -0
  45. package/spec/sections/introduction.adoc +16 -0
  46. package/spec/sections/layout-rules.adoc +491 -0
  47. package/spec/sections/lexical-conventions.adoc +68 -0
  48. package/spec/sections/objects.adoc +31 -0
  49. package/spec/sections/options.adoc +146 -0
  50. package/spec/sections/ports.adoc +77 -0
  51. package/spec/sections/rendering-contract.adoc +11 -0
  52. package/spec/sections/revision-history.adoc +9 -0
  53. package/spec/sections/styling.adoc +83 -0
  54. package/spec/sections/svg-symbol-specification.adoc +149 -0
  55. package/spec/sections/symbol-definitions.adoc +143 -0
  56. package/spec/sections/templates.adoc +31 -0
  57. package/spec/spec.adoc +49 -0
@@ -0,0 +1,16 @@
1
+ export interface MathSegment {
2
+ type: 'plain' | 'math';
3
+ text: string;
4
+ }
5
+ export interface MathRenderResult {
6
+ svg: string;
7
+ width: number;
8
+ height: number;
9
+ baselineOffset: number;
10
+ }
11
+ import '@mathjax/src/js/util/asyncLoad/esm.js';
12
+ import '@mathjax/src/js/input/tex/ams/AmsConfiguration.js';
13
+ export declare function renderMath(tex: string, fontSize: number): MathRenderResult | null;
14
+ export declare function splitIntoSegments(text: string): MathSegment[];
15
+ export declare function hasMathContent(text: string): boolean;
16
+ export declare function estimateTextWidth(text: string, fontSize: number): number;
@@ -0,0 +1,119 @@
1
+ import { mathjax } from '@mathjax/src/js/mathjax.js';
2
+ import { TeX } from '@mathjax/src/js/input/tex.js';
3
+ import { SVG } from '@mathjax/src/js/output/svg.js';
4
+ import { liteAdaptor } from '@mathjax/src/js/adaptors/liteAdaptor.js';
5
+ import { RegisterHTMLHandler } from '@mathjax/src/js/handlers/html.js';
6
+ import '@mathjax/src/js/util/asyncLoad/esm.js';
7
+ import '@mathjax/src/js/input/tex/ams/AmsConfiguration.js';
8
+ const adaptor = liteAdaptor();
9
+ RegisterHTMLHandler(adaptor);
10
+ const texInput = new TeX({ packages: ['base', 'ams'] });
11
+ const svgOutput = new SVG({ fontCache: 'local', linebreaks: { inline: false } });
12
+ const doc = mathjax.document('', { InputJax: texInput, OutputJax: svgOutput });
13
+ function getExInPx(fontSize) {
14
+ return fontSize * 0.5;
15
+ }
16
+ function setSvgPixelSize(svg, widthPx, heightPx) {
17
+ adaptor.setAttribute(svg, 'width', `${widthPx}px`);
18
+ adaptor.setAttribute(svg, 'height', `${heightPx}px`);
19
+ adaptor.removeAttribute(svg, 'style');
20
+ }
21
+ export function renderMath(tex, fontSize) {
22
+ try {
23
+ const node = doc.convert(tex, { display: false });
24
+ const svgEl = adaptor.firstChild(node);
25
+ if (!svgEl)
26
+ return null;
27
+ const widthEx = parseFloat(adaptor.getAttribute(svgEl, 'width') || '0');
28
+ const heightEx = parseFloat(adaptor.getAttribute(svgEl, 'height') || '0');
29
+ const exPx = getExInPx(fontSize);
30
+ const width = Math.max(widthEx * exPx, 10);
31
+ const height = Math.max(heightEx * exPx, fontSize * 0.8);
32
+ const viewBox = (adaptor.getAttribute(svgEl, 'viewBox') || '0 0 0 0').split(' ').map(Number);
33
+ const baselineOffset = viewBox[3] > 0 ? height * (-viewBox[1] / viewBox[3]) : 0;
34
+ setSvgPixelSize(svgEl, width, height);
35
+ const svgStr = adaptor.outerHTML(svgEl);
36
+ return { svg: svgStr, width, height, baselineOffset };
37
+ }
38
+ catch (e) {
39
+ console.error('MathJax conversion failed:', e);
40
+ return null;
41
+ }
42
+ }
43
+ export function splitIntoSegments(text) {
44
+ const segments = [];
45
+ let currentPlain = '';
46
+ let i = 0;
47
+ while (i < text.length) {
48
+ if (text[i] === '\\' && i + 1 < text.length && text[i + 1] === '$') {
49
+ currentPlain += '$';
50
+ i += 2;
51
+ continue;
52
+ }
53
+ if (text[i] === '$') {
54
+ const start = i + 1;
55
+ const end = text.indexOf('$', start);
56
+ if (end === -1) {
57
+ currentPlain += text.slice(i);
58
+ break;
59
+ }
60
+ if (currentPlain.length > 0) {
61
+ segments.push({ type: 'plain', text: currentPlain });
62
+ currentPlain = '';
63
+ }
64
+ segments.push({ type: 'math', text: text.slice(start, end) });
65
+ i = end + 1;
66
+ continue;
67
+ }
68
+ currentPlain += text[i];
69
+ i++;
70
+ }
71
+ if (currentPlain.length > 0) {
72
+ segments.push({ type: 'plain', text: currentPlain });
73
+ }
74
+ return segments;
75
+ }
76
+ export function hasMathContent(text) {
77
+ let i = 0;
78
+ while (i < text.length) {
79
+ if (text[i] === '\\' && i + 1 < text.length && text[i + 1] === '$') {
80
+ i += 2;
81
+ continue;
82
+ }
83
+ if (text[i] === '$') {
84
+ const end = text.indexOf('$', i + 1);
85
+ if (end > i)
86
+ return true;
87
+ }
88
+ i++;
89
+ }
90
+ return false;
91
+ }
92
+ // Approximate the advance width of a string in a sans-serif face, in pixels. Per-character
93
+ // em factors are calibrated to Helvetica/Arial and kept slightly generous so callers never
94
+ // under-estimate (which would let adjacent label segments overlap or clip the viewBox).
95
+ export function estimateTextWidth(text, fontSize) {
96
+ let em = 0;
97
+ for (const ch of text) {
98
+ const code = ch.charCodeAt(0);
99
+ if (ch >= 'A' && ch <= 'Z')
100
+ em += 0.70;
101
+ else if (ch === 'i' || ch === 'l' || ch === 'j' || ch === 't' || ch === 'f')
102
+ em += 0.30;
103
+ else if (ch >= 'a' && ch <= 'z')
104
+ em += 0.52;
105
+ else if (ch >= '0' && ch <= '9')
106
+ em += 0.56;
107
+ else if (ch === ' ')
108
+ em += 0.30;
109
+ else if (ch === '.' || ch === ',' || ch === ':' || ch === ';' || ch === "'" || ch === '|' || ch === '!')
110
+ em += 0.30;
111
+ else if (ch === '(' || ch === ')' || ch === '[' || ch === ']' || ch === '{' || ch === '}')
112
+ em += 0.36;
113
+ else if (code > 0x2000)
114
+ em += 0.62;
115
+ else
116
+ em += 0.56;
117
+ }
118
+ return em * fontSize;
119
+ }
@@ -0,0 +1,3 @@
1
+ import type { Diagram, PortMeta, RenderOptions } from '../parser/ast.js';
2
+ import type { DiagramTheme } from '../theme/themes.js';
3
+ export declare function renderDiagram(diagram: Diagram, portMeta?: PortMeta[], showLabels?: boolean, showIds?: boolean, options?: RenderOptions, diagramTheme?: DiagramTheme): string;