legal-markdown-js 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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -0
  3. package/dist/browser.d.ts +87 -0
  4. package/dist/browser.d.ts.map +1 -0
  5. package/dist/browser.js +157 -0
  6. package/dist/browser.js.map +1 -0
  7. package/dist/cli/index.d.ts +34 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +221 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/service.d.ts +128 -0
  12. package/dist/cli/service.d.ts.map +1 -0
  13. package/dist/cli/service.js +284 -0
  14. package/dist/cli/service.js.map +1 -0
  15. package/dist/constants/index.d.ts +229 -0
  16. package/dist/constants/index.d.ts.map +1 -0
  17. package/dist/constants/index.js +232 -0
  18. package/dist/constants/index.js.map +1 -0
  19. package/dist/core/exporters/metadata-exporter.d.ts +104 -0
  20. package/dist/core/exporters/metadata-exporter.d.ts.map +1 -0
  21. package/dist/core/exporters/metadata-exporter.js +201 -0
  22. package/dist/core/exporters/metadata-exporter.js.map +1 -0
  23. package/dist/core/index.d.ts +40 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +56 -0
  26. package/dist/core/index.js.map +1 -0
  27. package/dist/core/parsers/yaml-parser.d.ts +149 -0
  28. package/dist/core/parsers/yaml-parser.d.ts.map +1 -0
  29. package/dist/core/parsers/yaml-parser.js +321 -0
  30. package/dist/core/parsers/yaml-parser.js.map +1 -0
  31. package/dist/core/processors/clause-processor.d.ts +74 -0
  32. package/dist/core/processors/clause-processor.d.ts.map +1 -0
  33. package/dist/core/processors/clause-processor.js +213 -0
  34. package/dist/core/processors/clause-processor.js.map +1 -0
  35. package/dist/core/processors/date-processor.d.ts +90 -0
  36. package/dist/core/processors/date-processor.d.ts.map +1 -0
  37. package/dist/core/processors/date-processor.js +336 -0
  38. package/dist/core/processors/date-processor.js.map +1 -0
  39. package/dist/core/processors/header-processor.d.ts +104 -0
  40. package/dist/core/processors/header-processor.d.ts.map +1 -0
  41. package/dist/core/processors/header-processor.js +585 -0
  42. package/dist/core/processors/header-processor.js.map +1 -0
  43. package/dist/core/processors/import-processor.d.ts +116 -0
  44. package/dist/core/processors/import-processor.d.ts.map +1 -0
  45. package/dist/core/processors/import-processor.js +236 -0
  46. package/dist/core/processors/import-processor.js.map +1 -0
  47. package/dist/core/processors/mixin-processor.d.ts +93 -0
  48. package/dist/core/processors/mixin-processor.d.ts.map +1 -0
  49. package/dist/core/processors/mixin-processor.js +378 -0
  50. package/dist/core/processors/mixin-processor.js.map +1 -0
  51. package/dist/core/processors/reference-processor.d.ts +115 -0
  52. package/dist/core/processors/reference-processor.d.ts.map +1 -0
  53. package/dist/core/processors/reference-processor.js +273 -0
  54. package/dist/core/processors/reference-processor.js.map +1 -0
  55. package/dist/errors/index.d.ts +234 -0
  56. package/dist/errors/index.d.ts.map +1 -0
  57. package/dist/errors/index.js +267 -0
  58. package/dist/errors/index.js.map +1 -0
  59. package/dist/extensions/batch-processor.d.ts +197 -0
  60. package/dist/extensions/batch-processor.d.ts.map +1 -0
  61. package/dist/extensions/batch-processor.js +392 -0
  62. package/dist/extensions/batch-processor.js.map +1 -0
  63. package/dist/extensions/formatters/index.d.ts +99 -0
  64. package/dist/extensions/formatters/index.d.ts.map +1 -0
  65. package/dist/extensions/formatters/index.js +128 -0
  66. package/dist/extensions/formatters/index.js.map +1 -0
  67. package/dist/extensions/index.d.ts +53 -0
  68. package/dist/extensions/index.d.ts.map +1 -0
  69. package/dist/extensions/index.js +71 -0
  70. package/dist/extensions/index.js.map +1 -0
  71. package/dist/extensions/latex-parser.d.ts +111 -0
  72. package/dist/extensions/latex-parser.d.ts.map +1 -0
  73. package/dist/extensions/latex-parser.js +563 -0
  74. package/dist/extensions/latex-parser.js.map +1 -0
  75. package/dist/extensions/rst-parser.d.ts +112 -0
  76. package/dist/extensions/rst-parser.d.ts.map +1 -0
  77. package/dist/extensions/rst-parser.js +268 -0
  78. package/dist/extensions/rst-parser.js.map +1 -0
  79. package/dist/extensions/template-loops.d.ts +61 -0
  80. package/dist/extensions/template-loops.d.ts.map +1 -0
  81. package/dist/extensions/template-loops.js +418 -0
  82. package/dist/extensions/template-loops.js.map +1 -0
  83. package/dist/extensions/utilities/index.d.ts +114 -0
  84. package/dist/extensions/utilities/index.d.ts.map +1 -0
  85. package/dist/extensions/utilities/index.js +137 -0
  86. package/dist/extensions/utilities/index.js.map +1 -0
  87. package/dist/extensions/validators/index.d.ts +65 -0
  88. package/dist/extensions/validators/index.d.ts.map +1 -0
  89. package/dist/extensions/validators/index.js +88 -0
  90. package/dist/extensions/validators/index.js.map +1 -0
  91. package/dist/generators/html-generator.d.ts +184 -0
  92. package/dist/generators/html-generator.d.ts.map +1 -0
  93. package/dist/generators/html-generator.js +361 -0
  94. package/dist/generators/html-generator.js.map +1 -0
  95. package/dist/generators/pdf-generator.d.ts +165 -0
  96. package/dist/generators/pdf-generator.d.ts.map +1 -0
  97. package/dist/generators/pdf-generator.js +275 -0
  98. package/dist/generators/pdf-generator.js.map +1 -0
  99. package/dist/helpers/date-helpers.d.ts +216 -0
  100. package/dist/helpers/date-helpers.d.ts.map +1 -0
  101. package/dist/helpers/date-helpers.js +402 -0
  102. package/dist/helpers/date-helpers.js.map +1 -0
  103. package/dist/helpers/index.d.ts +87 -0
  104. package/dist/helpers/index.d.ts.map +1 -0
  105. package/dist/helpers/index.js +149 -0
  106. package/dist/helpers/index.js.map +1 -0
  107. package/dist/helpers/number-helpers.d.ts +269 -0
  108. package/dist/helpers/number-helpers.d.ts.map +1 -0
  109. package/dist/helpers/number-helpers.js +406 -0
  110. package/dist/helpers/number-helpers.js.map +1 -0
  111. package/dist/helpers/string-helpers.d.ts +391 -0
  112. package/dist/helpers/string-helpers.d.ts.map +1 -0
  113. package/dist/helpers/string-helpers.js +549 -0
  114. package/dist/helpers/string-helpers.js.map +1 -0
  115. package/dist/index.d.ts +229 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +384 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/legal-markdown.umd.min.js +2 -0
  120. package/dist/legal-markdown.umd.min.js.LICENSE.txt +14 -0
  121. package/dist/legal-markdown.umd.min.js.map +1 -0
  122. package/dist/lib/index.d.ts +150 -0
  123. package/dist/lib/index.d.ts.map +1 -0
  124. package/dist/lib/index.js +265 -0
  125. package/dist/lib/index.js.map +1 -0
  126. package/dist/parsers/content-detector.d.ts +131 -0
  127. package/dist/parsers/content-detector.d.ts.map +1 -0
  128. package/dist/parsers/content-detector.js +220 -0
  129. package/dist/parsers/content-detector.js.map +1 -0
  130. package/dist/parsers/fallback-parsers.d.ts +14 -0
  131. package/dist/parsers/fallback-parsers.d.ts.map +1 -0
  132. package/dist/parsers/fallback-parsers.js +188 -0
  133. package/dist/parsers/fallback-parsers.js.map +1 -0
  134. package/dist/parsers/implementations/pandoc-native.d.ts +13 -0
  135. package/dist/parsers/implementations/pandoc-native.d.ts.map +1 -0
  136. package/dist/parsers/implementations/pandoc-native.js +63 -0
  137. package/dist/parsers/implementations/pandoc-native.js.map +1 -0
  138. package/dist/parsers/implementations/pandoc-wasm.d.ts +14 -0
  139. package/dist/parsers/implementations/pandoc-wasm.d.ts.map +1 -0
  140. package/dist/parsers/implementations/pandoc-wasm.js +64 -0
  141. package/dist/parsers/implementations/pandoc-wasm.js.map +1 -0
  142. package/dist/parsers/pandoc-factory.d.ts +97 -0
  143. package/dist/parsers/pandoc-factory.d.ts.map +1 -0
  144. package/dist/parsers/pandoc-factory.js +146 -0
  145. package/dist/parsers/pandoc-factory.js.map +1 -0
  146. package/dist/parsers/pandoc-loader.d.ts +24 -0
  147. package/dist/parsers/pandoc-loader.d.ts.map +1 -0
  148. package/dist/parsers/pandoc-loader.js +124 -0
  149. package/dist/parsers/pandoc-loader.js.map +1 -0
  150. package/dist/parsers/pandoc-parser.d.ts +27 -0
  151. package/dist/parsers/pandoc-parser.d.ts.map +1 -0
  152. package/dist/parsers/pandoc-parser.js +3 -0
  153. package/dist/parsers/pandoc-parser.js.map +1 -0
  154. package/dist/styles/default.css +125 -0
  155. package/dist/styles/headers.css +146 -0
  156. package/dist/styles/highlight.css +171 -0
  157. package/dist/tracking/field-tracker.d.ts +206 -0
  158. package/dist/tracking/field-tracker.d.ts.map +1 -0
  159. package/dist/tracking/field-tracker.js +247 -0
  160. package/dist/tracking/field-tracker.js.map +1 -0
  161. package/dist/types.d.ts +186 -0
  162. package/dist/types.d.ts.map +1 -0
  163. package/dist/types.js +33 -0
  164. package/dist/types.js.map +1 -0
  165. package/dist/utils/logger.d.ts +107 -0
  166. package/dist/utils/logger.d.ts.map +1 -0
  167. package/dist/utils/logger.js +122 -0
  168. package/dist/utils/logger.js.map +1 -0
  169. package/dist/web/bundle-standalone.js +28 -0
  170. package/dist/web/bundle.js +17 -0
  171. package/dist/web/index.html +1465 -0
  172. package/dist/web/legal-markdown.umd.min.js +2 -0
  173. package/dist/web/standalone.html +390 -0
  174. package/dist/web/styles.css +874 -0
  175. package/package.json +118 -0
