@dotit/core 1.0.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -0
  3. package/dist/aliases.d.ts +1 -0
  4. package/dist/aliases.js +8 -0
  5. package/dist/ask.d.ts +7 -0
  6. package/dist/ask.js +55 -0
  7. package/dist/browser.d.ts +12 -0
  8. package/dist/browser.js +32 -0
  9. package/dist/diff.d.ts +17 -0
  10. package/dist/diff.js +179 -0
  11. package/dist/document-css.d.ts +1 -0
  12. package/dist/document-css.js +290 -0
  13. package/dist/executor.d.ts +40 -0
  14. package/dist/executor.js +501 -0
  15. package/dist/history.d.ts +10 -0
  16. package/dist/history.js +297 -0
  17. package/dist/html-to-it.d.ts +1 -0
  18. package/dist/html-to-it.js +288 -0
  19. package/dist/index-builder.d.ts +62 -0
  20. package/dist/index-builder.js +228 -0
  21. package/dist/index.d.ts +39 -0
  22. package/dist/index.js +94 -0
  23. package/dist/language-registry.d.ts +39 -0
  24. package/dist/language-registry.js +530 -0
  25. package/dist/markdown.d.ts +1 -0
  26. package/dist/markdown.js +123 -0
  27. package/dist/merge.d.ts +6 -0
  28. package/dist/merge.js +255 -0
  29. package/dist/parser.d.ts +29 -0
  30. package/dist/parser.js +1562 -0
  31. package/dist/query.d.ts +32 -0
  32. package/dist/query.js +293 -0
  33. package/dist/renderer.d.ts +16 -0
  34. package/dist/renderer.js +1286 -0
  35. package/dist/schema.d.ts +47 -0
  36. package/dist/schema.js +574 -0
  37. package/dist/source.d.ts +3 -0
  38. package/dist/source.js +223 -0
  39. package/dist/theme.d.ts +49 -0
  40. package/dist/theme.js +113 -0
  41. package/dist/themes/corporate.json +86 -0
  42. package/dist/themes/dark.json +64 -0
  43. package/dist/themes/editorial.json +54 -0
  44. package/dist/themes/legal.json +57 -0
  45. package/dist/themes/minimal.json +50 -0
  46. package/dist/themes/print.json +54 -0
  47. package/dist/themes/technical.json +59 -0
  48. package/dist/themes/warm.json +53 -0
  49. package/dist/trust.d.ts +66 -0
  50. package/dist/trust.js +200 -0
  51. package/dist/types.d.ts +234 -0
  52. package/dist/types.js +19 -0
  53. package/dist/utils.d.ts +2 -0
  54. package/dist/utils.js +13 -0
  55. package/dist/validate.d.ts +13 -0
  56. package/dist/validate.js +711 -0
  57. package/dist/workflow.d.ts +18 -0
  58. package/dist/workflow.js +160 -0
  59. package/package.json +51 -0
