wyreframe 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 (117) hide show
  1. package/README.md +123 -0
  2. package/dist/index.d.ts +267 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +195 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +63 -0
  7. package/src/parser/Core/Bounds.mjs +61 -0
  8. package/src/parser/Core/Bounds.res +65 -0
  9. package/src/parser/Core/Grid.mjs +268 -0
  10. package/src/parser/Core/Grid.res +265 -0
  11. package/src/parser/Core/Position.mjs +83 -0
  12. package/src/parser/Core/Position.res +54 -0
  13. package/src/parser/Core/Types.mjs +435 -0
  14. package/src/parser/Core/Types.res +331 -0
  15. package/src/parser/Core/__tests__/Bounds_test.mjs +326 -0
  16. package/src/parser/Core/__tests__/Bounds_test.res +412 -0
  17. package/src/parser/Core/__tests__/Grid_test.mjs +322 -0
  18. package/src/parser/Core/__tests__/Grid_test.res +319 -0
  19. package/src/parser/Core/__tests__/Types_test.mjs +614 -0
  20. package/src/parser/Core/__tests__/Types_test.res +650 -0
  21. package/src/parser/Detector/BoxTracer.mjs +302 -0
  22. package/src/parser/Detector/BoxTracer.res +374 -0
  23. package/src/parser/Detector/HierarchyBuilder.mjs +158 -0
  24. package/src/parser/Detector/HierarchyBuilder.res +315 -0
  25. package/src/parser/Detector/ShapeDetector.mjs +134 -0
  26. package/src/parser/Detector/ShapeDetector.res +236 -0
  27. package/src/parser/Detector/__tests__/BoxTracer_test.mjs +70 -0
  28. package/src/parser/Detector/__tests__/BoxTracer_test.res +92 -0
  29. package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +489 -0
  30. package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +849 -0
  31. package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +377 -0
  32. package/src/parser/Detector/__tests__/ShapeDetector_test.res +563 -0
  33. package/src/parser/Errors/ErrorContext.mjs +106 -0
  34. package/src/parser/Errors/ErrorContext.res +191 -0
  35. package/src/parser/Errors/ErrorMessages.mjs +289 -0
  36. package/src/parser/Errors/ErrorMessages.res +303 -0
  37. package/src/parser/Errors/ErrorTypes.mjs +105 -0
  38. package/src/parser/Errors/ErrorTypes.res +169 -0
  39. package/src/parser/Interactions/InteractionMerger.mjs +266 -0
  40. package/src/parser/Interactions/InteractionMerger.res +450 -0
  41. package/src/parser/Interactions/InteractionParser.mjs +88 -0
  42. package/src/parser/Interactions/InteractionParser.res +127 -0
  43. package/src/parser/Interactions/SimpleInteractionParser.mjs +278 -0
  44. package/src/parser/Interactions/SimpleInteractionParser.res +262 -0
  45. package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +576 -0
  46. package/src/parser/Interactions/__tests__/InteractionMerger_test.res +646 -0
  47. package/src/parser/Parser.gen.tsx +96 -0
  48. package/src/parser/Parser.mjs +212 -0
  49. package/src/parser/Parser.res +481 -0
  50. package/src/parser/Scanner/__tests__/Grid_manual.mjs +214 -0
  51. package/src/parser/Scanner/__tests__/Grid_manual.res +141 -0
  52. package/src/parser/Semantic/ASTBuilder.mjs +197 -0
  53. package/src/parser/Semantic/ASTBuilder.res +288 -0
  54. package/src/parser/Semantic/AlignmentCalc.mjs +41 -0
  55. package/src/parser/Semantic/AlignmentCalc.res +104 -0
  56. package/src/parser/Semantic/Elements/ButtonParser.mjs +58 -0
  57. package/src/parser/Semantic/Elements/ButtonParser.res +131 -0
  58. package/src/parser/Semantic/Elements/CheckboxParser.mjs +58 -0
  59. package/src/parser/Semantic/Elements/CheckboxParser.res +79 -0
  60. package/src/parser/Semantic/Elements/CodeTextParser.mjs +50 -0
  61. package/src/parser/Semantic/Elements/CodeTextParser.res +111 -0
  62. package/src/parser/Semantic/Elements/ElementParser.mjs +15 -0
  63. package/src/parser/Semantic/Elements/ElementParser.res +83 -0
  64. package/src/parser/Semantic/Elements/EmphasisParser.mjs +46 -0
  65. package/src/parser/Semantic/Elements/EmphasisParser.res +67 -0
  66. package/src/parser/Semantic/Elements/InputParser.mjs +41 -0
  67. package/src/parser/Semantic/Elements/InputParser.res +97 -0
  68. package/src/parser/Semantic/Elements/LinkParser.mjs +60 -0
  69. package/src/parser/Semantic/Elements/LinkParser.res +156 -0
  70. package/src/parser/Semantic/Elements/TextParser.mjs +19 -0
  71. package/src/parser/Semantic/Elements/TextParser.res +42 -0
  72. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +189 -0
  73. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +257 -0
  74. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +202 -0
  75. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +250 -0
  76. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +293 -0
  77. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +134 -0
  78. package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +253 -0
  79. package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +304 -0
  80. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +289 -0
  81. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +402 -0
  82. package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +149 -0
  83. package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +167 -0
  84. package/src/parser/Semantic/ParserRegistry.mjs +82 -0
  85. package/src/parser/Semantic/ParserRegistry.res +145 -0
  86. package/src/parser/Semantic/SemanticParser.mjs +850 -0
  87. package/src/parser/Semantic/SemanticParser.res +1368 -0
  88. package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +187 -0
  89. package/src/parser/Semantic/__tests__/ASTBuilder_test.res +192 -0
  90. package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +154 -0
  91. package/src/parser/Semantic/__tests__/ParserRegistry_test.res +191 -0
  92. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +768 -0
  93. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +1069 -0
  94. package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +1329 -0
  95. package/src/parser/Semantic/__tests__/SemanticParser_manual.res +544 -0
  96. package/src/parser/TestMain.mjs +21 -0
  97. package/src/parser/TestMain.res +14 -0
  98. package/src/parser/TextExtractor.mjs +179 -0
  99. package/src/parser/TextExtractor.res +264 -0
  100. package/src/parser/__tests__/GridScanner_integration.test.mjs +632 -0
  101. package/src/parser/__tests__/GridScanner_integration.test.res +816 -0
  102. package/src/parser/__tests__/Performance.test.mjs +244 -0
  103. package/src/parser/__tests__/Performance.test.res +371 -0
  104. package/src/parser/__tests__/PerformanceFixtures.mjs +200 -0
  105. package/src/parser/__tests__/PerformanceFixtures.res +284 -0
  106. package/src/parser/__tests__/WyreframeParser_integration.test.mjs +770 -0
  107. package/src/parser/__tests__/WyreframeParser_integration.test.res +1008 -0
  108. package/src/parser/__tests__/fixtures/alignment-test.txt +9 -0
  109. package/src/parser/__tests__/fixtures/all-elements.txt +16 -0
  110. package/src/parser/__tests__/fixtures/login-scene.txt +17 -0
  111. package/src/parser/__tests__/fixtures/multi-scene.txt +25 -0
  112. package/src/parser/__tests__/fixtures/nested-boxes.txt +15 -0
  113. package/src/parser/__tests__/fixtures/simple-box.txt +5 -0
  114. package/src/parser/__tests__/fixtures/with-dividers.txt +14 -0
  115. package/src/renderer/Renderer.gen.tsx +32 -0
  116. package/src/renderer/Renderer.mjs +391 -0
  117. package/src/renderer/Renderer.res +558 -0