@@ -0,0 +1,378 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Mixin Processing Module for Legal Markdown Documents
4
+ *
5
+ * This module provides comprehensive mixin processing functionality for Legal Markdown
6
+ * documents, supporting variable substitution, helper functions, conditional logic,
7
+ * and nested value access. It integrates with the field tracking system to monitor
8
+ * variable usage and provides robust error handling for complex document templates.
9
+ *
10
+ * Features:
11
+ * - Variable substitution syntax: {{variable}}
12
+ * - Helper function calls: {{helperName(arg1, arg2)}}
13
+ * - Conditional mixins: {{condition ? trueValue : falseValue}}
14
+ * - Nested metadata access with dot notation
15
+ * - Array access with bracket notation: {{parties[0].name}}
16
+ * - Recursive mixin processing for nested substitutions
17
+ * - Field tracking integration for highlighting and validation
18
+ * - Special value handling (@today, booleans, numbers, strings)
19
+ * - Graceful error handling and fallback behavior
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { processMixins } from './mixin-processor';
24
+ *
25
+ * const content = `
26
+ * This agreement is between {{client.name}} and {{provider.name}}.
27
+ * {{confidentiality ? "This includes confidentiality provisions." : ""}}
28
+ * Total amount: {{formatCurrency(contract.amount, "USD")}}
29
+ * Generated on: {{formatDate(@today, "long")}}
30
+ * `;
31
+ *
32
+ * const metadata = {
33
+ * client: { name: "Acme Corp" },
34
+ * provider: { name: "Service Ltd" },
35
+ * confidentiality: true,
36
+ * contract: { amount: 25000 }
37
+ * };
38
+ *
39
+ * const processed = processMixins(content, metadata);
40
+ * console.log(processed);
41
+ * // Output:
42
+ * // This agreement is between Acme Corp and Service Ltd.
43
+ * // This includes confidentiality provisions.
44
+ * // Total amount: $25,000.00
45
+ * // Generated on: January 15, 2024
46
+ * ```
47
+ */
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.processMixins = processMixins;
50
+ const field_tracker_1 = require("../../tracking/field-tracker");
51
+ const helpers_1 = require("../../helpers");
52
+ const template_loops_1 = require("../../extensions/template-loops");
53
+ /**
54
+ * Escapes HTML attribute values to prevent breaking HTML structure
55
+ * @param value - The value to escape
56
+ * @returns Escaped value safe for HTML attributes
57
+ */
58
+ function escapeHtmlAttribute(value) {
59
+ return value
60
+ .replace(/&/g, '&')
61
+ .replace(/"/g, '"')
62
+ .replace(/'/g, ''')
63
+ .replace(/</g, '&lt;')
64
+ .replace(/>/g, '&gt;');
65
+ }
66
+ /**
67
+ * Processes mixin references in legal documents
68
+ *
69
+ * This is the main function that processes mixin references using the {{variable}}
70
+ * syntax. It supports variable substitution, helper functions, conditional logic,
71
+ * and integrates with field tracking for document validation and highlighting.
72
+ *
73
+ * @param {string} content - The document content containing mixin references
74
+ * @param {Record<string, any>} metadata - Document metadata with variable values
75
+ * @param {LegalMarkdownOptions} [options={}] - Processing options
76
+ * @returns {string} Processed content with mixins resolved
77
+ * @example
78
+ * ```typescript
79
+ * // Basic variable substitution
80
+ * const content1 = "Hello {{user.name}}, welcome to {{company.name}}!";
81
+ * const metadata1 = {
82
+ * user: { name: "John" },
83
+ * company: { name: "Acme Corp" }
84
+ * };
85
+ * const result1 = processMixins(content1, metadata1);
86
+ * // Output: "Hello John, welcome to Acme Corp!"
87
+ *
88
+ * // Helper function usage
89
+ * const content2 = "Today is {{formatDate(@today, 'long')}}";
90
+ * const result2 = processMixins(content2, {});
91
+ * // Output: "Today is January 15, 2024"
92
+ *
93
+ * // Conditional mixins
94
+ * const content3 = "{{premium ? 'Premium features enabled' : 'Standard features'}}";
95
+ * const metadata3 = { premium: true };
96
+ * const result3 = processMixins(content3, metadata3);
97
+ * // Output: "Premium features enabled"
98
+ *
99
+ * // Array access
100
+ * const content4 = "Primary contact: {{contacts[0].name}} ({{contacts[0].email}})";
101
+ * const metadata4 = {
102
+ * contacts: [
103
+ * { name: "Jane Doe", email: "jane@example.com" }
104
+ * ]
105
+ * };
106
+ * const result4 = processMixins(content4, metadata4);
107
+ * // Output: "Primary contact: Jane Doe (jane@example.com)"
108
+ * ```
109
+ */
110
+ function processMixins(content, metadata, options = {}) {
111
+ if (options.noMixins) {
112
+ return content;
113
+ }
114
+ // Regular expression to match {{variable}} patterns
115
+ const mixinPattern = /\{\{([^}]+)\}\}/g;
116
+ /**
117
+ * Resolves a dot-notation path in an object, with support for array indices
118
+ *
119
+ * @private
120
+ * @param {any} obj - The object to traverse
121
+ * @param {string} path - Dot-notation path with optional array indices
122
+ * @returns {any} The resolved value or undefined if not found
123
+ * @example
124
+ * ```typescript
125
+ * const obj = {
126
+ * parties: [
127
+ * { name: "Company A", contact: { email: "a@example.com" } },
128
+ * { name: "Company B", contact: { email: "b@example.com" } }
129
+ * ]
130
+ * };
131
+ *
132
+ * console.log(resolvePath(obj, "parties[0].name")); // "Company A"
133
+ * console.log(resolvePath(obj, "parties[1].contact.email")); // "b@example.com"
134
+ * ```
135
+ */
136
+ function resolvePath(obj, path) {
137
+ return path.split('.').reduce((current, part) => {
138
+ // Handle array indices like parties.0.name
139
+ const match = part.match(/^(\w+)\[(\d+)\]$/);
140
+ if (match) {
141
+ const [, key, index] = match;
142
+ return current?.[key]?.[parseInt(index, 10)];
143
+ }
144
+ return current?.[part];
145
+ }, obj);
146
+ }
147
+ /**
148
+ * Evaluates a helper function expression with arguments
149
+ *
150
+ * @private
151
+ * @param {string} expression - The helper function expression (e.g., "formatDate(@today, 'long')")
152
+ * @param {Record<string, any>} metadata - Metadata context for argument resolution
153
+ * @returns {any} The result of the helper function call, or undefined if invalid
154
+ * @example
155
+ * ```typescript
156
+ * const result1 = evaluateHelperExpression("formatDate(@today, 'long')", {});
157
+ * const result2 = evaluateHelperExpression("formatCurrency(amount, 'USD')", { amount: 1500 });
158
+ * ```
159
+ */
160
+ function evaluateHelperExpression(expression, metadata) {
161
+ try {
162
+ // Parse helper function call: helperName(arg1, arg2, ...)
163
+ const match = expression.match(/^(\w+)\((.*)\)$/);
164
+ if (!match)
165
+ return undefined;
166
+ const [, helperName, argsString] = match;
167
+ const helper = helpers_1.helpers[helperName];
168
+ if (!helper || typeof helper !== 'function') {
169
+ return undefined;
170
+ }
171
+ // Parse arguments
172
+ const args = parseArguments(argsString, metadata);
173
+ // Call the helper function
174
+ return helper(...args);
175
+ }
176
+ catch (error) {
177
+ console.warn(`Error evaluating helper expression: ${expression}`, error);
178
+ return undefined;
179
+ }
180
+ }
181
+ /**
182
+ * Parses comma-separated arguments from a helper function call
183
+ *
184
+ * @private
185
+ * @param {string} argsString - The arguments string to parse
186
+ * @param {Record<string, any>} metadata - Metadata context for variable resolution
187
+ * @returns {any[]} Array of parsed arguments
188
+ * @example
189
+ * ```typescript
190
+ * const args = parseArguments("'USD', amount, true", { amount: 1500 });
191
+ * // Returns: ["USD", 1500, true]
192
+ * ```
193
+ */
194
+ function parseArguments(argsString, metadata) {
195
+ if (!argsString.trim())
196
+ return [];
197
+ // Simple argument parsing - split by comma but handle quoted strings
198
+ const args = [];
199
+ let current = '';
200
+ let inQuotes = false;
201
+ let quoteChar = '';
202
+ for (let i = 0; i < argsString.length; i++) {
203
+ const char = argsString[i];
204
+ if (!inQuotes && (char === '"' || char === "'")) {
205
+ inQuotes = true;
206
+ quoteChar = char;
207
+ continue;
208
+ }
209
+ if (inQuotes && char === quoteChar) {
210
+ inQuotes = false;
211
+ quoteChar = '';
212
+ continue;
213
+ }
214
+ if (!inQuotes && char === ',') {
215
+ args.push(parseArgument(current.trim(), metadata));
216
+ current = '';
217
+ continue;
218
+ }
219
+ current += char;
220
+ }
221
+ if (current.trim()) {
222
+ args.push(parseArgument(current.trim(), metadata));
223
+ }
224
+ return args;
225
+ }
226
+ /**
227
+ * Parses a single argument, handling different data types and special values
228
+ *
229
+ * @private
230
+ * @param {string} arg - The argument string to parse
231
+ * @param {Record<string, any>} metadata - Metadata context for variable resolution
232
+ * @returns {any} The parsed argument value
233
+ * @example
234
+ * ```typescript
235
+ * console.log(parseArgument("'hello'", {})); // "hello"
236
+ * console.log(parseArgument("123", {})); // 123
237
+ * console.log(parseArgument("true", {})); // true
238
+ * console.log(parseArgument("@today", {})); // Date object
239
+ * console.log(parseArgument("user.name", { user: { name: "John" } })); // "John"
240
+ * ```
241
+ */
242
+ function parseArgument(arg, metadata) {
243
+ // Handle quoted strings
244
+ if ((arg.startsWith('"') && arg.endsWith('"')) || (arg.startsWith("'") && arg.endsWith("'"))) {
245
+ return arg.slice(1, -1);
246
+ }
247
+ // Handle numbers
248
+ if (/^-?\d+(\.\d+)?$/.test(arg)) {
249
+ return parseFloat(arg);
250
+ }
251
+ // Handle booleans
252
+ if (arg === 'true')
253
+ return true;
254
+ if (arg === 'false')
255
+ return false;
256
+ // Handle null/undefined
257
+ if (arg === 'null')
258
+ return null;
259
+ if (arg === 'undefined')
260
+ return undefined;
261
+ // Handle @today special value
262
+ if (arg === '@today') {
263
+ return new Date();
264
+ }
265
+ // Handle variable references
266
+ return resolvePath(metadata, arg);
267
+ }
268
+ /**
269
+ * Recursively replaces mixins in text with their resolved values
270
+ *
271
+ * @private
272
+ * @param {string} text - The text containing mixins to replace
273
+ * @param {number} [depth=0] - Current recursion depth to prevent infinite loops
274
+ * @returns {string} Text with mixins replaced by their values
275
+ * @example
276
+ * ```typescript
277
+ * const text = "Hello {{user.name}}, {{greeting ? 'Good morning' : 'Hello'}}";
278
+ * const result = replaceMixins(text, 0);
279
+ * // Processes all mixins and returns resolved text
280
+ * ```
281
+ */
282
+ function replaceMixins(text, depth = 0) {
283
+ // Prevent infinite recursion
284
+ if (depth > 10) {
285
+ return text;
286
+ }
287
+ return text.replace(mixinPattern, (match, variable) => {
288
+ const trimmedVar = variable.trim();
289
+ // Check if it's a helper function call
290
+ if (trimmedVar.includes('(') && trimmedVar.includes(')')) {
291
+ const result = evaluateHelperExpression(trimmedVar, metadata);
292
+ if (result !== undefined) {
293
+ // Track field with helper
294
+ field_tracker_1.fieldTracker.trackField(trimmedVar, {
295
+ value: result,
296
+ hasLogic: true,
297
+ mixinUsed: 'helper',
298
+ });
299
+ if (options.enableFieldTracking) {
300
+ return `<span class="highlight"><span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${String(result)}</span></span>`;
301
+ }
302
+ return String(result);
303
+ }
304
+ // Helper failed - treat as missing value
305
+ if (options.enableFieldTracking) {
306
+ return `<span class="highlight"><span class="missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span></span>`;
307
+ }
308
+ return `{{${trimmedVar}}}`;
309
+ }
310
+ // Check if it's a conditional mixin
311
+ if (trimmedVar.includes('?')) {
312
+ const questionIndex = trimmedVar.indexOf('?');
313
+ const colonIndex = trimmedVar.indexOf(':', questionIndex);
314
+ if (colonIndex !== -1) {
315
+ const condition = trimmedVar.substring(0, questionIndex).trim();
316
+ const truePart = trimmedVar.substring(questionIndex + 1, colonIndex).trim();
317
+ const falsePart = trimmedVar.substring(colonIndex + 1).trim();
318
+ const conditionValue = resolvePath(metadata, condition);
319
+ const selectedPart = conditionValue ? truePart : falsePart;
320
+ // Track field with logic
321
+ field_tracker_1.fieldTracker.trackField(condition, {
322
+ value: conditionValue,
323
+ hasLogic: true,
324
+ mixinUsed: 'conditional',
325
+ });
326
+ if (selectedPart) {
327
+ const processedPart = replaceMixins(selectedPart, depth + 1);
328
+ if (options.enableFieldTracking) {
329
+ return `<span class="highlight"><span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${processedPart}</span></span>`;
330
+ }
331
+ return processedPart;
332
+ }
333
+ }
334
+ if (options.enableFieldTracking) {
335
+ return `<span class="highlight"><span class="missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span></span>`;
336
+ }
337
+ return `{{${trimmedVar}}}`;
338
+ }
339
+ // Regular variable substitution
340
+ const value = resolvePath(metadata, trimmedVar);
341
+ if (value === undefined || value === null) {
342
+ // Track empty field
343
+ field_tracker_1.fieldTracker.trackField(trimmedVar, {
344
+ value: undefined,
345
+ hasLogic: false,
346
+ });
347
+ // Return wrapped missing value or original mixin
348
+ if (options.enableFieldTracking) {
349
+ return `<span class="missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span>`;
350
+ }
351
+ return `{{${trimmedVar}}}`;
352
+ }
353
+ // Track filled field
354
+ field_tracker_1.fieldTracker.trackField(trimmedVar, {
355
+ value: value,
356
+ hasLogic: false,
357
+ });
358
+ // Convert value to string
359
+ const stringValue = String(value);
360
+ // Check if the result contains more mixins (nested mixins)
361
+ if (mixinPattern.test(stringValue)) {
362
+ const nestedResult = replaceMixins(stringValue, depth + 1);
363
+ if (options.enableFieldTracking) {
364
+ return `<span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${nestedResult}</span>`;
365
+ }
366
+ return nestedResult;
367
+ }
368
+ if (options.enableFieldTracking) {
369
+ return `<span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${stringValue}</span>`;
370
+ }
371
+ return stringValue;
372
+ });
373
+ }
374
+ // First process template loops, then regular mixins
375
+ const loopProcessedContent = (0, template_loops_1.processTemplateLoops)(content, metadata, undefined, options.enableFieldTracking);
376
+ return replaceMixins(loopProcessedContent);
377
+ }
378
+ //# sourceMappingURL=mixin-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mixin-processor.js","sourceRoot":"","sources":["../../../src/core/processors/mixin-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @fileoverview Cross-Reference Processing Module for Legal Markdown Documents
3
+ *
4
+ * This module provides functionality to process cross-references in Legal Markdown
5
+ * documents, replacing reference placeholders with actual values from metadata.
6
+ * It supports various formatting options including date formatting, currency
7
+ * formatting, and nested metadata access through dot notation.
8
+ *
9
+ * Features:
10
+ * - Cross-reference syntax: |reference_key|
11
+ * - Date reference processing with @today support
12
+ * - Automatic currency formatting for amount fields
13
+ * - Nested metadata value access with dot notation
14
+ * - Type-aware value formatting (dates, numbers, strings)
15
+ * - Fallback to original reference if value not found
16
+ * - Integration with date-processor for date handling
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { processCrossReferences } from './reference-processor';
21
+ *
22
+ * const content = `
23
+ * This agreement is between |client.name| and |provider.name|.
24
+ * The total amount is |contract.amount| due on |contract.due_date|.
25
+ * Document generated on |@today|.
26
+ * `;
27
+ *
28
+ * const metadata = {
29
+ * client: { name: "Acme Corp" },
30
+ * provider: { name: "Service Ltd" },
31
+ * contract: {
32
+ * amount: 25000,
33
+ * due_date: new Date("2024-12-31")
34
+ * },
35
+ * payment_currency: "USD"
36
+ * };
37
+ *
38
+ * const processed = processCrossReferences(content, metadata);
39
+ * console.log(processed);
40
+ * // Output:
41
+ * // This agreement is between Acme Corp and Service Ltd.
42
+ * // The total amount is $25,000.00 due on 2024-12-31.
43
+ * // Document generated on 2024-01-15.
44
+ * ```
45
+ */
46
+ /**
47
+ * Processes cross-references in a LegalMarkdown document
48
+ *
49
+ * This is the main function that processes cross-references using the |reference_key|
50
+ * syntax. It first processes date references, then handles regular cross-references
51
+ * with automatic formatting based on value type and field names.
52
+ *
53
+ * @param {string} content - The document content containing cross-references
54
+ * @param {Record<string, any>} metadata - Document metadata with reference values
55
+ * @returns {string} Processed content with references replaced by their values
56
+ * @example
57
+ * ```typescript
58
+ * // Basic reference processing
59
+ * const content = "Payment due: |payment.amount| on |payment.date|";
60
+ * const metadata = {
61
+ * payment: {
62
+ * amount: 1500,
63
+ * date: new Date("2024-03-15")
64
+ * },
65
+ * payment_currency: "EUR"
66
+ * };
67
+ *
68
+ * const result = processCrossReferences(content, metadata);
69
+ * // Output: "Payment due: €1,500.00 on 2024-03-15"
70
+ *
71
+ * // Nested reference access
72
+ * const content2 = "Contact: |client.contact.email| (|client.contact.phone|)";
73
+ * const metadata2 = {
74
+ * client: {
75
+ * contact: {
76
+ * email: "info@client.com",
77
+ * phone: "+1-555-0123"
78
+ * }
79
+ * }
80
+ * };
81
+ *
82
+ * const result2 = processCrossReferences(content2, metadata2);
83
+ * // Output: "Contact: info@client.com (+1-555-0123)"
84
+ * ```
85
+ */
86
+ export declare function processCrossReferences(content: string, metadata: Record<string, any>): string;
87
+ /**
88
+ * Processes special reference formats like dates and currency amounts
89
+ *
90
+ * Applies appropriate formatting to reference values based on their type and
91
+ * optional format specifiers. Handles dates, currency amounts, and falls back
92
+ * to string conversion for other types.
93
+ *
94
+ * @param {any} value - The reference value to format
95
+ * @param {string} [format] - Optional format specifier (e.g., "currency:USD:en-US")
96
+ * @returns {string} Formatted value as string
97
+ * @example
98
+ * ```typescript
99
+ * // Date formatting
100
+ * const date = new Date("2024-03-15");
101
+ * console.log(formatReferenceValue(date)); // "2024-03-15"
102
+ * console.log(formatReferenceValue(date, "long")); // "March 15, 2024"
103
+ * console.log(formatReferenceValue(date, "short")); // "3/15/2024"
104
+ *
105
+ * // Currency formatting
106
+ * console.log(formatReferenceValue(1500, "currency:USD")); // "$1,500.00"
107
+ * console.log(formatReferenceValue(1500, "currency:EUR:de-DE")); // "1.500,00 €"
108
+ *
109
+ * // Default string conversion
110
+ * console.log(formatReferenceValue("Hello World")); // "Hello World"
111
+ * console.log(formatReferenceValue(12345)); // "12345"
112
+ * ```
113
+ */
114
+ export declare function formatReferenceValue(value: any, format?: string): string;
115
+ //# sourceMappingURL=reference-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference-processor.d.ts","sourceRoot":"","sources":["../../../src/core/processors/reference-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CA4B7F;AA6CD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAgBxE"}