@semanticintent/recall 0.2.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/README.md ADDED
@@ -0,0 +1,279 @@
1
+ # RECALL
2
+
3
+ **A declarative web interface language with COBOL-inspired syntax.**
4
+
5
+ ```cobol
6
+ IDENTIFICATION DIVISION.
7
+ PROGRAM-ID. MY-SITE.
8
+ PAGE-TITLE. "Hello, World.".
9
+
10
+ DATA DIVISION.
11
+ WORKING-STORAGE SECTION.
12
+ 01 HERO-HEAD PIC X(40) VALUE "STILL HERE.".
13
+ 01 HERO-BODY PIC X(200) VALUE "Built to last.".
14
+
15
+ PROCEDURE DIVISION.
16
+
17
+ RENDER-HERO.
18
+ DISPLAY SECTION ID "hero"
19
+ WITH LAYOUT CENTERED
20
+ WITH PADDING LARGE.
21
+ DISPLAY HEADING-1 HERO-HEAD.
22
+ DISPLAY PARAGRAPH HERO-BODY.
23
+ STOP SECTION.
24
+
25
+ STOP RUN.
26
+ ```
27
+
28
+ ```sh
29
+ recall compile my-site.rcl
30
+ # → my-site.html (self-contained, zero dependencies)
31
+ ```
32
+
33
+ ---
34
+
35
+ ## What is RECALL?
36
+
37
+ RECALL is a compiler, not a runtime. You write `.rcl` source files in a
38
+ COBOL-inspired, division-based syntax. The compiler produces a single,
39
+ self-contained HTML file — inline CSS, no external dependencies, no build
40
+ step to run the result.
41
+
42
+ The guiding principle: **the source is the artifact.**
43
+
44
+ Every compiled `.html` file embeds its original `.rcl` source in an HTML
45
+ comment block at the top of the output. View source on any RECALL page and
46
+ you see COBOL divisions.
47
+
48
+ RECALL is not:
49
+ - A COBOL runtime or interpreter
50
+ - A wrapper around React, Vue, or any JS framework
51
+ - A templating engine on top of HTML
52
+ - A joke
53
+
54
+ RECALL is:
55
+ - A domain-specific language for web interfaces
56
+ - Inspired by COBOL syntax — verbose, English-like, division-based
57
+ - A transpiler that produces vanilla HTML + inline CSS
58
+ - A statement about longevity
59
+
60
+ ---
61
+
62
+ ## Install
63
+
64
+ ```sh
65
+ npm install -g @semanticintent/recall
66
+ ```
67
+
68
+ Or use it as a library:
69
+
70
+ ```sh
71
+ npm install @semanticintent/recall
72
+ ```
73
+
74
+ ---
75
+
76
+ ## CLI
77
+
78
+ ```sh
79
+ # Compile a .rcl file to HTML
80
+ recall compile my-site.rcl
81
+
82
+ # Compile to a specific output directory
83
+ recall compile my-site.rcl --out dist/
84
+
85
+ # Check a file for errors without compiling
86
+ recall check my-site.rcl
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Language Structure
92
+
93
+ Every RECALL program has four divisions:
94
+
95
+ ```cobol
96
+ IDENTIFICATION DIVISION. ← who this is
97
+ ENVIRONMENT DIVISION. ← how it looks (theme, fonts, palette)
98
+ DATA DIVISION. ← what it holds (variables, lists)
99
+ PROCEDURE DIVISION. ← what it renders
100
+ ```
101
+
102
+ ### IDENTIFICATION DIVISION
103
+
104
+ ```cobol
105
+ IDENTIFICATION DIVISION.
106
+ PROGRAM-ID. MY-SITE.
107
+ AUTHOR. SEMANTICINTENT.
108
+ DATE-WRITTEN. 2026-04-03.
109
+ PAGE-TITLE. "My Site".
110
+ DESCRIPTION. "A site about things.".
111
+ FAVICON. "/favicon.ico".
112
+ ```
113
+
114
+ ### ENVIRONMENT DIVISION
115
+
116
+ ```cobol
117
+ ENVIRONMENT DIVISION.
118
+ CONFIGURATION SECTION.
119
+ VIEWPORT RESPONSIVE.
120
+ COLOR-MODE DARK.
121
+ FONT-PRIMARY "IBM Plex Mono".
122
+ FONT-SECONDARY "IBM Plex Sans".
123
+
124
+ PALETTE SECTION.
125
+ 01 COLOR-ACCENT PIC X(7) VALUE "#00FF41".
126
+ 01 COLOR-BG PIC X(7) VALUE "#080808".
127
+ 01 COLOR-TEXT PIC X(7) VALUE "#E0E0E0".
128
+ 01 COLOR-MUTED PIC X(7) VALUE "#555555".
129
+ 01 COLOR-BORDER PIC X(7) VALUE "#1A1A1A".
130
+ ```
131
+
132
+ ### DATA DIVISION
133
+
134
+ ```cobol
135
+ DATA DIVISION.
136
+ WORKING-STORAGE SECTION.
137
+ 01 PAGE-HEADING PIC X(60) VALUE "Hello, World.".
138
+ 01 PAGE-BODY PIC X(200) VALUE "Welcome to RECALL.".
139
+
140
+ ITEMS SECTION.
141
+ 01 NAV-ITEMS.
142
+ 05 NAV-ITEM-1 PIC X(20) VALUE "HOME".
143
+ 05 NAV-ITEM-1-HREF PIC X(80) VALUE "/".
144
+ 05 NAV-ITEM-2 PIC X(20) VALUE "ABOUT".
145
+ 05 NAV-ITEM-2-HREF PIC X(80) VALUE "/about".
146
+ ```
147
+
148
+ ### PROCEDURE DIVISION
149
+
150
+ ```cobol
151
+ PROCEDURE DIVISION.
152
+
153
+ RENDER-NAV.
154
+ DISPLAY NAVIGATION USING NAV-ITEMS
155
+ WITH STICKY YES
156
+ WITH LOGO "MY SITE".
157
+
158
+ RENDER-HERO.
159
+ DISPLAY SECTION ID "hero"
160
+ WITH LAYOUT CENTERED
161
+ WITH PADDING LARGE.
162
+ DISPLAY HEADING-1 PAGE-HEADING
163
+ WITH STYLE MONO.
164
+ DISPLAY PARAGRAPH PAGE-BODY.
165
+ DISPLAY BUTTON "Get Started"
166
+ ON-CLICK GOTO "#install"
167
+ WITH STYLE PRIMARY.
168
+ STOP SECTION.
169
+
170
+ STOP RUN.
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Elements
176
+
177
+ | Element | Description |
178
+ |---|---|
179
+ | `HEADING-1` / `HEADING-2` / `HEADING-3` | Section headings |
180
+ | `PARAGRAPH` | Body text |
181
+ | `LABEL` | Small uppercase label |
182
+ | `BUTTON` | CTA button with `ON-CLICK GOTO` |
183
+ | `LINK` | Inline hyperlink |
184
+ | `CODE-BLOCK` | Preformatted code block |
185
+ | `CARD-LIST` | Grid of cards from a data group |
186
+ | `NAVIGATION` | Site navigation with logo + links |
187
+ | `SECTION` | Layout container (`CENTERED`, `STACK`, `GRID`) |
188
+ | `FOOTER` | Page footer |
189
+ | `DIVIDER` | Horizontal rule |
190
+ | `BANNER` | Full-width announcement strip |
191
+ | `IMAGE` | Responsive image |
192
+ | `INPUT` | Text / textarea input field |
193
+
194
+ ---
195
+
196
+ ## Components (COPY)
197
+
198
+ Reuse elements across pages with `COPY FROM`:
199
+
200
+ ```cobol
201
+ * components/nav.rcl — a full .rcl file with its own DATA and PROCEDURE
202
+ ```
203
+
204
+ ```cobol
205
+ PROCEDURE DIVISION.
206
+
207
+ RENDER-NAV.
208
+ COPY FROM "components/nav.rcl".
209
+
210
+ RENDER-FOOTER.
211
+ COPY FROM "components/footer.rcl".
212
+ ```
213
+
214
+ The compiler merges the component's data into the parent's DATA division
215
+ and inlines its procedure statements at the COPY position. The output is
216
+ still one self-contained HTML file.
217
+
218
+ ---
219
+
220
+ ## Library Usage
221
+
222
+ ```ts
223
+ import { parse } from '@semanticintent/recall/parser'
224
+ import { generate } from '@semanticintent/recall/generator'
225
+ import { compile } from '@semanticintent/recall/compiler'
226
+
227
+ // Compile file → HTML file
228
+ const result = compile('my-site.rcl', 'dist/')
229
+ if (!result.ok) console.error(result.error)
230
+
231
+ // Parse source → AST
232
+ const program = parse(source)
233
+
234
+ // Generate HTML from AST
235
+ const html = generate(program, source)
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Examples
241
+
242
+ See [`examples/`](examples/) for working `.rcl` files:
243
+
244
+ - [`examples/portfolio.rcl`](examples/portfolio.rcl) — personal portfolio page
245
+ - [`examples/landing.rcl`](examples/landing.rcl) — RECALL's own landing page (written in RECALL)
246
+ - [`examples/components/nav.rcl`](examples/components/nav.rcl) — reusable nav component
247
+
248
+ ---
249
+
250
+ ## Roadmap
251
+
252
+ - [x] Four-division language structure
253
+ - [x] Full element library (16 elements)
254
+ - [x] COPY — component-based composability
255
+ - [ ] Multi-page `recall build` with project manifest
256
+ - [ ] Shared theme inheritance (`COPY PALETTE FROM "theme.rcl"`)
257
+ - [ ] Opt-in vanilla JS interactions (tabs, accordion, modal)
258
+ - [ ] Compile-time data binding from JSON / CSV
259
+
260
+ ---
261
+
262
+ ## Contributing
263
+
264
+ Pull requests welcome. Please open an issue first for significant changes.
265
+
266
+ ```sh
267
+ git clone https://github.com/semanticintent/recall
268
+ cd recall
269
+ npm install
270
+ npm test # 37 tests
271
+ npm run build # compile TypeScript
272
+ node bin/recall.js compile examples/landing.rcl
273
+ ```
274
+
275
+ ---
276
+
277
+ ## License
278
+
279
+ MIT © [semanticintent](https://github.com/semanticintent)
package/bin/recall.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/cli/index.js'
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const checkCommand: Command;
3
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,eAAO,MAAM,YAAY,SAgBrB,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { Command } from 'commander';
2
+ import { check } from '../../compiler/index.js';
3
+ export const checkCommand = new Command('check')
4
+ .argument('<file>', 'path to .rcl source file')
5
+ .description('Validate .rcl syntax without compiling')
6
+ .action((file) => {
7
+ const result = check(file);
8
+ if (result.ok) {
9
+ console.log(`\n✓ SYNTAX VALID`);
10
+ console.log(` FILE: ${result.inputPath}\n`);
11
+ }
12
+ else {
13
+ console.error(`\nRECALL SYNTAX ERRORS`);
14
+ console.error(` FILE: ${result.inputPath}\n`);
15
+ result.errors.forEach(e => console.error(` ✗ ${e}`));
16
+ console.error('');
17
+ process.exit(1);
18
+ }
19
+ });
20
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAE/C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;KAC9C,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;IAE1B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QAC/B,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,SAAS,IAAI,CAAC,CAAA;IAC9C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACvC,OAAO,CAAC,KAAK,CAAC,WAAW,MAAM,CAAC,SAAS,IAAI,CAAC,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;QACrD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const compileCommand: Command;
3
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,eAAO,MAAM,cAAc,SAiBvB,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ import { compile } from '../../compiler/index.js';
3
+ export const compileCommand = new Command('compile')
4
+ .argument('<file>', 'path to .rcl source file')
5
+ .option('--out <dir>', 'output directory (default: same as source)')
6
+ .description('Transpile a .rcl source file to a self-contained HTML file')
7
+ .action((file, options) => {
8
+ const result = compile(file, options.out);
9
+ if (result.ok) {
10
+ console.log(`\n✓ COMPILED SUCCESSFULLY`);
11
+ console.log(` SOURCE: ${result.inputPath}`);
12
+ console.log(` OUTPUT: ${result.outputPath}\n`);
13
+ }
14
+ else {
15
+ console.error(`\nRECALL COMPILATION ERROR`);
16
+ console.error(` FILE: ${result.inputPath}`);
17
+ console.error(`\n ${result.error}\n`);
18
+ process.exit(1);
19
+ }
20
+ });
21
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAEjD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;KAC9C,MAAM,CAAC,aAAa,EAAE,4CAA4C,CAAC;KACnE,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,CAAC,IAAY,EAAE,OAAyB,EAAE,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAEzC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;QACxC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;QAC5C,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,UAAU,IAAI,CAAC,CAAA;IACjD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAA;QAC3C,OAAO,CAAC,KAAK,CAAC,WAAW,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;QAC5C,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,KAAK,IAAI,CAAC,CAAA;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+ import { compileCommand } from './commands/compile.js';
3
+ import { checkCommand } from './commands/check.js';
4
+ const program = new Command();
5
+ program
6
+ .name('recall')
7
+ .description('RECALL — the source that remembers. A COBOL-inspired web interface language.')
8
+ .version('0.1.0');
9
+ program.addCommand(compileCommand);
10
+ program.addCommand(checkCommand);
11
+ program.parse();
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,8EAA8E,CAAC;KAC3F,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAA;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;AAEhC,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,14 @@
1
+ export interface CompileResult {
2
+ ok: boolean;
3
+ inputPath: string;
4
+ outputPath?: string;
5
+ error?: string;
6
+ }
7
+ export interface CheckResult {
8
+ ok: boolean;
9
+ inputPath: string;
10
+ errors: string[];
11
+ }
12
+ export declare function compile(inputPath: string, outDir?: string): CompileResult;
13
+ export declare function check(inputPath: string): CheckResult;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compiler/index.ts"],"names":[],"mappings":"AAiDA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CA4CzE;AAED,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAoCpD"}
@@ -0,0 +1,115 @@
1
+ // ─────────────────────────────────────────────────────────
2
+ // RECALL Compiler — orchestrates parse → generate
3
+ // ─────────────────────────────────────────────────────────
4
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
5
+ import { resolve, basename, dirname, join } from 'node:path';
6
+ import { parse } from '../parser/rcl.js';
7
+ import { generate } from '../generator/html.js';
8
+ // ─────────────────────────────────────────────────────────
9
+ // COPY resolution — merges component files into the AST
10
+ // ─────────────────────────────────────────────────────────
11
+ function resolveStatementsInPlace(statements, data, dir) {
12
+ let i = 0;
13
+ while (i < statements.length) {
14
+ const stmt = statements[i];
15
+ if (stmt.element === 'COPY') {
16
+ const filePath = resolve(dir, stmt.value);
17
+ const componentSource = readFileSync(filePath, 'utf-8');
18
+ const component = parse(componentSource);
19
+ // Merge component data into parent
20
+ data.workingStorage.push(...component.data.workingStorage);
21
+ data.items.push(...component.data.items);
22
+ // Inline all component procedure statements (flatten sections)
23
+ const inlined = component.procedure.sections.flatMap(s => s.statements);
24
+ statements.splice(i, 1, ...inlined);
25
+ i += inlined.length;
26
+ }
27
+ else {
28
+ // Recurse into SECTION children so COPY works inside DISPLAY SECTION too
29
+ if (stmt.children.length > 0) {
30
+ resolveStatementsInPlace(stmt.children, data, dir);
31
+ }
32
+ i++;
33
+ }
34
+ }
35
+ }
36
+ function resolveIncludes(program, dir) {
37
+ for (const section of program.procedure.sections) {
38
+ resolveStatementsInPlace(section.statements, program.data, dir);
39
+ }
40
+ }
41
+ export function compile(inputPath, outDir) {
42
+ const absInput = resolve(inputPath);
43
+ if (!existsSync(absInput)) {
44
+ return { ok: false, inputPath: absInput, error: `FILE NOT FOUND: ${absInput}` };
45
+ }
46
+ if (!absInput.endsWith('.rcl')) {
47
+ return { ok: false, inputPath: absInput, error: `NOT A RECALL SOURCE FILE. EXPECTED .rcl EXTENSION.` };
48
+ }
49
+ let source;
50
+ try {
51
+ source = readFileSync(absInput, 'utf-8');
52
+ }
53
+ catch (err) {
54
+ return { ok: false, inputPath: absInput, error: `CANNOT READ FILE: ${err.message}` };
55
+ }
56
+ let program;
57
+ try {
58
+ program = parse(source);
59
+ resolveIncludes(program, dirname(absInput));
60
+ }
61
+ catch (err) {
62
+ return { ok: false, inputPath: absInput, error: `PARSE ERROR: ${err.message}` };
63
+ }
64
+ let html;
65
+ try {
66
+ html = generate(program, source);
67
+ }
68
+ catch (err) {
69
+ return { ok: false, inputPath: absInput, error: `GENERATION ERROR: ${err.message}` };
70
+ }
71
+ const outputDir = outDir ? resolve(outDir) : dirname(absInput);
72
+ const outputName = basename(absInput, '.rcl') + '.html';
73
+ const outputPath = join(outputDir, outputName);
74
+ try {
75
+ writeFileSync(outputPath, html, 'utf-8');
76
+ }
77
+ catch (err) {
78
+ return { ok: false, inputPath: absInput, error: `CANNOT WRITE OUTPUT: ${err.message}` };
79
+ }
80
+ return { ok: true, inputPath: absInput, outputPath };
81
+ }
82
+ export function check(inputPath) {
83
+ const absInput = resolve(inputPath);
84
+ const errors = [];
85
+ if (!existsSync(absInput)) {
86
+ return { ok: false, inputPath: absInput, errors: [`FILE NOT FOUND: ${absInput}`] };
87
+ }
88
+ if (!absInput.endsWith('.rcl')) {
89
+ return { ok: false, inputPath: absInput, errors: ['NOT A RECALL SOURCE FILE. EXPECTED .rcl EXTENSION.'] };
90
+ }
91
+ let source;
92
+ try {
93
+ source = readFileSync(absInput, 'utf-8');
94
+ }
95
+ catch (err) {
96
+ return { ok: false, inputPath: absInput, errors: [`CANNOT READ FILE: ${err.message}`] };
97
+ }
98
+ try {
99
+ const program = parse(source);
100
+ if (!program.identification.programId) {
101
+ errors.push('IDENTIFICATION DIVISION: PROGRAM-ID IS REQUIRED.');
102
+ }
103
+ if (!program.identification.pageTitle) {
104
+ errors.push('IDENTIFICATION DIVISION: PAGE-TITLE IS REQUIRED.');
105
+ }
106
+ if (program.procedure.sections.length === 0) {
107
+ errors.push('PROCEDURE DIVISION: NO SECTIONS FOUND. AT LEAST ONE RENDER SECTION IS REQUIRED.');
108
+ }
109
+ }
110
+ catch (err) {
111
+ errors.push(`PARSE ERROR: ${err.message}`);
112
+ }
113
+ return { ok: errors.length === 0, inputPath: absInput, errors };
114
+ }
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compiler/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,kDAAkD;AAClD,4DAA4D;AAE5D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAG/C,4DAA4D;AAC5D,wDAAwD;AACxD,4DAA4D;AAE5D,SAAS,wBAAwB,CAC/B,UAA8B,EAC9B,IAAkB,EAClB,GAAW;IAEX,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAM,CAAC,CAAA;YAC1C,MAAM,eAAe,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YACvD,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,CAAC,CAAA;YACxC,mCAAmC;YACnC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;YAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACxC,+DAA+D;YAC/D,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;YACvE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAA;YACnC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,yEAAyE;YACzE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,wBAAwB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;YACpD,CAAC;YACD,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAiC,EAAE,GAAW;IACrE,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;QACjD,wBAAwB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACjE,CAAC;AACH,CAAC;AAeD,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,MAAe;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;IAEnC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,QAAQ,EAAE,EAAE,CAAA;IACjF,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAA;IACxG,CAAC;IAED,IAAI,MAAc,CAAA;IAClB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAsB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAA;IACjG,CAAC;IAED,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;QACvB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAiB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAA;IAC5F,CAAC;IAED,IAAI,IAAY,CAAA;IAChB,IAAI,CAAC;QACH,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAsB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAA;IACjG,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9D,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAA;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;IAE9C,IAAI,CAAC;QACH,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,wBAAyB,GAAa,CAAC,OAAO,EAAE,EAAE,CAAA;IACpG,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,SAAiB;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;IACnC,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,mBAAmB,QAAQ,EAAE,CAAC,EAAE,CAAA;IACpF,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,oDAAoD,CAAC,EAAE,CAAA;IAC3G,CAAC;IAED,IAAI,MAAc,CAAA;IAClB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;IACpG,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;QAE7B,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;QACjE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;QACjE,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAA;QAChG,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,gBAAiB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;AACjE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ReclProgram, DataDivision, DisplayStatement } from '../parser/rcl.js';
2
+ export declare function renderStatement(stmt: DisplayStatement, data: DataDivision): string;
3
+ export declare function generate(program: ReclProgram, source: string): string;
4
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/generator/html.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EAEX,YAAY,EAEZ,gBAAgB,EAEjB,MAAM,kBAAkB,CAAA;AAyTzB,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CA0BlF;AAMD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA8CrE"}