rs_web/lua/
types.rs

1//! Lua API type definitions for generating EmmyLua annotations and documentation
2//!
3//! This module provides the type registry used to generate:
4//! - EmmyLua annotations (.lua file with @param, @return, @class)
5//! - Markdown API documentation
6
7/// A Lua function definition
8#[derive(Debug, Clone)]
9pub struct LuaFunction {
10    pub name: &'static str,
11    pub module: Option<&'static str>,
12    pub description: &'static str,
13    pub params: &'static [LuaParam],
14    pub returns: &'static str,
15}
16
17/// A Lua function parameter
18#[derive(Debug, Clone)]
19pub struct LuaParam {
20    pub name: &'static str,
21    pub typ: &'static str,
22    pub description: &'static str,
23    pub optional: bool,
24}
25
26/// A Lua class/table type definition
27#[derive(Debug, Clone)]
28pub struct LuaClass {
29    pub name: &'static str,
30    pub description: &'static str,
31    pub fields: &'static [LuaField],
32}
33
34/// A field in a Lua class
35#[derive(Debug, Clone)]
36pub struct LuaField {
37    pub name: &'static str,
38    pub typ: &'static str,
39    pub description: &'static str,
40}
41
42// ============================================================================
43// CLASS DEFINITIONS
44// ============================================================================
45
46pub static LUA_CLASSES: &[LuaClass] = &[
47    LuaClass {
48        name: "FileInfo",
49        description: "File metadata",
50        fields: &[
51            LuaField {
52                name: "path",
53                typ: "string",
54                description: "Absolute path",
55            },
56            LuaField {
57                name: "name",
58                typ: "string",
59                description: "Full filename with extension",
60            },
61            LuaField {
62                name: "stem",
63                typ: "string",
64                description: "Filename without extension",
65            },
66            LuaField {
67                name: "ext",
68                typ: "string",
69                description: "File extension",
70            },
71            LuaField {
72                name: "is_dir",
73                typ: "boolean",
74                description: "Whether this is a directory",
75            },
76            LuaField {
77                name: "modified",
78                typ: "number|nil",
79                description: "Unix timestamp of last modification",
80            },
81        ],
82    },
83    LuaClass {
84        name: "FrontmatterResult",
85        description: "Result of reading frontmatter from a file. Frontmatter fields are merged to top level.",
86        fields: &[
87            LuaField {
88                name: "raw",
89                typ: "string",
90                description: "Original file content",
91            },
92            LuaField {
93                name: "content",
94                typ: "string",
95                description: "Content after frontmatter",
96            },
97            LuaField {
98                name: "title",
99                typ: "string?",
100                description: "Common frontmatter field",
101            },
102            LuaField {
103                name: "description",
104                typ: "string?",
105                description: "Common frontmatter field",
106            },
107            LuaField {
108                name: "date",
109                typ: "string?",
110                description: "Common frontmatter field",
111            },
112            LuaField {
113                name: "template",
114                typ: "string?",
115                description: "Common frontmatter field",
116            },
117            LuaField {
118                name: "[string]",
119                typ: "string|number|boolean|table|any[]",
120                description: "Additional frontmatter fields (supports nested values)",
121            },
122        ],
123    },
124    LuaClass {
125        name: "GitInfo",
126        description: "Git repository information",
127        fields: &[
128            LuaField {
129                name: "hash",
130                typ: "string",
131                description: "Full commit hash",
132            },
133            LuaField {
134                name: "short_hash",
135                typ: "string",
136                description: "Short hash (7 chars)",
137            },
138            LuaField {
139                name: "branch",
140                typ: "string|nil",
141                description: "Current branch name",
142            },
143            LuaField {
144                name: "author",
145                typ: "string|nil",
146                description: "Commit author",
147            },
148            LuaField {
149                name: "date",
150                typ: "string|nil",
151                description: "Commit date (YYYY-MM-DD)",
152            },
153            LuaField {
154                name: "dirty",
155                typ: "boolean",
156                description: "Has uncommitted changes",
157            },
158        ],
159    },
160    LuaClass {
161        name: "ImageDimensions",
162        description: "Image dimensions",
163        fields: &[
164            LuaField {
165                name: "width",
166                typ: "number",
167                description: "Image width in pixels",
168            },
169            LuaField {
170                name: "height",
171                typ: "number",
172                description: "Image height in pixels",
173            },
174        ],
175    },
176    LuaClass {
177        name: "ImageResizeOptions",
178        description: "Options for image_resize",
179        fields: &[
180            LuaField {
181                name: "width",
182                typ: "number",
183                description: "Target width in pixels",
184            },
185            LuaField {
186                name: "height",
187                typ: "number?",
188                description: "Target height (maintains aspect ratio if omitted)",
189            },
190            LuaField {
191                name: "quality",
192                typ: "number?",
193                description: "Quality 0-100 for lossy formats (default: 85)",
194            },
195        ],
196    },
197    LuaClass {
198        name: "ImageConvertOptions",
199        description: "Options for image_convert",
200        fields: &[
201            LuaField {
202                name: "format",
203                typ: "string?",
204                description: "Target format: 'webp'|'png'|'jpg' (default: from extension)",
205            },
206            LuaField {
207                name: "quality",
208                typ: "number?",
209                description: "Quality 0-100 for lossy formats (default: 85)",
210            },
211        ],
212    },
213    LuaClass {
214        name: "ImageOptimizeOptions",
215        description: "Options for image_optimize",
216        fields: &[LuaField {
217            name: "quality",
218            typ: "number?",
219            description: "Quality 0-100 (default: 85)",
220        }],
221    },
222    LuaClass {
223        name: "BuildCssOptions",
224        description: "Options for build_css",
225        fields: &[LuaField {
226            name: "minify",
227            typ: "boolean?",
228            description: "Minify output CSS (default: false)",
229        }],
230    },
231    LuaClass {
232        name: "GoogleFontOptions",
233        description: "Options for download_google_font",
234        fields: &[
235            LuaField {
236                name: "fonts_dir",
237                typ: "string",
238                description: "Directory to save font files (required)",
239            },
240            LuaField {
241                name: "css_path",
242                typ: "string",
243                description: "Path to save CSS file (required)",
244            },
245            LuaField {
246                name: "css_prefix",
247                typ: "string?",
248                description: "URL prefix for fonts in CSS (default: '/fonts')",
249            },
250            LuaField {
251                name: "weights",
252                typ: "number[]?",
253                description: "Font weights to download (default: {400})",
254            },
255            LuaField {
256                name: "display",
257                typ: "string?",
258                description: "Font display strategy: 'swap'|'block'|'fallback'|'optional' (default: 'swap')",
259            },
260        ],
261    },
262    LuaClass {
263        name: "MarkdownEvent",
264        description: "Markdown AST event for transformation",
265        fields: &[
266            LuaField {
267                name: "type",
268                typ: "string",
269                description: "Event type: 'text'|'html'|'code'|'start'|'end'|'softbreak'|'hardbreak'|'rule'",
270            },
271            LuaField {
272                name: "content",
273                typ: "string|nil",
274                description: "Text/HTML/code content",
275            },
276            LuaField {
277                name: "tag",
278                typ: "string|nil",
279                description: "Tag name for start/end events",
280            },
281            LuaField {
282                name: "level",
283                typ: "number|nil",
284                description: "Heading level (1-6)",
285            },
286            LuaField {
287                name: "url",
288                typ: "string|nil",
289                description: "Link/image URL",
290            },
291            LuaField {
292                name: "title",
293                typ: "string|nil",
294                description: "Link/image title",
295            },
296        ],
297    },
298    LuaClass {
299        name: "MarkdownContext",
300        description: "Context information during markdown parsing",
301        fields: &[
302            LuaField {
303                name: "in_paragraph",
304                typ: "boolean",
305                description: "Inside paragraph",
306            },
307            LuaField {
308                name: "in_heading",
309                typ: "boolean",
310                description: "Inside heading",
311            },
312            LuaField {
313                name: "in_list",
314                typ: "boolean",
315                description: "Inside list",
316            },
317            LuaField {
318                name: "in_list_item",
319                typ: "boolean",
320                description: "Inside list item",
321            },
322            LuaField {
323                name: "in_blockquote",
324                typ: "boolean",
325                description: "Inside blockquote",
326            },
327            LuaField {
328                name: "in_link",
329                typ: "boolean",
330                description: "Inside link",
331            },
332            LuaField {
333                name: "in_emphasis",
334                typ: "boolean",
335                description: "Inside emphasis",
336            },
337            LuaField {
338                name: "in_strong",
339                typ: "boolean",
340                description: "Inside strong",
341            },
342            LuaField {
343                name: "in_code_block",
344                typ: "boolean",
345                description: "Inside code block",
346            },
347            LuaField {
348                name: "in_table",
349                typ: "boolean",
350                description: "Inside table",
351            },
352            LuaField {
353                name: "heading_level",
354                typ: "number",
355                description: "Current heading level (0 if not in heading)",
356            },
357            LuaField {
358                name: "list_depth",
359                typ: "number",
360                description: "Nesting depth of lists",
361            },
362        ],
363    },
364    LuaClass {
365        name: "CoroTask",
366        description: "Coroutine task wrapper for cooperative multitasking",
367        fields: &[
368            LuaField {
369                name: "_co",
370                typ: "thread",
371                description: "Internal coroutine",
372            },
373            LuaField {
374                name: "_completed",
375                typ: "boolean",
376                description: "Whether task has completed",
377            },
378            LuaField {
379                name: "_result",
380                typ: "any",
381                description: "Task result",
382            },
383        ],
384    },
385    LuaClass {
386        name: "AsyncTask",
387        description: "Async task handle for tokio-backed I/O operations",
388        fields: &[LuaField {
389            name: "is_completed",
390            typ: "fun(): boolean",
391            description: "Check if task has completed",
392        }],
393    },
394    LuaClass {
395        name: "FetchResponse",
396        description: "HTTP response from async.fetch",
397        fields: &[
398            LuaField {
399                name: "status",
400                typ: "number",
401                description: "HTTP status code",
402            },
403            LuaField {
404                name: "ok",
405                typ: "boolean",
406                description: "Whether request was successful (2xx)",
407            },
408            LuaField {
409                name: "body",
410                typ: "string",
411                description: "Response body as string",
412            },
413            LuaField {
414                name: "headers",
415                typ: "table<string, string>",
416                description: "Response headers",
417            },
418            LuaField {
419                name: "json",
420                typ: "fun(): table",
421                description: "Parse body as JSON",
422            },
423        ],
424    },
425    LuaClass {
426        name: "FetchOptions",
427        description: "Options for async.fetch",
428        fields: &[
429            LuaField {
430                name: "method",
431                typ: "string?",
432                description: "HTTP method: GET|POST|PUT|DELETE|PATCH|HEAD (default: GET)",
433            },
434            LuaField {
435                name: "headers",
436                typ: "table<string, string>?",
437                description: "Request headers",
438            },
439            LuaField {
440                name: "body",
441                typ: "string|table?",
442                description: "Request body (table will be JSON encoded)",
443            },
444            LuaField {
445                name: "timeout",
446                typ: "number?",
447                description: "Timeout in seconds",
448            },
449        ],
450    },
451    LuaClass {
452        name: "EncryptedData",
453        description: "Encrypted content data from crypt.encrypt",
454        fields: &[
455            LuaField {
456                name: "ciphertext",
457                typ: "string",
458                description: "Base64-encoded encrypted content",
459            },
460            LuaField {
461                name: "salt",
462                typ: "string",
463                description: "Base64-encoded salt for key derivation",
464            },
465            LuaField {
466                name: "nonce",
467                typ: "string",
468                description: "Base64-encoded nonce for decryption",
469            },
470        ],
471    },
472    LuaClass {
473        name: "EncryptHtmlOptions",
474        description: "Options for crypt.encrypt_html",
475        fields: &[
476            LuaField {
477                name: "password",
478                typ: "string?",
479                description: "Encryption password (uses SITE_PASSWORD env if not provided)",
480            },
481            LuaField {
482                name: "slug",
483                typ: "string?",
484                description: "Page slug for localStorage key (default: 'page')",
485            },
486            LuaField {
487                name: "block_id",
488                typ: "string?",
489                description: "Unique block ID (auto-generated if not provided)",
490            },
491            LuaField {
492                name: "own_password",
493                typ: "boolean?",
494                description: "Whether block has its own password (default: false)",
495            },
496        ],
497    },
498    LuaClass {
499        name: "DirEntry",
500        description: "Directory entry from async.read_dir",
501        fields: &[
502            LuaField {
503                name: "path",
504                typ: "string",
505                description: "Full path to the entry",
506            },
507            LuaField {
508                name: "name",
509                typ: "string",
510                description: "Entry name (filename or directory name)",
511            },
512            LuaField {
513                name: "is_file",
514                typ: "boolean",
515                description: "Whether this is a file",
516            },
517            LuaField {
518                name: "is_dir",
519                typ: "boolean",
520                description: "Whether this is a directory",
521            },
522            LuaField {
523                name: "is_symlink",
524                typ: "boolean",
525                description: "Whether this is a symbolic link",
526            },
527        ],
528    },
529    LuaClass {
530        name: "FileMetadata",
531        description: "File metadata from async.metadata",
532        fields: &[
533            LuaField {
534                name: "is_file",
535                typ: "boolean",
536                description: "Whether this is a file",
537            },
538            LuaField {
539                name: "is_dir",
540                typ: "boolean",
541                description: "Whether this is a directory",
542            },
543            LuaField {
544                name: "len",
545                typ: "number",
546                description: "File size in bytes",
547            },
548            LuaField {
549                name: "readonly",
550                typ: "boolean",
551                description: "Whether file is read-only",
552            },
553            LuaField {
554                name: "modified",
555                typ: "number?",
556                description: "Unix timestamp of last modification",
557            },
558        ],
559    },
560    LuaClass {
561        name: "DateTable",
562        description: "Date as table with year, month, day fields",
563        fields: &[
564            LuaField {
565                name: "year",
566                typ: "number",
567                description: "Year (e.g., 2024)",
568            },
569            LuaField {
570                name: "month",
571                typ: "number",
572                description: "Month (1-12)",
573            },
574            LuaField {
575                name: "day",
576                typ: "number",
577                description: "Day of month (1-31)",
578            },
579        ],
580    },
581];
582
583// ============================================================================
584// FUNCTION DEFINITIONS
585// ============================================================================
586
587pub static LUA_FUNCTIONS: &[LuaFunction] = &[
588    // FILE OPERATIONS
589    LuaFunction {
590        name: "read_file",
591        module: None,
592        description: "Read file contents as string",
593        params: &[LuaParam {
594            name: "path",
595            typ: "string",
596            description: "Path to file",
597            optional: false,
598        }],
599        returns: "string|nil",
600    },
601    LuaFunction {
602        name: "write_file",
603        module: None,
604        description: "Write content to file",
605        params: &[
606            LuaParam {
607                name: "path",
608                typ: "string",
609                description: "Path to write to",
610                optional: false,
611            },
612            LuaParam {
613                name: "content",
614                typ: "string",
615                description: "Content to write",
616                optional: false,
617            },
618        ],
619        returns: "boolean",
620    },
621    LuaFunction {
622        name: "copy_file",
623        module: None,
624        description: "Copy a file (works with binary files)",
625        params: &[
626            LuaParam {
627                name: "src",
628                typ: "string",
629                description: "Source file path",
630                optional: false,
631            },
632            LuaParam {
633                name: "dest",
634                typ: "string",
635                description: "Destination file path",
636                optional: false,
637            },
638        ],
639        returns: "boolean",
640    },
641    LuaFunction {
642        name: "file_exists",
643        module: None,
644        description: "Check if file exists",
645        params: &[LuaParam {
646            name: "path",
647            typ: "string",
648            description: "Path to check",
649            optional: false,
650        }],
651        returns: "boolean",
652    },
653    LuaFunction {
654        name: "list_files",
655        module: None,
656        description: "List files in directory matching pattern",
657        params: &[
658            LuaParam {
659                name: "path",
660                typ: "string",
661                description: "Directory to search",
662                optional: false,
663            },
664            LuaParam {
665                name: "pattern",
666                typ: "string",
667                description: "Glob pattern (default: '*')",
668                optional: true,
669            },
670        ],
671        returns: "FileInfo[]",
672    },
673    LuaFunction {
674        name: "list_dirs",
675        module: None,
676        description: "List subdirectories",
677        params: &[LuaParam {
678            name: "path",
679            typ: "string",
680            description: "Directory to search",
681            optional: false,
682        }],
683        returns: "string[]",
684    },
685    LuaFunction {
686        name: "load_json",
687        module: None,
688        description: "Load and parse JSON file",
689        params: &[LuaParam {
690            name: "path",
691            typ: "string",
692            description: "Path to JSON file",
693            optional: false,
694        }],
695        returns: "table<string, any>|nil",
696    },
697    LuaFunction {
698        name: "load_yaml",
699        module: None,
700        description: "Load and parse YAML file",
701        params: &[LuaParam {
702            name: "path",
703            typ: "string",
704            description: "Path to YAML file",
705            optional: false,
706        }],
707        returns: "table<string, any>|nil",
708    },
709    LuaFunction {
710        name: "load_toml",
711        module: None,
712        description: "Load and parse TOML file",
713        params: &[LuaParam {
714            name: "path",
715            typ: "string",
716            description: "Path to TOML file",
717            optional: false,
718        }],
719        returns: "table<string, any>|nil",
720    },
721    LuaFunction {
722        name: "read_frontmatter",
723        module: None,
724        description: "Read and parse frontmatter from markdown file",
725        params: &[LuaParam {
726            name: "path",
727            typ: "string",
728            description: "Path to markdown file",
729            optional: false,
730        }],
731        returns: "FrontmatterResult|nil",
732    },
733    // SEARCH
734    LuaFunction {
735        name: "glob",
736        module: None,
737        description: "Find files matching glob pattern",
738        params: &[LuaParam {
739            name: "pattern",
740            typ: "string",
741            description: "Glob pattern (e.g., '**/*.md')",
742            optional: false,
743        }],
744        returns: "FileInfo[]",
745    },
746    LuaFunction {
747        name: "scan",
748        module: None,
749        description: "List directories in path",
750        params: &[LuaParam {
751            name: "path",
752            typ: "string",
753            description: "Directory to scan",
754            optional: false,
755        }],
756        returns: "FileInfo[]",
757    },
758    // COLLECTIONS
759    LuaFunction {
760        name: "filter",
761        module: None,
762        description: "Filter items using predicate function",
763        params: &[
764            LuaParam {
765                name: "items",
766                typ: "T[]",
767                description: "Items to filter",
768                optional: false,
769            },
770            LuaParam {
771                name: "fn",
772                typ: "fun(item: T): boolean",
773                description: "Predicate function",
774                optional: false,
775            },
776        ],
777        returns: "T[]",
778    },
779    LuaFunction {
780        name: "sort",
781        module: None,
782        description: "Sort items using comparator function",
783        params: &[
784            LuaParam {
785                name: "items",
786                typ: "T[]",
787                description: "Items to sort",
788                optional: false,
789            },
790            LuaParam {
791                name: "fn",
792                typ: "fun(a: T, b: T): boolean",
793                description: "Comparator (return true if a < b)",
794                optional: false,
795            },
796        ],
797        returns: "T[]",
798    },
799    LuaFunction {
800        name: "map",
801        module: None,
802        description: "Transform items using mapping function",
803        params: &[
804            LuaParam {
805                name: "items",
806                typ: "T[]",
807                description: "Items to transform",
808                optional: false,
809            },
810            LuaParam {
811                name: "fn",
812                typ: "fun(item: T): U",
813                description: "Mapping function",
814                optional: false,
815            },
816        ],
817        returns: "U[]",
818    },
819    LuaFunction {
820        name: "find",
821        module: None,
822        description: "Find first item where predicate returns true",
823        params: &[
824            LuaParam {
825                name: "items",
826                typ: "T[]",
827                description: "Items to search",
828                optional: false,
829            },
830            LuaParam {
831                name: "fn",
832                typ: "fun(item: T): boolean",
833                description: "Predicate function",
834                optional: false,
835            },
836        ],
837        returns: "T|nil",
838    },
839    LuaFunction {
840        name: "group_by",
841        module: None,
842        description: "Group items by key returned by key function",
843        params: &[
844            LuaParam {
845                name: "items",
846                typ: "T[]",
847                description: "Items to group",
848                optional: false,
849            },
850            LuaParam {
851                name: "fn",
852                typ: "fun(item: T): string",
853                description: "Key function",
854                optional: false,
855            },
856        ],
857        returns: "table<string, T[]>",
858    },
859    LuaFunction {
860        name: "unique",
861        module: None,
862        description: "Remove duplicates from array",
863        params: &[LuaParam {
864            name: "items",
865            typ: "T[]",
866            description: "Items to deduplicate",
867            optional: false,
868        }],
869        returns: "T[]",
870    },
871    LuaFunction {
872        name: "reverse",
873        module: None,
874        description: "Reverse array order",
875        params: &[LuaParam {
876            name: "items",
877            typ: "T[]",
878            description: "Items to reverse",
879            optional: false,
880        }],
881        returns: "T[]",
882    },
883    LuaFunction {
884        name: "take",
885        module: None,
886        description: "Take first n items from array",
887        params: &[
888            LuaParam {
889                name: "items",
890                typ: "T[]",
891                description: "Items to take from",
892                optional: false,
893            },
894            LuaParam {
895                name: "n",
896                typ: "number",
897                description: "Number of items to take",
898                optional: false,
899            },
900        ],
901        returns: "T[]",
902    },
903    LuaFunction {
904        name: "skip",
905        module: None,
906        description: "Skip first n items from array",
907        params: &[
908            LuaParam {
909                name: "items",
910                typ: "T[]",
911                description: "Items to skip from",
912                optional: false,
913            },
914            LuaParam {
915                name: "n",
916                typ: "number",
917                description: "Number of items to skip",
918                optional: false,
919            },
920        ],
921        returns: "T[]",
922    },
923    LuaFunction {
924        name: "keys",
925        module: None,
926        description: "Get all keys from a table",
927        params: &[LuaParam {
928            name: "table",
929            typ: "table<K, V>",
930            description: "Table to get keys from",
931            optional: false,
932        }],
933        returns: "K[]",
934    },
935    LuaFunction {
936        name: "values",
937        module: None,
938        description: "Get all values from a table",
939        params: &[LuaParam {
940            name: "table",
941            typ: "table<K, V>",
942            description: "Table to get values from",
943            optional: false,
944        }],
945        returns: "V[]",
946    },
947    // TEXT
948    LuaFunction {
949        name: "slugify",
950        module: None,
951        description: "Convert text to URL-friendly slug",
952        params: &[LuaParam {
953            name: "text",
954            typ: "string",
955            description: "Text to slugify",
956            optional: false,
957        }],
958        returns: "string",
959    },
960    LuaFunction {
961        name: "word_count",
962        module: None,
963        description: "Count words in text",
964        params: &[LuaParam {
965            name: "text",
966            typ: "string",
967            description: "Text to count",
968            optional: false,
969        }],
970        returns: "number",
971    },
972    LuaFunction {
973        name: "reading_time",
974        module: None,
975        description: "Calculate reading time in minutes",
976        params: &[
977            LuaParam {
978                name: "text",
979                typ: "string",
980                description: "Text to analyze",
981                optional: false,
982            },
983            LuaParam {
984                name: "wpm",
985                typ: "number",
986                description: "Words per minute (default: 200)",
987                optional: true,
988            },
989        ],
990        returns: "number",
991    },
992    LuaFunction {
993        name: "truncate",
994        module: None,
995        description: "Truncate text with optional suffix",
996        params: &[
997            LuaParam {
998                name: "text",
999                typ: "string",
1000                description: "Text to truncate",
1001                optional: false,
1002            },
1003            LuaParam {
1004                name: "len",
1005                typ: "number",
1006                description: "Maximum length",
1007                optional: false,
1008            },
1009            LuaParam {
1010                name: "suffix",
1011                typ: "string",
1012                description: "Suffix to append (default: '...')",
1013                optional: true,
1014            },
1015        ],
1016        returns: "string",
1017    },
1018    LuaFunction {
1019        name: "strip_tags",
1020        module: None,
1021        description: "Remove HTML tags from string",
1022        params: &[LuaParam {
1023            name: "html",
1024            typ: "string",
1025            description: "HTML content",
1026            optional: false,
1027        }],
1028        returns: "string",
1029    },
1030    LuaFunction {
1031        name: "format_date",
1032        module: None,
1033        description: "Format a date string",
1034        params: &[
1035            LuaParam {
1036                name: "date",
1037                typ: "string|DateTable",
1038                description: "Date string (YYYY-MM-DD) or table {year, month, day}",
1039                optional: false,
1040            },
1041            LuaParam {
1042                name: "format",
1043                typ: "string",
1044                description: "Output format (chrono strftime)",
1045                optional: false,
1046            },
1047        ],
1048        returns: "string|nil",
1049    },
1050    LuaFunction {
1051        name: "parse_date",
1052        module: None,
1053        description: "Parse date string to table",
1054        params: &[LuaParam {
1055            name: "date_str",
1056            typ: "string",
1057            description: "Date string to parse",
1058            optional: false,
1059        }],
1060        returns: "DateTable|nil",
1061    },
1062    LuaFunction {
1063        name: "hash",
1064        module: None,
1065        description: "Hash content using xxHash64",
1066        params: &[LuaParam {
1067            name: "content",
1068            typ: "string",
1069            description: "Content to hash",
1070            optional: false,
1071        }],
1072        returns: "string",
1073    },
1074    LuaFunction {
1075        name: "hash_file",
1076        module: None,
1077        description: "Hash file contents using xxHash64",
1078        params: &[LuaParam {
1079            name: "path",
1080            typ: "string",
1081            description: "Path to file",
1082            optional: false,
1083        }],
1084        returns: "string|nil",
1085    },
1086    LuaFunction {
1087        name: "url_encode",
1088        module: None,
1089        description: "URL encode a string",
1090        params: &[LuaParam {
1091            name: "text",
1092            typ: "string",
1093            description: "Text to encode",
1094            optional: false,
1095        }],
1096        returns: "string",
1097    },
1098    LuaFunction {
1099        name: "url_decode",
1100        module: None,
1101        description: "URL decode a string",
1102        params: &[LuaParam {
1103            name: "text",
1104            typ: "string",
1105            description: "Text to decode",
1106            optional: false,
1107        }],
1108        returns: "string",
1109    },
1110    // PATH UTILITIES
1111    LuaFunction {
1112        name: "join_path",
1113        module: None,
1114        description: "Join path segments",
1115        params: &[LuaParam {
1116            name: "...",
1117            typ: "string",
1118            description: "Path segments to join",
1119            optional: false,
1120        }],
1121        returns: "string",
1122    },
1123    LuaFunction {
1124        name: "basename",
1125        module: None,
1126        description: "Get file name from path",
1127        params: &[LuaParam {
1128            name: "path",
1129            typ: "string",
1130            description: "File path",
1131            optional: false,
1132        }],
1133        returns: "string",
1134    },
1135    LuaFunction {
1136        name: "dirname",
1137        module: None,
1138        description: "Get directory from path",
1139        params: &[LuaParam {
1140            name: "path",
1141            typ: "string",
1142            description: "File path",
1143            optional: false,
1144        }],
1145        returns: "string",
1146    },
1147    LuaFunction {
1148        name: "extension",
1149        module: None,
1150        description: "Get file extension from path",
1151        params: &[LuaParam {
1152            name: "path",
1153            typ: "string",
1154            description: "File path",
1155            optional: false,
1156        }],
1157        returns: "string",
1158    },
1159    // ENV
1160    LuaFunction {
1161        name: "env",
1162        module: None,
1163        description: "Get environment variable",
1164        params: &[LuaParam {
1165            name: "name",
1166            typ: "string",
1167            description: "Variable name",
1168            optional: false,
1169        }],
1170        returns: "string|nil",
1171    },
1172    LuaFunction {
1173        name: "print",
1174        module: None,
1175        description: "Log message to build output",
1176        params: &[LuaParam {
1177            name: "...",
1178            typ: "any",
1179            description: "Values to print",
1180            optional: false,
1181        }],
1182        returns: "nil",
1183    },
1184    LuaFunction {
1185        name: "is_gitignored",
1186        module: None,
1187        description: "Check if path is gitignored",
1188        params: &[LuaParam {
1189            name: "path",
1190            typ: "string",
1191            description: "Path to check",
1192            optional: false,
1193        }],
1194        returns: "boolean",
1195    },
1196    // GIT
1197    LuaFunction {
1198        name: "git_info",
1199        module: None,
1200        description: "Get git information for repo or file",
1201        params: &[LuaParam {
1202            name: "path",
1203            typ: "string",
1204            description: "File/directory path (default: repo root)",
1205            optional: true,
1206        }],
1207        returns: "GitInfo|nil",
1208    },
1209    // CONTENT
1210    LuaFunction {
1211        name: "render_markdown",
1212        module: None,
1213        description: "Render markdown to HTML with optional AST transformation",
1214        params: &[
1215            LuaParam {
1216                name: "content",
1217                typ: "string",
1218                description: "Markdown content",
1219                optional: false,
1220            },
1221            LuaParam {
1222                name: "transform_fn",
1223                typ: "fun(event: MarkdownEvent, ctx: MarkdownContext): MarkdownEvent|nil",
1224                description: "Optional transform function",
1225                optional: true,
1226            },
1227        ],
1228        returns: "string",
1229    },
1230    LuaFunction {
1231        name: "rss_date",
1232        module: None,
1233        description: "Format date for RSS (RFC 2822)",
1234        params: &[LuaParam {
1235            name: "date_string",
1236            typ: "string",
1237            description: "Date string (YYYY-MM-DD)",
1238            optional: false,
1239        }],
1240        returns: "string|nil",
1241    },
1242    LuaFunction {
1243        name: "extract_links_markdown",
1244        module: None,
1245        description: "Extract links from markdown content",
1246        params: &[LuaParam {
1247            name: "content",
1248            typ: "string",
1249            description: "Markdown content",
1250            optional: false,
1251        }],
1252        returns: "string[]",
1253    },
1254    LuaFunction {
1255        name: "extract_links_html",
1256        module: None,
1257        description: "Extract links from HTML content",
1258        params: &[LuaParam {
1259            name: "content",
1260            typ: "string",
1261            description: "HTML content",
1262            optional: false,
1263        }],
1264        returns: "string[]",
1265    },
1266    LuaFunction {
1267        name: "extract_images_markdown",
1268        module: None,
1269        description: "Extract image paths from markdown",
1270        params: &[LuaParam {
1271            name: "content",
1272            typ: "string",
1273            description: "Markdown content",
1274            optional: false,
1275        }],
1276        returns: "string[]",
1277    },
1278    LuaFunction {
1279        name: "extract_images_html",
1280        module: None,
1281        description: "Extract image paths from HTML",
1282        params: &[LuaParam {
1283            name: "content",
1284            typ: "string",
1285            description: "HTML content",
1286            optional: false,
1287        }],
1288        returns: "string[]",
1289    },
1290    LuaFunction {
1291        name: "html_to_text",
1292        module: None,
1293        description: "Convert HTML to formatted plain text",
1294        params: &[LuaParam {
1295            name: "html",
1296            typ: "string",
1297            description: "HTML content",
1298            optional: false,
1299        }],
1300        returns: "string",
1301    },
1302    // ASSETS
1303    LuaFunction {
1304        name: "build_css",
1305        module: None,
1306        description: "Build and concatenate CSS files from glob pattern or array of paths",
1307        params: &[
1308            LuaParam {
1309                name: "paths_or_pattern",
1310                typ: "string|string[]",
1311                description: "Glob pattern (e.g., 'styles/*.css') or array of file paths",
1312                optional: false,
1313            },
1314            LuaParam {
1315                name: "output_path",
1316                typ: "string",
1317                description: "Output file path",
1318                optional: false,
1319            },
1320            LuaParam {
1321                name: "options",
1322                typ: "BuildCssOptions",
1323                description: "Build options (minify)",
1324                optional: true,
1325            },
1326        ],
1327        returns: "boolean",
1328    },
1329    LuaFunction {
1330        name: "check_unused_assets",
1331        module: None,
1332        description: "Find assets in output directory not referenced by any HTML file",
1333        params: &[LuaParam {
1334            name: "output_dir",
1335            typ: "string",
1336            description: "Output directory to check",
1337            optional: false,
1338        }],
1339        returns: "string[]",
1340    },
1341    LuaFunction {
1342        name: "download_google_font",
1343        module: None,
1344        description: "Download Google Font files and generate local CSS",
1345        params: &[
1346            LuaParam {
1347                name: "family",
1348                typ: "string",
1349                description: "Font family name (e.g., 'Lexend', 'Open Sans')",
1350                optional: false,
1351            },
1352            LuaParam {
1353                name: "options",
1354                typ: "GoogleFontOptions",
1355                description: "Font options (fonts_dir, css_path required)",
1356                optional: false,
1357            },
1358        ],
1359        returns: "boolean",
1360    },
1361    // IMAGES
1362    LuaFunction {
1363        name: "image_dimensions",
1364        module: None,
1365        description: "Get image dimensions",
1366        params: &[LuaParam {
1367            name: "path",
1368            typ: "string",
1369            description: "Path to image",
1370            optional: false,
1371        }],
1372        returns: "ImageDimensions|nil",
1373    },
1374    LuaFunction {
1375        name: "image_resize",
1376        module: None,
1377        description: "Resize image",
1378        params: &[
1379            LuaParam {
1380                name: "input",
1381                typ: "string",
1382                description: "Input image path",
1383                optional: false,
1384            },
1385            LuaParam {
1386                name: "output",
1387                typ: "string",
1388                description: "Output image path",
1389                optional: false,
1390            },
1391            LuaParam {
1392                name: "options",
1393                typ: "ImageResizeOptions",
1394                description: "Resize options (width required, height/quality optional)",
1395                optional: false,
1396            },
1397        ],
1398        returns: "boolean",
1399    },
1400    LuaFunction {
1401        name: "image_convert",
1402        module: None,
1403        description: "Convert image format",
1404        params: &[
1405            LuaParam {
1406                name: "input",
1407                typ: "string",
1408                description: "Input image path",
1409                optional: false,
1410            },
1411            LuaParam {
1412                name: "output",
1413                typ: "string",
1414                description: "Output image path",
1415                optional: false,
1416            },
1417            LuaParam {
1418                name: "options",
1419                typ: "ImageConvertOptions",
1420                description: "Convert options (format/quality)",
1421                optional: true,
1422            },
1423        ],
1424        returns: "boolean",
1425    },
1426    LuaFunction {
1427        name: "image_optimize",
1428        module: None,
1429        description: "Optimize/compress image",
1430        params: &[
1431            LuaParam {
1432                name: "input",
1433                typ: "string",
1434                description: "Input image path",
1435                optional: false,
1436            },
1437            LuaParam {
1438                name: "output",
1439                typ: "string",
1440                description: "Output image path",
1441                optional: false,
1442            },
1443            LuaParam {
1444                name: "options",
1445                typ: "ImageOptimizeOptions",
1446                description: "Optimize options (quality)",
1447                optional: true,
1448            },
1449        ],
1450        returns: "boolean",
1451    },
1452    // CORO MODULE
1453    LuaFunction {
1454        name: "task",
1455        module: Some("coro"),
1456        description: "Create coroutine task from function",
1457        params: &[LuaParam {
1458            name: "fn",
1459            typ: "function",
1460            description: "Function to wrap",
1461            optional: false,
1462        }],
1463        returns: "CoroTask",
1464    },
1465    LuaFunction {
1466        name: "await",
1467        module: Some("coro"),
1468        description: "Run task to completion",
1469        params: &[LuaParam {
1470            name: "task",
1471            typ: "CoroTask",
1472            description: "Task to run",
1473            optional: false,
1474        }],
1475        returns: "any",
1476    },
1477    LuaFunction {
1478        name: "yield",
1479        module: Some("coro"),
1480        description: "Yield from current task",
1481        params: &[LuaParam {
1482            name: "value",
1483            typ: "any",
1484            description: "Value to yield",
1485            optional: true,
1486        }],
1487        returns: "any",
1488    },
1489    LuaFunction {
1490        name: "all",
1491        module: Some("coro"),
1492        description: "Run multiple tasks concurrently",
1493        params: &[LuaParam {
1494            name: "tasks",
1495            typ: "CoroTask[]",
1496            description: "Tasks to run",
1497            optional: false,
1498        }],
1499        returns: "any[]",
1500    },
1501    LuaFunction {
1502        name: "race",
1503        module: Some("coro"),
1504        description: "Run tasks and return first completed",
1505        params: &[LuaParam {
1506            name: "tasks",
1507            typ: "CoroTask[]",
1508            description: "Tasks to race",
1509            optional: false,
1510        }],
1511        returns: "any",
1512    },
1513    LuaFunction {
1514        name: "sleep",
1515        module: Some("coro"),
1516        description: "Sleep/delay (yields N times for cooperative scheduling)",
1517        params: &[LuaParam {
1518            name: "n",
1519            typ: "number",
1520            description: "Number of yields",
1521            optional: true,
1522        }],
1523        returns: "nil",
1524    },
1525    // PARALLEL MODULE
1526    LuaFunction {
1527        name: "load_json",
1528        module: Some("parallel"),
1529        description: "Load multiple JSON files in parallel",
1530        params: &[LuaParam {
1531            name: "paths",
1532            typ: "string[]",
1533            description: "Paths to load",
1534            optional: false,
1535        }],
1536        returns: "(table<string, any>|nil)[]",
1537    },
1538    LuaFunction {
1539        name: "read_files",
1540        module: Some("parallel"),
1541        description: "Read multiple files in parallel",
1542        params: &[LuaParam {
1543            name: "paths",
1544            typ: "string[]",
1545            description: "Paths to read",
1546            optional: false,
1547        }],
1548        returns: "(string|nil)[]",
1549    },
1550    LuaFunction {
1551        name: "file_exists",
1552        module: Some("parallel"),
1553        description: "Check multiple files exist in parallel",
1554        params: &[LuaParam {
1555            name: "paths",
1556            typ: "string[]",
1557            description: "Paths to check",
1558            optional: false,
1559        }],
1560        returns: "boolean[]",
1561    },
1562    LuaFunction {
1563        name: "load_yaml",
1564        module: Some("parallel"),
1565        description: "Load multiple YAML files in parallel",
1566        params: &[LuaParam {
1567            name: "paths",
1568            typ: "string[]",
1569            description: "Paths to load",
1570            optional: false,
1571        }],
1572        returns: "(table<string, any>|nil)[]",
1573    },
1574    LuaFunction {
1575        name: "read_frontmatter",
1576        module: Some("parallel"),
1577        description: "Parse frontmatter from multiple files in parallel",
1578        params: &[LuaParam {
1579            name: "paths",
1580            typ: "string[]",
1581            description: "Paths to parse",
1582            optional: false,
1583        }],
1584        returns: "(FrontmatterResult|nil)[]",
1585    },
1586    LuaFunction {
1587        name: "map",
1588        module: Some("parallel"),
1589        description: "Map over items (structure for parallel-ready code)",
1590        params: &[
1591            LuaParam {
1592                name: "items",
1593                typ: "T[]",
1594                description: "Items to map",
1595                optional: false,
1596            },
1597            LuaParam {
1598                name: "fn",
1599                typ: "fun(item: T): U",
1600                description: "Mapping function",
1601                optional: false,
1602            },
1603        ],
1604        returns: "U[]",
1605    },
1606    LuaFunction {
1607        name: "filter",
1608        module: Some("parallel"),
1609        description: "Filter items using predicate",
1610        params: &[
1611            LuaParam {
1612                name: "items",
1613                typ: "T[]",
1614                description: "Items to filter",
1615                optional: false,
1616            },
1617            LuaParam {
1618                name: "fn",
1619                typ: "fun(item: T): boolean",
1620                description: "Predicate function",
1621                optional: false,
1622            },
1623        ],
1624        returns: "T[]",
1625    },
1626    LuaFunction {
1627        name: "reduce",
1628        module: Some("parallel"),
1629        description: "Reduce items to single value",
1630        params: &[
1631            LuaParam {
1632                name: "items",
1633                typ: "T[]",
1634                description: "Items to reduce",
1635                optional: false,
1636            },
1637            LuaParam {
1638                name: "initial",
1639                typ: "U",
1640                description: "Initial accumulator value",
1641                optional: false,
1642            },
1643            LuaParam {
1644                name: "fn",
1645                typ: "fun(acc: U, item: T): U",
1646                description: "Reducer function",
1647                optional: false,
1648            },
1649        ],
1650        returns: "U",
1651    },
1652    // ASYNC MODULE (tokio-backed)
1653    LuaFunction {
1654        name: "fetch",
1655        module: Some("async"),
1656        description: "Fetch URL (blocking)",
1657        params: &[
1658            LuaParam {
1659                name: "url",
1660                typ: "string",
1661                description: "URL to fetch",
1662                optional: false,
1663            },
1664            LuaParam {
1665                name: "options",
1666                typ: "FetchOptions",
1667                description: "Request options",
1668                optional: true,
1669            },
1670        ],
1671        returns: "FetchResponse",
1672    },
1673    LuaFunction {
1674        name: "fetch_json",
1675        module: Some("async"),
1676        description: "Fetch URL and parse as JSON",
1677        params: &[
1678            LuaParam {
1679                name: "url",
1680                typ: "string",
1681                description: "URL to fetch",
1682                optional: false,
1683            },
1684            LuaParam {
1685                name: "options",
1686                typ: "FetchOptions",
1687                description: "Request options",
1688                optional: true,
1689            },
1690        ],
1691        returns: "table",
1692    },
1693    LuaFunction {
1694        name: "fetch_all",
1695        module: Some("async"),
1696        description: "Fetch multiple URLs concurrently",
1697        params: &[LuaParam {
1698            name: "requests",
1699            typ: "(string|{url: string, options?: FetchOptions})[]",
1700            description: "URLs or request objects",
1701            optional: false,
1702        }],
1703        returns: "FetchResponse[]",
1704    },
1705    LuaFunction {
1706        name: "spawn",
1707        module: Some("async"),
1708        description: "Spawn async fetch task for later await",
1709        params: &[
1710            LuaParam {
1711                name: "url",
1712                typ: "string",
1713                description: "URL to fetch",
1714                optional: false,
1715            },
1716            LuaParam {
1717                name: "options",
1718                typ: "FetchOptions",
1719                description: "Request options",
1720                optional: true,
1721            },
1722        ],
1723        returns: "AsyncTask",
1724    },
1725    LuaFunction {
1726        name: "await",
1727        module: Some("async"),
1728        description: "Await spawned async task",
1729        params: &[LuaParam {
1730            name: "task",
1731            typ: "AsyncTask",
1732            description: "Task to await",
1733            optional: false,
1734        }],
1735        returns: "FetchResponse",
1736    },
1737    LuaFunction {
1738        name: "await_all",
1739        module: Some("async"),
1740        description: "Await multiple async tasks",
1741        params: &[LuaParam {
1742            name: "tasks",
1743            typ: "AsyncTask[]",
1744            description: "Tasks to await",
1745            optional: false,
1746        }],
1747        returns: "FetchResponse[]",
1748    },
1749    LuaFunction {
1750        name: "read_file",
1751        module: Some("async"),
1752        description: "Read file asynchronously",
1753        params: &[LuaParam {
1754            name: "path",
1755            typ: "string",
1756            description: "File path",
1757            optional: false,
1758        }],
1759        returns: "string",
1760    },
1761    LuaFunction {
1762        name: "write_file",
1763        module: Some("async"),
1764        description: "Write file asynchronously",
1765        params: &[
1766            LuaParam {
1767                name: "path",
1768                typ: "string",
1769                description: "File path",
1770                optional: false,
1771            },
1772            LuaParam {
1773                name: "content",
1774                typ: "string",
1775                description: "Content to write",
1776                optional: false,
1777            },
1778        ],
1779        returns: "boolean",
1780    },
1781    LuaFunction {
1782        name: "read_files",
1783        module: Some("async"),
1784        description: "Read multiple files concurrently",
1785        params: &[LuaParam {
1786            name: "paths",
1787            typ: "string[]",
1788            description: "File paths",
1789            optional: false,
1790        }],
1791        returns: "(string|nil)[]",
1792    },
1793    LuaFunction {
1794        name: "load_json",
1795        module: Some("async"),
1796        description: "Load and parse JSON file asynchronously",
1797        params: &[LuaParam {
1798            name: "path",
1799            typ: "string",
1800            description: "JSON file path",
1801            optional: false,
1802        }],
1803        returns: "table",
1804    },
1805    LuaFunction {
1806        name: "copy_file",
1807        module: Some("async"),
1808        description: "Copy file asynchronously",
1809        params: &[
1810            LuaParam {
1811                name: "src",
1812                typ: "string",
1813                description: "Source path",
1814                optional: false,
1815            },
1816            LuaParam {
1817                name: "dst",
1818                typ: "string",
1819                description: "Destination path",
1820                optional: false,
1821            },
1822        ],
1823        returns: "number",
1824    },
1825    LuaFunction {
1826        name: "rename",
1827        module: Some("async"),
1828        description: "Rename/move file or directory asynchronously",
1829        params: &[
1830            LuaParam {
1831                name: "src",
1832                typ: "string",
1833                description: "Source path",
1834                optional: false,
1835            },
1836            LuaParam {
1837                name: "dst",
1838                typ: "string",
1839                description: "Destination path",
1840                optional: false,
1841            },
1842        ],
1843        returns: "boolean",
1844    },
1845    LuaFunction {
1846        name: "create_dir",
1847        module: Some("async"),
1848        description: "Create directory (including parents) asynchronously",
1849        params: &[LuaParam {
1850            name: "path",
1851            typ: "string",
1852            description: "Directory path",
1853            optional: false,
1854        }],
1855        returns: "boolean",
1856    },
1857    LuaFunction {
1858        name: "remove_file",
1859        module: Some("async"),
1860        description: "Remove file asynchronously",
1861        params: &[LuaParam {
1862            name: "path",
1863            typ: "string",
1864            description: "File path",
1865            optional: false,
1866        }],
1867        returns: "boolean",
1868    },
1869    LuaFunction {
1870        name: "remove_dir",
1871        module: Some("async"),
1872        description: "Remove directory recursively asynchronously",
1873        params: &[LuaParam {
1874            name: "path",
1875            typ: "string",
1876            description: "Directory path",
1877            optional: false,
1878        }],
1879        returns: "boolean",
1880    },
1881    LuaFunction {
1882        name: "exists",
1883        module: Some("async"),
1884        description: "Check if file/directory exists asynchronously",
1885        params: &[LuaParam {
1886            name: "path",
1887            typ: "string",
1888            description: "Path to check",
1889            optional: false,
1890        }],
1891        returns: "boolean",
1892    },
1893    LuaFunction {
1894        name: "metadata",
1895        module: Some("async"),
1896        description: "Get file metadata asynchronously",
1897        params: &[LuaParam {
1898            name: "path",
1899            typ: "string",
1900            description: "File path",
1901            optional: false,
1902        }],
1903        returns: "FileMetadata",
1904    },
1905    LuaFunction {
1906        name: "read",
1907        module: Some("async"),
1908        description: "Read file as binary data asynchronously",
1909        params: &[LuaParam {
1910            name: "path",
1911            typ: "string",
1912            description: "File path",
1913            optional: false,
1914        }],
1915        returns: "string",
1916    },
1917    LuaFunction {
1918        name: "write",
1919        module: Some("async"),
1920        description: "Write binary data to file asynchronously",
1921        params: &[
1922            LuaParam {
1923                name: "path",
1924                typ: "string",
1925                description: "File path",
1926                optional: false,
1927            },
1928            LuaParam {
1929                name: "data",
1930                typ: "string",
1931                description: "Binary data to write",
1932                optional: false,
1933            },
1934        ],
1935        returns: "boolean",
1936    },
1937    LuaFunction {
1938        name: "fetch_bytes",
1939        module: Some("async"),
1940        description: "Fetch URL and return binary response body",
1941        params: &[
1942            LuaParam {
1943                name: "url",
1944                typ: "string",
1945                description: "URL to fetch",
1946                optional: false,
1947            },
1948            LuaParam {
1949                name: "options",
1950                typ: "FetchOptions",
1951                description: "Request options",
1952                optional: true,
1953            },
1954        ],
1955        returns: "FetchResponse",
1956    },
1957    LuaFunction {
1958        name: "read_dir",
1959        module: Some("async"),
1960        description: "List directory contents asynchronously",
1961        params: &[LuaParam {
1962            name: "path",
1963            typ: "string",
1964            description: "Directory path",
1965            optional: false,
1966        }],
1967        returns: "DirEntry[]",
1968    },
1969    LuaFunction {
1970        name: "canonicalize",
1971        module: Some("async"),
1972        description: "Get canonical/absolute path asynchronously",
1973        params: &[LuaParam {
1974            name: "path",
1975            typ: "string",
1976            description: "Path to canonicalize",
1977            optional: false,
1978        }],
1979        returns: "string",
1980    },
1981    // CRYPT MODULE
1982    LuaFunction {
1983        name: "encrypt",
1984        module: Some("crypt"),
1985        description: "Encrypt content using AES-256-GCM",
1986        params: &[
1987            LuaParam {
1988                name: "content",
1989                typ: "string",
1990                description: "Content to encrypt",
1991                optional: false,
1992            },
1993            LuaParam {
1994                name: "password",
1995                typ: "string",
1996                description: "Encryption password (uses SITE_PASSWORD env if not provided)",
1997                optional: true,
1998            },
1999        ],
2000        returns: "EncryptedData",
2001    },
2002    LuaFunction {
2003        name: "decrypt",
2004        module: Some("crypt"),
2005        description: "Decrypt content using AES-256-GCM",
2006        params: &[
2007            LuaParam {
2008                name: "data",
2009                typ: "EncryptedData",
2010                description: "Encrypted data table with ciphertext, salt, nonce",
2011                optional: false,
2012            },
2013            LuaParam {
2014                name: "password",
2015                typ: "string",
2016                description: "Decryption password (uses SITE_PASSWORD env if not provided)",
2017                optional: true,
2018            },
2019        ],
2020        returns: "string",
2021    },
2022    LuaFunction {
2023        name: "encrypt_html",
2024        module: Some("crypt"),
2025        description: "Encrypt content and wrap in HTML container for browser decryption",
2026        params: &[
2027            LuaParam {
2028                name: "content",
2029                typ: "string",
2030                description: "Content to encrypt (can be HTML)",
2031                optional: false,
2032            },
2033            LuaParam {
2034                name: "options",
2035                typ: "EncryptHtmlOptions",
2036                description: "Encryption options",
2037                optional: true,
2038            },
2039        ],
2040        returns: "string",
2041    },
2042];
2043
2044// ============================================================================
2045// GENERATION FUNCTIONS
2046// ============================================================================
2047
2048/// Generate EmmyLua type definitions
2049pub fn generate_emmylua() -> String {
2050    let mut output = String::new();
2051    output.push_str("---@meta rs-web\n\n");
2052    output.push_str("-- Auto-generated EmmyLua type definitions for rs-web\n");
2053    output.push_str("-- Generated with: rs-web types --lua\n");
2054    output.push_str("--\n");
2055    output.push_str("-- Usage:\n");
2056    output.push_str("--   local rs = require(\"rs-web\")\n");
2057    output.push_str("--   local content = rs.read_file(\"path/to/file.md\")\n");
2058    output.push_str("--   local html = rs.render_markdown(content)\n\n");
2059
2060    // Generate class definitions
2061    output.push_str(
2062        "-- =============================================================================\n",
2063    );
2064    output.push_str("-- TYPE DEFINITIONS\n");
2065    output.push_str(
2066        "-- =============================================================================\n\n",
2067    );
2068
2069    for class in LUA_CLASSES {
2070        output.push_str(&format!("---@class {}\n", class.name));
2071        for field in class.fields {
2072            output.push_str(&format!(
2073                "---@field {} {} {}\n",
2074                field.name, field.typ, field.description
2075            ));
2076        }
2077        output.push('\n');
2078    }
2079
2080    // Group functions by module
2081    let mut global_fns: Vec<&LuaFunction> = Vec::new();
2082    let mut coro_fns: Vec<&LuaFunction> = Vec::new();
2083    let mut parallel_fns: Vec<&LuaFunction> = Vec::new();
2084    let mut async_fns: Vec<&LuaFunction> = Vec::new();
2085    let mut crypt_fns: Vec<&LuaFunction> = Vec::new();
2086
2087    for func in LUA_FUNCTIONS {
2088        match func.module {
2089            None => global_fns.push(func),
2090            Some("coro") => coro_fns.push(func),
2091            Some("parallel") => parallel_fns.push(func),
2092            Some("async") => async_fns.push(func),
2093            Some("crypt") => crypt_fns.push(func),
2094            _ => global_fns.push(func),
2095        }
2096    }
2097
2098    // Generate coro submodule class
2099    output.push_str(
2100        "-- =============================================================================\n",
2101    );
2102    output.push_str("-- CORO SUBMODULE\n");
2103    output.push_str(
2104        "-- =============================================================================\n\n",
2105    );
2106    output.push_str("---@class RsCoroModule\n");
2107    for func in &coro_fns {
2108        let params = func
2109            .params
2110            .iter()
2111            .map(|p| {
2112                let opt = if p.optional { "?" } else { "" };
2113                format!("{}{}: {}", p.name, opt, p.typ)
2114            })
2115            .collect::<Vec<_>>()
2116            .join(", ");
2117        output.push_str(&format!(
2118            "---@field {} fun({}): {} {}\n",
2119            func.name, params, func.returns, func.description
2120        ));
2121    }
2122    output.push('\n');
2123
2124    // Generate parallel submodule class
2125    output.push_str(
2126        "-- =============================================================================\n",
2127    );
2128    output.push_str("-- PARALLEL SUBMODULE\n");
2129    output.push_str(
2130        "-- =============================================================================\n\n",
2131    );
2132    output.push_str("---@class RsParallelModule\n");
2133    for func in &parallel_fns {
2134        let params = func
2135            .params
2136            .iter()
2137            .map(|p| {
2138                let opt = if p.optional { "?" } else { "" };
2139                format!("{}{}: {}", p.name, opt, p.typ)
2140            })
2141            .collect::<Vec<_>>()
2142            .join(", ");
2143        output.push_str(&format!(
2144            "---@field {} fun({}): {} {}\n",
2145            func.name, params, func.returns, func.description
2146        ));
2147    }
2148    output.push('\n');
2149
2150    // Generate async submodule class
2151    output.push_str(
2152        "-- =============================================================================\n",
2153    );
2154    output.push_str("-- ASYNC SUBMODULE (tokio-backed)\n");
2155    output.push_str(
2156        "-- =============================================================================\n\n",
2157    );
2158    output.push_str("---@class RsAsyncModule\n");
2159    for func in &async_fns {
2160        let params = func
2161            .params
2162            .iter()
2163            .map(|p| {
2164                let opt = if p.optional { "?" } else { "" };
2165                format!("{}{}: {}", p.name, opt, p.typ)
2166            })
2167            .collect::<Vec<_>>()
2168            .join(", ");
2169        output.push_str(&format!(
2170            "---@field {} fun({}): {} {}\n",
2171            func.name, params, func.returns, func.description
2172        ));
2173    }
2174    output.push('\n');
2175
2176    // Generate crypt submodule class
2177    output.push_str(
2178        "-- =============================================================================\n",
2179    );
2180    output.push_str("-- CRYPT SUBMODULE\n");
2181    output.push_str(
2182        "-- =============================================================================\n\n",
2183    );
2184    output.push_str("---@class RsCryptModule\n");
2185    for func in &crypt_fns {
2186        let params = func
2187            .params
2188            .iter()
2189            .map(|p| {
2190                let opt = if p.optional { "?" } else { "" };
2191                format!("{}{}: {}", p.name, opt, p.typ)
2192            })
2193            .collect::<Vec<_>>()
2194            .join(", ");
2195        output.push_str(&format!(
2196            "---@field {} fun({}): {} {}\n",
2197            func.name, params, func.returns, func.description
2198        ));
2199    }
2200    output.push('\n');
2201
2202    // Generate main rs module class
2203    output.push_str(
2204        "-- =============================================================================\n",
2205    );
2206    output.push_str("-- RS-WEB MODULE\n");
2207    output.push_str(
2208        "-- =============================================================================\n\n",
2209    );
2210    output.push_str("---@class RsWebModule\n");
2211    output.push_str("---@field _VERSION string Module version\n");
2212    output.push_str("---@field _SANDBOX boolean Whether sandbox mode is enabled\n");
2213    output.push_str("---@field _PROJECT_ROOT string Project root directory\n");
2214    output.push_str("---@field coro RsCoroModule Coroutine helpers\n");
2215    output.push_str("---@field parallel RsParallelModule Parallel processing functions\n");
2216    output.push_str("---@field async RsAsyncModule Async I/O functions (tokio-backed)\n");
2217    output.push_str("---@field crypt RsCryptModule Encryption functions (AES-256-GCM)\n");
2218
2219    // Add all global functions as fields
2220    for func in &global_fns {
2221        let params = func
2222            .params
2223            .iter()
2224            .map(|p| {
2225                let opt = if p.optional { "?" } else { "" };
2226                format!("{}{}: {}", p.name, opt, p.typ)
2227            })
2228            .collect::<Vec<_>>()
2229            .join(", ");
2230        output.push_str(&format!(
2231            "---@field {} fun({}): {} {}\n",
2232            func.name, params, func.returns, func.description
2233        ));
2234    }
2235    output.push('\n');
2236
2237    // Create the rs table
2238    output.push_str("---The rs-web module\n");
2239    output.push_str("---@type RsWebModule\n");
2240    output.push_str("local rs = {}\n\n");
2241
2242    // Generate function stubs for better IDE completion
2243    output.push_str(
2244        "-- =============================================================================\n",
2245    );
2246    output.push_str("-- FUNCTION STUBS (for IDE completion)\n");
2247    output.push_str(
2248        "-- =============================================================================\n\n",
2249    );
2250
2251    for func in &global_fns {
2252        output.push_str(&format!("---{}\n", func.description));
2253        for param in func.params {
2254            let opt = if param.optional { "?" } else { "" };
2255            output.push_str(&format!(
2256                "---@param {}{} {} {}\n",
2257                param.name, opt, param.typ, param.description
2258            ));
2259        }
2260        output.push_str(&format!("---@return {}\n", func.returns));
2261
2262        let params = func
2263            .params
2264            .iter()
2265            .map(|p| p.name.to_string())
2266            .collect::<Vec<_>>()
2267            .join(", ");
2268        output.push_str(&format!("function rs.{}({}) end\n\n", func.name, params));
2269    }
2270
2271    // Coro submodule stubs
2272    output.push_str("-- Coro submodule\n");
2273    output.push_str("rs.coro = {}\n\n");
2274
2275    for func in &coro_fns {
2276        output.push_str(&format!("---{}\n", func.description));
2277        for param in func.params {
2278            let opt = if param.optional { "?" } else { "" };
2279            output.push_str(&format!(
2280                "---@param {}{} {} {}\n",
2281                param.name, opt, param.typ, param.description
2282            ));
2283        }
2284        output.push_str(&format!("---@return {}\n", func.returns));
2285
2286        let params = func
2287            .params
2288            .iter()
2289            .map(|p| p.name.to_string())
2290            .collect::<Vec<_>>()
2291            .join(", ");
2292        output.push_str(&format!(
2293            "function rs.coro.{}({}) end\n\n",
2294            func.name, params
2295        ));
2296    }
2297
2298    // Parallel submodule stubs
2299    output.push_str("-- Parallel submodule\n");
2300    output.push_str("rs.parallel = {}\n\n");
2301
2302    for func in &parallel_fns {
2303        output.push_str(&format!("---{}\n", func.description));
2304        for param in func.params {
2305            let opt = if param.optional { "?" } else { "" };
2306            output.push_str(&format!(
2307                "---@param {}{} {} {}\n",
2308                param.name, opt, param.typ, param.description
2309            ));
2310        }
2311        output.push_str(&format!("---@return {}\n", func.returns));
2312
2313        let params = func
2314            .params
2315            .iter()
2316            .map(|p| p.name.to_string())
2317            .collect::<Vec<_>>()
2318            .join(", ");
2319        output.push_str(&format!(
2320            "function rs.parallel.{}({}) end\n\n",
2321            func.name, params
2322        ));
2323    }
2324
2325    // Async submodule stubs
2326    output.push_str("-- Async submodule (tokio-backed)\n");
2327    output.push_str("rs.async = {}\n\n");
2328
2329    for func in &async_fns {
2330        output.push_str(&format!("---{}\n", func.description));
2331        for param in func.params {
2332            let opt = if param.optional { "?" } else { "" };
2333            output.push_str(&format!(
2334                "---@param {}{} {} {}\n",
2335                param.name, opt, param.typ, param.description
2336            ));
2337        }
2338        output.push_str(&format!("---@return {}\n", func.returns));
2339
2340        let params = func
2341            .params
2342            .iter()
2343            .map(|p| p.name.to_string())
2344            .collect::<Vec<_>>()
2345            .join(", ");
2346        output.push_str(&format!(
2347            "function rs.async.{}({}) end\n\n",
2348            func.name, params
2349        ));
2350    }
2351
2352    // Crypt submodule stubs
2353    output.push_str("-- Crypt submodule (AES-256-GCM encryption)\n");
2354    output.push_str("rs.crypt = {}\n\n");
2355
2356    for func in &crypt_fns {
2357        output.push_str(&format!("---{}\n", func.description));
2358        for param in func.params {
2359            let opt = if param.optional { "?" } else { "" };
2360            output.push_str(&format!(
2361                "---@param {}{} {} {}\n",
2362                param.name, opt, param.typ, param.description
2363            ));
2364        }
2365        output.push_str(&format!("---@return {}\n", func.returns));
2366
2367        let params = func
2368            .params
2369            .iter()
2370            .map(|p| p.name.to_string())
2371            .collect::<Vec<_>>()
2372            .join(", ");
2373        output.push_str(&format!(
2374            "function rs.crypt.{}({}) end\n\n",
2375            func.name, params
2376        ));
2377    }
2378
2379    output.push_str("return rs\n");
2380
2381    output
2382}
2383
2384/// Generate Markdown API documentation
2385pub fn generate_markdown() -> String {
2386    let mut output = String::new();
2387    output.push_str("# rs-web Lua API Reference\n\n");
2388    output.push_str("Auto-generated documentation for rs-web Lua functions.\n\n");
2389    output.push_str("## Usage\n\n");
2390    output.push_str("```lua\n");
2391    output.push_str("local rs = require(\"rs-web\")\n");
2392    output.push_str("local content = rs.read_file(\"path/to/file.md\")\n");
2393    output.push_str("local html = rs.render_markdown(content)\n");
2394    output.push_str("```\n\n");
2395    output.push_str("## Table of Contents\n\n");
2396    output.push_str("- [Types](#types)\n");
2397    output.push_str("- [File Operations](#file-operations)\n");
2398    output.push_str("- [Search](#search)\n");
2399    output.push_str("- [Collections](#collections)\n");
2400    output.push_str("- [Text Processing](#text-processing)\n");
2401    output.push_str("- [Path Utilities](#path-utilities)\n");
2402    output.push_str("- [Environment](#environment)\n");
2403    output.push_str("- [Git](#git)\n");
2404    output.push_str("- [Content Processing](#content-processing)\n");
2405    output.push_str("- [Image Processing](#image-processing)\n");
2406    output.push_str("- [Coro Module](#coro-module)\n");
2407    output.push_str("- [Parallel Module](#parallel-module)\n");
2408    output.push_str("- [Async Module](#async-module)\n");
2409    output.push_str("- [Crypt Module](#crypt-module)\n\n");
2410
2411    // Types section
2412    output.push_str("## Types\n\n");
2413    for class in LUA_CLASSES {
2414        output.push_str(&format!("### {}\n\n", class.name));
2415        output.push_str(&format!("{}\n\n", class.description));
2416        output.push_str("| Field | Type | Description |\n");
2417        output.push_str("|-------|------|-------------|\n");
2418        for field in class.fields {
2419            output.push_str(&format!(
2420                "| `{}` | `{}` | {} |\n",
2421                field.name, field.typ, field.description
2422            ));
2423        }
2424        output.push('\n');
2425    }
2426
2427    // Group functions by category
2428    let categories = [
2429        (
2430            "File Operations",
2431            vec![
2432                "read_file",
2433                "write_file",
2434                "copy_file",
2435                "file_exists",
2436                "list_files",
2437                "list_dirs",
2438                "load_json",
2439                "load_yaml",
2440                "load_toml",
2441                "read_frontmatter",
2442            ],
2443        ),
2444        ("Search", vec!["glob", "scan"]),
2445        (
2446            "Collections",
2447            vec![
2448                "filter", "sort", "map", "find", "group_by", "unique", "reverse", "take", "skip",
2449                "keys", "values",
2450            ],
2451        ),
2452        (
2453            "Text Processing",
2454            vec![
2455                "slugify",
2456                "word_count",
2457                "reading_time",
2458                "truncate",
2459                "strip_tags",
2460                "format_date",
2461                "parse_date",
2462                "hash",
2463                "hash_file",
2464                "url_encode",
2465                "url_decode",
2466            ],
2467        ),
2468        (
2469            "Path Utilities",
2470            vec!["join_path", "basename", "dirname", "extension"],
2471        ),
2472        ("Environment", vec!["env", "print", "is_gitignored"]),
2473        ("Git", vec!["git_info"]),
2474        (
2475            "Content Processing",
2476            vec![
2477                "render_markdown",
2478                "rss_date",
2479                "extract_links_markdown",
2480                "extract_links_html",
2481                "extract_images_markdown",
2482                "extract_images_html",
2483                "html_to_text",
2484            ],
2485        ),
2486        (
2487            "Image Processing",
2488            vec![
2489                "image_dimensions",
2490                "image_resize",
2491                "image_convert",
2492                "image_optimize",
2493            ],
2494        ),
2495        (
2496            "Assets",
2497            vec!["build_css", "check_unused_assets", "download_google_font"],
2498        ),
2499    ];
2500
2501    for (cat_name, func_names) in &categories {
2502        output.push_str(&format!("## {}\n\n", cat_name));
2503
2504        for func_name in func_names {
2505            if let Some(func) = LUA_FUNCTIONS
2506                .iter()
2507                .find(|f| f.name == *func_name && f.module.is_none())
2508            {
2509                output.push_str(&format!("### `rs.{}()`\n\n", func.name));
2510                output.push_str(&format!("{}\n\n", func.description));
2511
2512                if !func.params.is_empty() {
2513                    output.push_str("**Parameters:**\n\n");
2514                    for param in func.params {
2515                        let opt = if param.optional { " (optional)" } else { "" };
2516                        output.push_str(&format!(
2517                            "- `{}`: `{}`{} - {}\n",
2518                            param.name, param.typ, opt, param.description
2519                        ));
2520                    }
2521                    output.push('\n');
2522                }
2523
2524                output.push_str(&format!("**Returns:** `{}`\n\n", func.returns));
2525            }
2526        }
2527    }
2528
2529    // Coro module
2530    output.push_str("## Coro Module\n\n");
2531    output.push_str("Coroutine-based cooperative multitasking helpers.\n\n");
2532    for func in LUA_FUNCTIONS.iter().filter(|f| f.module == Some("coro")) {
2533        output.push_str(&format!("### `rs.coro.{}()`\n\n", func.name));
2534        output.push_str(&format!("{}\n\n", func.description));
2535
2536        if !func.params.is_empty() {
2537            output.push_str("**Parameters:**\n\n");
2538            for param in func.params {
2539                let opt = if param.optional { " (optional)" } else { "" };
2540                output.push_str(&format!(
2541                    "- `{}`: `{}`{} - {}\n",
2542                    param.name, param.typ, opt, param.description
2543                ));
2544            }
2545            output.push('\n');
2546        }
2547
2548        output.push_str(&format!("**Returns:** `{}`\n\n", func.returns));
2549    }
2550
2551    // Parallel module
2552    output.push_str("## Parallel Module\n\n");
2553    output.push_str("True parallel processing with Rayon.\n\n");
2554    for func in LUA_FUNCTIONS
2555        .iter()
2556        .filter(|f| f.module == Some("parallel"))
2557    {
2558        output.push_str(&format!("### `rs.parallel.{}()`\n\n", func.name));
2559        output.push_str(&format!("{}\n\n", func.description));
2560
2561        if !func.params.is_empty() {
2562            output.push_str("**Parameters:**\n\n");
2563            for param in func.params {
2564                let opt = if param.optional { " (optional)" } else { "" };
2565                output.push_str(&format!(
2566                    "- `{}`: `{}`{} - {}\n",
2567                    param.name, param.typ, opt, param.description
2568                ));
2569            }
2570            output.push('\n');
2571        }
2572
2573        output.push_str(&format!("**Returns:** `{}`\n\n", func.returns));
2574    }
2575
2576    // Async module
2577    output.push_str("## Async Module\n\n");
2578    output.push_str("Async I/O operations backed by Tokio.\n\n");
2579    for func in LUA_FUNCTIONS.iter().filter(|f| f.module == Some("async")) {
2580        output.push_str(&format!("### `rs.async.{}()`\n\n", func.name));
2581        output.push_str(&format!("{}\n\n", func.description));
2582
2583        if !func.params.is_empty() {
2584            output.push_str("**Parameters:**\n\n");
2585            for param in func.params {
2586                let opt = if param.optional { " (optional)" } else { "" };
2587                output.push_str(&format!(
2588                    "- `{}`: `{}`{} - {}\n",
2589                    param.name, param.typ, opt, param.description
2590                ));
2591            }
2592            output.push('\n');
2593        }
2594
2595        output.push_str(&format!("**Returns:** `{}`\n\n", func.returns));
2596    }
2597
2598    // Crypt module
2599    output.push_str("## Crypt Module\n\n");
2600    output.push_str("Encryption functions using AES-256-GCM with Argon2id key derivation.\n\n");
2601    for func in LUA_FUNCTIONS.iter().filter(|f| f.module == Some("crypt")) {
2602        output.push_str(&format!("### `rs.crypt.{}()`\n\n", func.name));
2603        output.push_str(&format!("{}\n\n", func.description));
2604
2605        if !func.params.is_empty() {
2606            output.push_str("**Parameters:**\n\n");
2607            for param in func.params {
2608                let opt = if param.optional { " (optional)" } else { "" };
2609                output.push_str(&format!(
2610                    "- `{}`: `{}`{} - {}\n",
2611                    param.name, param.typ, opt, param.description
2612                ));
2613            }
2614            output.push('\n');
2615        }
2616
2617        output.push_str(&format!("**Returns:** `{}`\n\n", func.returns));
2618    }
2619
2620    output
2621}