@@ -0,0 +1,46 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Types from "../../Core/Types.mjs";
4
+ import * as AlignmentCalc from "../AlignmentCalc.mjs";
5
+ import * as ElementParser from "./ElementParser.mjs";
6
+
7
+ let emphasisPattern = /^\s*\*\s+(.+)$/;
8
+
9
+ let quickTestPattern = /^\s*\*\s/;
10
+
11
+ function canParse(content) {
12
+ return quickTestPattern.test(content);
13
+ }
14
+
15
+ function parse(content, position, bounds) {
16
+ let result = emphasisPattern.exec(content);
17
+ if (result == null) {
18
+ return;
19
+ }
20
+ let matches = result.slice(1);
21
+ let textContent = matches[0];
22
+ if (textContent === undefined) {
23
+ return;
24
+ }
25
+ let align = AlignmentCalc.calculateWithStrategy(content, position, bounds, "RespectPosition");
26
+ return {
27
+ TAG: "Text",
28
+ content: textContent,
29
+ emphasis: true,
30
+ position: Types.Position.make(position.row, position.col),
31
+ align: align
32
+ };
33
+ }
34
+
35
+ function make() {
36
+ return ElementParser.make(70, canParse, parse);
37
+ }
38
+
39
+ export {
40
+ emphasisPattern,
41
+ quickTestPattern,
42
+ canParse,
43
+ parse,
44
+ make,
45
+ }
46
+ /* Types Not a pure module */
@@ -0,0 +1,67 @@
1
+ // EmphasisParser.res
2
+ // Parser for emphasis text syntax: * Text
3
+
4
+ open Types
5
+
6
+ /**
7
+ * Emphasis pattern regex: ^\s*\*\s+(.+)
8
+ * Matches: * Important text
9
+ */
10
+ let emphasisPattern = %re("/^\s*\*\s+(.+)$/")
11
+
12
+ /**
13
+ * Quick test pattern for canParse (optimized for speed).
14
+ */
15
+ let quickTestPattern = %re("/^\s*\*\s/")
16
+
17
+ /**
18
+ * Check if content matches emphasis syntax pattern.
19
+ */
20
+ let canParse = (content: string): bool => {
21
+ Js.Re.test_(quickTestPattern, content)
22
+ }
23
+
24
+ /**
25
+ * Parse emphasis element from content.
26
+ */
27
+ let parse = (
28
+ content: string,
29
+ position: Position.t,
30
+ bounds: Bounds.t,
31
+ ): option<Types.element> => {
32
+ switch emphasisPattern->RegExp.exec(content) {
33
+ | None => None
34
+ | Some(result) => {
35
+ // RegExp.Result.matches slices off the full match, so matches[0] is the first captured group
36
+ let matches = result->RegExp.Result.matches
37
+ switch matches[0] {
38
+ | None => None
39
+ | Some(textContent) => {
40
+ let align = AlignmentCalc.calculateWithStrategy(
41
+ content,
42
+ position,
43
+ bounds,
44
+ AlignmentCalc.RespectPosition,
45
+ )
46
+
47
+ Some(
48
+ Types.Text({
49
+ content: textContent,
50
+ emphasis: true,
51
+ position: Types.Position.make(position.row, position.col),
52
+ align: align,
53
+ }),
54
+ )
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Create an EmphasisParser instance.
63
+ * Priority: 70
64
+ */
65
+ let make = (): ElementParser.elementParser => {
66
+ ElementParser.make(~priority=70, ~canParse, ~parse)
67
+ }
@@ -0,0 +1,41 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Types from "../../Core/Types.mjs";
4
+ import * as ElementParser from "./ElementParser.mjs";
5
+
6
+ let inputPattern = /(?:^|[^#])#(\w+)\s*$/;
7
+
8
+ function canParse(content) {
9
+ let trimmed = content.trim();
10
+ return inputPattern.test(trimmed);
11
+ }
12
+
13
+ function parse(content, position, _bounds) {
14
+ let trimmed = content.trim();
15
+ let result = inputPattern.exec(trimmed);
16
+ if (result == null) {
17
+ return;
18
+ }
19
+ let matches = result.slice(1);
20
+ let identifier = matches[0];
21
+ if (identifier !== undefined) {
22
+ return {
23
+ TAG: "Input",
24
+ id: identifier,
25
+ placeholder: undefined,
26
+ position: Types.Position.make(position.row, position.col)
27
+ };
28
+ }
29
+ }
30
+
31
+ function make() {
32
+ return ElementParser.make(90, canParse, parse);
33
+ }
34
+
35
+ export {
36
+ inputPattern,
37
+ canParse,
38
+ parse,
39
+ make,
40
+ }
41
+ /* Types Not a pure module */
@@ -0,0 +1,97 @@
1
+ // InputParser.res
2
+
3
+ open Types
4
+ // Parser for input field elements with syntax "#fieldname"
5
+ //
6
+ // Recognizes input fields denoted by a hash (#) followed by an identifier.
7
+ // Example: "#email", "#password", "#username"
8
+
9
+ /**
10
+ * Regular expression pattern for input field syntax.
11
+ * Matches: # followed by one or more word characters (letters, digits, underscores)
12
+ * The field must be at the end of the string (with optional trailing whitespace).
13
+ * Can appear anywhere in the line, optionally preceded by a label.
14
+ * Examples:
15
+ * - "#email" ✓
16
+ * - "#password123" ✓
17
+ * - "#user_name" ✓
18
+ * - "Email: #email" ✓ (with label prefix)
19
+ * - "Password: #password" ✓ (with label prefix)
20
+ * - "#first-name" ✗ (contains hyphen after word characters)
21
+ * - "#email.address" ✗ (dot not allowed)
22
+ * - "##email" ✗ (double hash not allowed)
23
+ * - "# email" ✗ (space after #)
24
+ */
25
+ // Pattern: (start or non-#) + # + word chars + optional trailing whitespace + end
26
+ let inputPattern = %re("/(?:^|[^#])#(\w+)\s*$/")
27
+
28
+ /**
29
+ * Quick check if content matches input field pattern.
30
+ *
31
+ * @param content - Text content to check
32
+ * @return true if content contains # followed by word characters
33
+ */
34
+ let canParse = (content: string): bool => {
35
+ let trimmed = content->String.trim
36
+
37
+ // Check if contains #\w+ pattern anywhere in the string
38
+ inputPattern->RegExp.test(trimmed)
39
+ }
40
+
41
+ /**
42
+ * Parse input field element from content.
43
+ *
44
+ * Extracts the field identifier after the # character and creates
45
+ * an Input element with that ID.
46
+ *
47
+ * @param content - Text content to parse (e.g., "#email")
48
+ * @param position - Grid position where input was found
49
+ * @param _bounds - Bounding box (not used for inputs, they are always left-aligned)
50
+ * @return Some(Input element) if parsing succeeds, None otherwise
51
+ */
52
+ let parse = (
53
+ content: string,
54
+ position: Position.t,
55
+ _bounds: Bounds.t,
56
+ ): ElementParser.parseResult<Types.element> => {
57
+ let trimmed = content->String.trim
58
+
59
+ // Extract identifier after # character
60
+ switch inputPattern->RegExp.exec(trimmed) {
61
+ | Some(result) => {
62
+ // Get first capture group (the identifier after #)
63
+ // RegExp.Result.matches slices off the full match, so matches[0] is the first captured group
64
+ let matches = result->RegExp.Result.matches
65
+ switch matches[0] {
66
+ | Some(identifier) => {
67
+ // Successfully extracted identifier
68
+ Some(
69
+ Types.Input({
70
+ id: identifier,
71
+ placeholder: None,
72
+ position: Types.Position.make(position.row, position.col),
73
+ })
74
+ )
75
+ }
76
+ | None => None
77
+ }
78
+ }
79
+ | None => None
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Create an InputParser instance with priority 90.
85
+ *
86
+ * Priority explanation:
87
+ * - 100: Buttons (highest priority)
88
+ * - 90: Inputs (this parser)
89
+ * - 80: Links
90
+ * - 70: Emphasis
91
+ * - 1: Text (fallback, lowest priority)
92
+ *
93
+ * @return ElementParser.elementParser configured for input fields
94
+ */
95
+ let make = (): ElementParser.elementParser => {
96
+ ElementParser.make(~priority=90, ~canParse, ~parse)
97
+ }
@@ -0,0 +1,60 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Types from "../../Core/Types.mjs";
4
+ import * as ElementParser from "./ElementParser.mjs";
5
+
6
+ let linkPattern = /"((?:[^"\\]|\\.)+)"/;
7
+
8
+ let quickPattern = /"(?:[^"\\]|\\.)+"/;
9
+
10
+ function slugify(text) {
11
+ return text.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
12
+ }
13
+
14
+ function unescapeQuotes(text) {
15
+ return (text.replace(/\\"/g, '"'));
16
+ }
17
+
18
+ function canParse(content) {
19
+ return quickPattern.test(content);
20
+ }
21
+
22
+ function parse(content, position, _bounds) {
23
+ let result = linkPattern.exec(content);
24
+ if (result == null) {
25
+ return;
26
+ }
27
+ let matches = result.slice(1);
28
+ let linkText = matches[0];
29
+ if (linkText === undefined) {
30
+ return;
31
+ }
32
+ if (linkText.trim() === "") {
33
+ return;
34
+ }
35
+ let unescapedText = unescapeQuotes(linkText);
36
+ let linkId = slugify(unescapedText);
37
+ return {
38
+ TAG: "Link",
39
+ id: linkId,
40
+ text: unescapedText,
41
+ position: Types.Position.make(position.row, position.col),
42
+ align: "Left",
43
+ actions: []
44
+ };
45
+ }
46
+
47
+ function make() {
48
+ return ElementParser.make(80, canParse, parse);
49
+ }
50
+
51
+ export {
52
+ linkPattern,
53
+ quickPattern,
54
+ slugify,
55
+ unescapeQuotes,
56
+ canParse,
57
+ parse,
58
+ make,
59
+ }
60
+ /* Types Not a pure module */
@@ -0,0 +1,156 @@
1
+ // LinkParser.res
2
+
3
+ open Types
4
+ // Parser for link syntax: "Link Text" (quoted text)
5
+ //
6
+ // Recognizes quoted text patterns and generates Link elements.
7
+ // Priority: 80 (between inputs and checkboxes)
8
+
9
+ /**
10
+ * Regular expression pattern for matching quoted text.
11
+ * Matches: "text content" where content can include escaped quotes (\")
12
+ *
13
+ * Pattern breakdown:
14
+ * - " : Opening quote
15
+ * - ((?:[^"\\]|\\.)+) : One or more of either:
16
+ * - [^"\\] : any character except quote or backslash
17
+ * - \\. : a backslash followed by any character (handles escaped quotes)
18
+ * - " : Closing quote
19
+ *
20
+ * Using %raw to avoid ReScript's regex escaping complexity
21
+ */
22
+ let linkPattern: Js.Re.t = %raw(`/"((?:[^"\\]|\\.)+)"/`)
23
+
24
+ /**
25
+ * Quick check pattern for canParse (faster, no capture groups)
26
+ * Handles escaped quotes within the quoted text
27
+ */
28
+ let quickPattern: Js.Re.t = %raw(`/"(?:[^"\\]|\\.)+"/`)
29
+
30
+ /**
31
+ * Convert text to a URL-friendly slug identifier.
32
+ *
33
+ * Rules:
34
+ * - Convert to lowercase
35
+ * - Replace spaces and special characters with hyphens
36
+ * - Remove consecutive hyphens
37
+ * - Trim leading/trailing hyphens
38
+ *
39
+ * Examples:
40
+ * - "Login Here" -> "login-here"
41
+ * - "Sign Up!" -> "sign-up"
42
+ * - " Multiple Spaces " -> "multiple-spaces"
43
+ *
44
+ * @param text - The text to slugify
45
+ * @return URL-friendly identifier
46
+ */
47
+ let slugify = (text: string): string => {
48
+ text
49
+ ->String.toLowerCase
50
+ ->String.trim
51
+ // Replace whitespace and special chars with hyphens
52
+ ->Js.String2.replaceByRe(%re("/[^a-z0-9]+/g"), "-")
53
+ // Remove consecutive hyphens
54
+ ->Js.String2.replaceByRe(%re("/-+/g"), "-")
55
+ // Trim hyphens from start and end
56
+ ->Js.String2.replaceByRe(%re("/^-+|-+$/g"), "")
57
+ }
58
+
59
+ /**
60
+ * Unescape quotes within the link text.
61
+ * Handles escaped quotes (\") within the text content.
62
+ *
63
+ * @param text - The extracted text with potential escape sequences
64
+ * @return Text with escape sequences resolved
65
+ */
66
+ let unescapeQuotes = (text: string): string => {
67
+ // Match backslash followed by quote and replace with just quote
68
+ // Use raw JS to avoid ReScript escaping complexity
69
+ %raw(`text.replace(/\\"/g, '"')`)
70
+ }
71
+
72
+ /**
73
+ * Check if content matches the link pattern.
74
+ *
75
+ * This is a fast pattern check that doesn't extract data.
76
+ * Used by the parser registry to quickly determine if this parser should be tried.
77
+ *
78
+ * @param content - The content string to check
79
+ * @return true if content matches link syntax
80
+ */
81
+ let canParse = (content: string): bool => {
82
+ quickPattern->Js.Re.test_(content)
83
+ }
84
+
85
+ /**
86
+ * Parse link content and generate a Link element.
87
+ *
88
+ * Extracts text between quotes and creates a Link element with:
89
+ * - id: Slugified version of the link text
90
+ * - text: The extracted link text
91
+ * - position: Grid position of the link
92
+ * - align: Left alignment (default for links)
93
+ *
94
+ * @param content - The content string to parse
95
+ * @param position - Position in the grid
96
+ * @param _bounds - Bounding box (unused for now, will be used for alignment calculation)
97
+ * @return Some(Link element) if parsing succeeds, None otherwise
98
+ */
99
+ let parse = (
100
+ content: string,
101
+ position: Position.t,
102
+ _bounds: Bounds.t,
103
+ ): ElementParser.parseResult<Types.element> => {
104
+ switch linkPattern->RegExp.exec(content) {
105
+ | Some(result) => {
106
+ // RegExp.Result.matches slices off the full match, so matches[0] is the first captured group
107
+ let matches = result->RegExp.Result.matches
108
+
109
+ switch matches[0] {
110
+ | Some(linkText) => {
111
+ // linkText is already a string, no need for Nullable conversion
112
+
113
+ // Check for empty text
114
+ if linkText->String.trim === "" {
115
+ None
116
+ } else {
117
+ // Unescape any escaped quotes in the text
118
+ let unescapedText = unescapeQuotes(linkText)
119
+
120
+ // Generate ID from text
121
+ let linkId = slugify(unescapedText)
122
+
123
+ // Create Link element
124
+ // Note: Using Left alignment as default
125
+ // When AlignmentCalc is implemented, this will use calculated alignment
126
+ Some(
127
+ Types.Link({
128
+ id: linkId,
129
+ text: unescapedText,
130
+ position: Types.Position.make(position.row, position.col),
131
+ align: Left,
132
+ actions: [],
133
+ }),
134
+ )
135
+ }
136
+ }
137
+ | None => None
138
+ }
139
+ }
140
+ | None => None
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Create a LinkParser instance with priority 80.
146
+ *
147
+ * Priority 80 places it:
148
+ * - After buttons (100) and inputs (90)
149
+ * - Before checkboxes (85) and emphasis (70)
150
+ * - Well before text fallback (1)
151
+ *
152
+ * @return ElementParser.t configured for link parsing
153
+ */
154
+ let make = (): ElementParser.elementParser => {
155
+ ElementParser.make(~priority=80, ~canParse, ~parse)
156
+ }
@@ -0,0 +1,19 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Types from "../../Core/Types.mjs";
4
+ import * as ElementParser from "./ElementParser.mjs";
5
+
6
+ function make() {
7
+ return ElementParser.make(1, _content => true, (content, position, _bounds) => ({
8
+ TAG: "Text",
9
+ content: content,
10
+ emphasis: false,
11
+ position: Types.Position.make(position.row, position.col),
12
+ align: "Left"
13
+ }));
14
+ }
15
+
16
+ export {
17
+ make,
18
+ }
19
+ /* Types Not a pure module */
@@ -0,0 +1,42 @@
1
+ // TextParser.res
2
+ // Fallback parser for plain text that doesn't match any other pattern
3
+ //
4
+ // This parser has the lowest priority (1) and always accepts content,
5
+ // making it the last resort when no other parser matches.
6
+
7
+ /**
8
+ * Create a TextParser instance.
9
+ *
10
+ * This is a fallback parser that catches all unrecognized content and
11
+ * treats it as plain text. It should be registered with the lowest priority
12
+ * in the ParserRegistry.
13
+ *
14
+ * Behavior:
15
+ * - canParse: Always returns true (catches everything)
16
+ * - parse: Generates a Text element with emphasis=false
17
+ * - Priority: 1 (lowest - used as fallback)
18
+ *
19
+ * @return An ElementParser instance configured as a text fallback parser
20
+ */
21
+ let make = (): ElementParser.elementParser => {
22
+ ElementParser.make(
23
+ ~priority=1, // Lowest priority - fallback parser
24
+ ~canParse=_content => {
25
+ // Always returns true to catch any content that no other parser matched
26
+ true
27
+ },
28
+ ~parse=(content, position, _bounds) => {
29
+ // Generate a plain text element with the raw content
30
+ // Note: For fallback text, we use Left alignment by default
31
+ // This is simpler than calculating alignment for unstructured text
32
+ Some(
33
+ Types.Text({
34
+ content: content,
35
+ emphasis: false,
36
+ position: Types.Position.make(position.row, position.col),
37
+ align: Types.Left,
38
+ }),
39
+ )
40
+ },
41
+ )
42
+ }