package/dist/merge.js ADDED
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeData = mergeData;
4
+ exports.parseAndMerge = parseAndMerge;
5
+ const parser_1 = require("./parser");
6
+ const RUNTIME_VARIABLES = new Set(["page", "pages"]);
7
+ const SYSTEM_VARIABLES = new Set(["timestamp", "date", "year"]);
8
+ const DANGEROUS_PATH_KEYS = new Set(["__proto__", "constructor", "prototype"]);
9
+ const MAX_PATH_DEPTH = 20;
10
+ function getByPath(obj, path) {
11
+ const keys = path.split(".");
12
+ if (keys.length > MAX_PATH_DEPTH)
13
+ return undefined;
14
+ return keys.reduce((current, key) => {
15
+ if (current === null || current === undefined)
16
+ return undefined;
17
+ if (DANGEROUS_PATH_KEYS.has(key))
18
+ return undefined;
19
+ if (Array.isArray(current)) {
20
+ const idx = Number(key);
21
+ if (!isNaN(idx) && idx >= 0 && idx < current.length)
22
+ return current[idx];
23
+ return undefined;
24
+ }
25
+ if (typeof current === "object") {
26
+ return Object.prototype.hasOwnProperty.call(current, key)
27
+ ? current[key]
28
+ : undefined;
29
+ }
30
+ return undefined;
31
+ }, obj);
32
+ }
33
+ function getSystemVariable(key) {
34
+ switch (key) {
35
+ case "timestamp":
36
+ return new Date().toISOString();
37
+ case "date":
38
+ return new Date().toLocaleDateString();
39
+ case "year":
40
+ return String(new Date().getFullYear());
41
+ default:
42
+ return undefined;
43
+ }
44
+ }
45
+ function resolveString(str, data, agentName) {
46
+ if (!str.includes("{{"))
47
+ return { resolved: str, hasUnresolved: false };
48
+ let hasUnresolved = false;
49
+ const resolved = str.replace(/\{\{([^}]+)\}\}/g, (match, rawPath) => {
50
+ const path = rawPath.trim();
51
+ if (path.length > 200) {
52
+ hasUnresolved = true;
53
+ return match;
54
+ }
55
+ if (RUNTIME_VARIABLES.has(path))
56
+ return match;
57
+ if (SYSTEM_VARIABLES.has(path)) {
58
+ const sysVal = getSystemVariable(path);
59
+ if (sysVal !== undefined)
60
+ return sysVal;
61
+ }
62
+ if (path === "agent") {
63
+ if (agentName)
64
+ return agentName;
65
+ hasUnresolved = true;
66
+ return match;
67
+ }
68
+ const value = getByPath(data, path);
69
+ if (value !== undefined && value !== null)
70
+ return String(value);
71
+ hasUnresolved = true;
72
+ return MISSING_MODE === "blank" ? "" : match;
73
+ });
74
+ return { resolved, hasUnresolved };
75
+ }
76
+ let MISSING_MODE = "keep";
77
+ function resolveBlock(block, data, agentName) {
78
+ const newBlock = { ...block };
79
+ let blockHasUnresolved = false;
80
+ if (newBlock.content) {
81
+ const { resolved, hasUnresolved } = resolveString(newBlock.content, data, agentName);
82
+ newBlock.content = resolved;
83
+ if (hasUnresolved)
84
+ blockHasUnresolved = true;
85
+ }
86
+ if (newBlock.originalContent) {
87
+ const { resolved } = resolveString(newBlock.originalContent, data, agentName);
88
+ newBlock.originalContent = resolved;
89
+ }
90
+ if (newBlock.properties) {
91
+ const newProps = {};
92
+ for (const [key, val] of Object.entries(newBlock.properties)) {
93
+ if (typeof val === "string") {
94
+ const { resolved, hasUnresolved } = resolveString(val, data, agentName);
95
+ newProps[key] = resolved;
96
+ if (hasUnresolved)
97
+ blockHasUnresolved = true;
98
+ }
99
+ else {
100
+ newProps[key] = val;
101
+ }
102
+ }
103
+ newBlock.properties = newProps;
104
+ }
105
+ if (blockHasUnresolved) {
106
+ if (!newBlock.properties)
107
+ newBlock.properties = {};
108
+ newBlock.properties.unresolved = 1;
109
+ }
110
+ if (newBlock.children) {
111
+ newBlock.children = newBlock.children.map((child) => resolveBlock(child, data, agentName));
112
+ }
113
+ if (newBlock.table) {
114
+ newBlock.table = {
115
+ headers: newBlock.table.headers?.map((h) => {
116
+ const { resolved } = resolveString(h, data, agentName);
117
+ return resolved;
118
+ }),
119
+ rows: newBlock.table.rows.map((row) => row.map((cell) => {
120
+ const { resolved } = resolveString(cell, data, agentName);
121
+ return resolved;
122
+ })),
123
+ };
124
+ }
125
+ if (newBlock.inline) {
126
+ newBlock.inline = newBlock.inline.map((node) => {
127
+ const newNode = { ...node };
128
+ if ("value" in newNode && typeof newNode.value === "string") {
129
+ const { resolved } = resolveString(newNode.value, data, agentName);
130
+ newNode.value = resolved;
131
+ }
132
+ if ("href" in newNode && typeof newNode.href === "string") {
133
+ const { resolved } = resolveString(newNode.href, data, agentName);
134
+ newNode.href = resolved;
135
+ }
136
+ return newNode;
137
+ });
138
+ }
139
+ return newBlock;
140
+ }
141
+ function singularize(name) {
142
+ if (name.endsWith("ies"))
143
+ return name.slice(0, -3) + "y";
144
+ if (name.endsWith("s"))
145
+ return name.slice(0, -1);
146
+ return name;
147
+ }
148
+ function expandEachRows(blocks, data, agentName) {
149
+ const result = [];
150
+ for (const block of blocks) {
151
+ if (block.type !== "table" ||
152
+ !block.table?.headers ||
153
+ block.table.headers.length === 0) {
154
+ if (block.children && block.children.length > 0) {
155
+ result.push({
156
+ ...block,
157
+ children: expandEachRows(block.children, data, agentName),
158
+ });
159
+ }
160
+ else {
161
+ result.push(block);
162
+ }
163
+ continue;
164
+ }
165
+ const headers = block.table.headers;
166
+ const lastHeader = headers[headers.length - 1].trim();
167
+ const eachMatch = lastHeader.match(/^each:\s*(.+)$/i);
168
+ if (!eachMatch) {
169
+ result.push(block);
170
+ continue;
171
+ }
172
+ const eachDirective = eachMatch[1].trim();
173
+ let arrayName;
174
+ let loopVar;
175
+ if (eachDirective.includes(" as ")) {
176
+ const parts = eachDirective.split(" as ");
177
+ arrayName = parts[0].trim();
178
+ loopVar = parts[1].trim();
179
+ }
180
+ else {
181
+ arrayName = eachDirective;
182
+ loopVar = singularize(arrayName);
183
+ }
184
+ const items = getByPath(data, arrayName);
185
+ const cleanHeaders = headers.slice(0, -1);
186
+ if (!Array.isArray(items) || items.length === 0) {
187
+ result.push({
188
+ ...block,
189
+ table: {
190
+ headers: cleanHeaders,
191
+ rows: [],
192
+ },
193
+ });
194
+ continue;
195
+ }
196
+ const templateRow = block.table.rows[0];
197
+ if (!templateRow) {
198
+ result.push({
199
+ ...block,
200
+ table: {
201
+ headers: cleanHeaders,
202
+ rows: [],
203
+ },
204
+ });
205
+ continue;
206
+ }
207
+ const expandedRows = [];
208
+ for (const item of items) {
209
+ const itemData = { ...data, [loopVar]: item };
210
+ const expandedRow = templateRow.map((cell) => {
211
+ const { resolved } = resolveString(cell, itemData, agentName);
212
+ return resolved;
213
+ });
214
+ expandedRows.push(expandedRow);
215
+ }
216
+ result.push({
217
+ ...block,
218
+ table: {
219
+ headers: cleanHeaders,
220
+ rows: expandedRows,
221
+ },
222
+ });
223
+ }
224
+ return result;
225
+ }
226
+ function mergeData(template, data, options) {
227
+ if (!template || !template.blocks)
228
+ return template;
229
+ if (!data || typeof data !== "object")
230
+ return template;
231
+ MISSING_MODE = options?.missing ?? "keep";
232
+ const agentName = template.metadata?.agent;
233
+ const expandedBlocks = expandEachRows(template.blocks, data, agentName);
234
+ const newBlocks = expandedBlocks.map((block) => resolveBlock(block, data, agentName));
235
+ let newMetadata = template.metadata ? { ...template.metadata } : undefined;
236
+ if (newMetadata) {
237
+ if (newMetadata.title) {
238
+ const { resolved } = resolveString(newMetadata.title, data, agentName);
239
+ newMetadata.title = resolved;
240
+ }
241
+ if (newMetadata.summary) {
242
+ const { resolved } = resolveString(newMetadata.summary, data, agentName);
243
+ newMetadata.summary = resolved;
244
+ }
245
+ }
246
+ return {
247
+ ...template,
248
+ blocks: newBlocks,
249
+ metadata: newMetadata,
250
+ };
251
+ }
252
+ function parseAndMerge(source, data, options) {
253
+ const template = (0, parser_1.parseIntentText)(source);
254
+ return mergeData(template, data, options);
255
+ }
@@ -0,0 +1,29 @@
1
+ import { IntentDocument, ParseOptions } from "./types";
2
+ export declare function _resetIdCounter(): void;
3
+ export declare function detectHistoryBoundary(lines: string[]): number;
4
+ export declare function parseIntentText(fileContent: string, options?: ParseOptions): IntentDocument;
5
+ export interface SafeParseOptions {
6
+ unknownKeyword: "note" | "skip" | "throw";
7
+ maxBlocks: number;
8
+ maxLineLength: number;
9
+ strict: boolean;
10
+ }
11
+ export declare const DEFAULT_SAFE_PARSE_OPTIONS: SafeParseOptions;
12
+ export interface ParseWarning {
13
+ line: number;
14
+ message: string;
15
+ code: string;
16
+ original: string;
17
+ }
18
+ export interface ParseError {
19
+ line: number;
20
+ message: string;
21
+ code: string;
22
+ original: string;
23
+ }
24
+ export interface SafeParseResult {
25
+ document: IntentDocument;
26
+ warnings: ParseWarning[];
27
+ errors: ParseError[];
28
+ }
29
+ export declare function parseIntentTextSafe(source: string, options?: Partial<SafeParseOptions>): SafeParseResult;