rs_web/lua/
types.rs

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