@promptbook/cli 0.48.0-0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.es.js CHANGED
@@ -143,7 +143,86 @@ new Function("\n try {\n if (typeof WorkerGlobalScope !== 'undefined'
143
143
  /**
144
144
  * The version of the Promptbook library
145
145
  */
146
- var PROMPTBOOK_VERSION = '0.47.0';
146
+ var PROMPTBOOK_VERSION = '0.48.0-1';
147
+
148
+ /**
149
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
150
+ */
151
+ var PromptbookSyntaxError = /** @class */ (function (_super) {
152
+ __extends(PromptbookSyntaxError, _super);
153
+ function PromptbookSyntaxError(message) {
154
+ var _this = _super.call(this, message) || this;
155
+ _this.name = 'PromptbookSyntaxError';
156
+ Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
157
+ return _this;
158
+ }
159
+ return PromptbookSyntaxError;
160
+ }(Error));
161
+
162
+ /**
163
+ * Supported script languages
164
+ */
165
+ var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
166
+
167
+ /**
168
+ * Parses the template and returns the list of all parameter names
169
+ *
170
+ * @param template the template with parameters in {curly} braces
171
+ * @returns the list of parameter names
172
+ *
173
+ * @private within the library
174
+ */
175
+ function extractParameters(template) {
176
+ var e_1, _a;
177
+ var matches = template.matchAll(/{\w+}/g);
178
+ var parameterNames = [];
179
+ try {
180
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
181
+ var match = matches_1_1.value;
182
+ var parameterName = match[0].slice(1, -1);
183
+ if (!parameterNames.includes(parameterName)) {
184
+ parameterNames.push(parameterName);
185
+ }
186
+ }
187
+ }
188
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
189
+ finally {
190
+ try {
191
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
192
+ }
193
+ finally { if (e_1) throw e_1.error; }
194
+ }
195
+ return parameterNames;
196
+ }
197
+
198
+ /**
199
+ * Computes the deepness of the markdown structure.
200
+ *
201
+ * @private within the library
202
+ */
203
+ function countMarkdownStructureDeepness(markdownStructure) {
204
+ var e_1, _a;
205
+ var maxDeepness = 0;
206
+ try {
207
+ for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
208
+ var section = _c.value;
209
+ maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
210
+ }
211
+ }
212
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
213
+ finally {
214
+ try {
215
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
216
+ }
217
+ finally { if (e_1) throw e_1.error; }
218
+ }
219
+ return maxDeepness + 1;
220
+ }
221
+
222
+ /**
223
+ * The maximum number of iterations for a loops
224
+ */
225
+ var LOOP_LIMIT = 1000;
147
226
 
148
227
  /**
149
228
  * This error type indicates that the error should not happen and its last check before crashing with some other error
@@ -159,6 +238,301 @@ var UnexpectedError = /** @class */ (function (_super) {
159
238
  return UnexpectedError;
160
239
  }(Error));
161
240
 
241
+ /**
242
+ * Parse a markdown string into a MarkdownStructure object.
243
+ *
244
+ * Note: This function does work with code blocks
245
+ * Note: This function does not work with markdown comments
246
+ *
247
+ * @param markdown The markdown string to parse.
248
+ * @returns The MarkdownStructure object.
249
+ *
250
+ * @private within the library
251
+ */
252
+ function markdownToMarkdownStructure(markdown) {
253
+ var e_1, _a;
254
+ var lines = markdown.split('\n');
255
+ var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
256
+ var current = root;
257
+ var isInsideCodeBlock = false;
258
+ try {
259
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
260
+ var line = lines_1_1.value;
261
+ var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
262
+ if (isInsideCodeBlock || !headingMatch) {
263
+ if (line.startsWith('```')) {
264
+ isInsideCodeBlock = !isInsideCodeBlock;
265
+ }
266
+ current.contentLines.push(line);
267
+ }
268
+ else {
269
+ var level = headingMatch.groups.mark.length;
270
+ var title = headingMatch.groups.title.trim();
271
+ var parent_1 = void 0;
272
+ if (level > current.level) {
273
+ // Note: Going deeper (next section is child of current)
274
+ parent_1 = current;
275
+ }
276
+ else {
277
+ // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
278
+ parent_1 = current;
279
+ var loopLimit = LOOP_LIMIT;
280
+ while (parent_1.level !== level - 1) {
281
+ if (loopLimit-- < 0) {
282
+ throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
283
+ }
284
+ if (parent_1.parent === null /* <- Note: We are in root */) {
285
+ // [🌻]
286
+ throw new Error(spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
287
+ }
288
+ parent_1 = parent_1.parent;
289
+ }
290
+ }
291
+ var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
292
+ parent_1.sections.push(section);
293
+ current = section;
294
+ }
295
+ }
296
+ }
297
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
298
+ finally {
299
+ try {
300
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
301
+ }
302
+ finally { if (e_1) throw e_1.error; }
303
+ }
304
+ if (root.sections.length === 1) {
305
+ var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
306
+ return markdownStructure;
307
+ }
308
+ // [🌻]
309
+ throw new Error('The markdown file must have exactly one top-level section.');
310
+ // return root;
311
+ }
312
+ /**
313
+ * @private
314
+ */
315
+ function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
316
+ var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
317
+ return {
318
+ level: level,
319
+ title: title,
320
+ content: spaceTrim(contentLines.join('\n')),
321
+ sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
322
+ };
323
+ }
324
+
325
+ /**
326
+ * Utility function to extract all list items from markdown
327
+ *
328
+ * Note: It works with both ul and ol
329
+ * Note: It omits list items in code blocks
330
+ * Note: It flattens nested lists
331
+ * Note: It can not work with html syntax and comments
332
+ *
333
+ * @param markdown any valid markdown
334
+ * @returns
335
+ */
336
+ function extractAllListItemsFromMarkdown(markdown) {
337
+ var e_1, _a;
338
+ var lines = markdown.split('\n');
339
+ var listItems = [];
340
+ var isInCodeBlock = false;
341
+ try {
342
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
343
+ var line = lines_1_1.value;
344
+ var trimmedLine = line.trim();
345
+ if (trimmedLine.startsWith('```')) {
346
+ isInCodeBlock = !isInCodeBlock;
347
+ }
348
+ if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
349
+ var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
350
+ listItems.push(listItem);
351
+ }
352
+ }
353
+ }
354
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
355
+ finally {
356
+ try {
357
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
358
+ }
359
+ finally { if (e_1) throw e_1.error; }
360
+ }
361
+ return listItems;
362
+ }
363
+
364
+ /**
365
+ * Makes first letter of a string uppercase
366
+ *
367
+ */
368
+ function capitalize(word) {
369
+ return word.substring(0, 1).toUpperCase() + word.substring(1);
370
+ }
371
+
372
+ /**
373
+ * Extracts all code blocks from markdown.
374
+ *
375
+ * Note: There are 3 simmilar function:
376
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
377
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
378
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
379
+ *
380
+ * @param markdown any valid markdown
381
+ * @returns code blocks with language and content
382
+ *
383
+ */
384
+ function extractAllBlocksFromMarkdown(markdown) {
385
+ var e_1, _a;
386
+ var codeBlocks = [];
387
+ var lines = markdown.split('\n');
388
+ var currentCodeBlock = null;
389
+ try {
390
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
391
+ var line = lines_1_1.value;
392
+ if (line.startsWith('```')) {
393
+ var language = line.slice(3).trim() || null;
394
+ if (currentCodeBlock === null) {
395
+ currentCodeBlock = { language: language, content: '' };
396
+ }
397
+ else {
398
+ if (language !== null) {
399
+ // [🌻]
400
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
401
+ }
402
+ codeBlocks.push(currentCodeBlock);
403
+ currentCodeBlock = null;
404
+ }
405
+ }
406
+ else if (currentCodeBlock !== null) {
407
+ if (currentCodeBlock.content !== '') {
408
+ currentCodeBlock.content += '\n';
409
+ }
410
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
411
+ }
412
+ }
413
+ }
414
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
415
+ finally {
416
+ try {
417
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
418
+ }
419
+ finally { if (e_1) throw e_1.error; }
420
+ }
421
+ if (currentCodeBlock !== null) {
422
+ // [🌻]
423
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
424
+ }
425
+ return codeBlocks;
426
+ }
427
+
428
+ /**
429
+ * Extracts exactly ONE code block from markdown.
430
+ *
431
+ * Note: If there are multiple or no code blocks the function throws an error
432
+ *
433
+ * Note: There are 3 simmilar function:
434
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
435
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
436
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
437
+ *
438
+ * @param markdown any valid markdown
439
+ * @returns code block with language and content
440
+ */
441
+ function extractOneBlockFromMarkdown(markdown) {
442
+ var codeBlocks = extractAllBlocksFromMarkdown(markdown);
443
+ if (codeBlocks.length !== 1) {
444
+ // TODO: Report more specific place where the error happened
445
+ throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
446
+ }
447
+ return codeBlocks[0];
448
+ }
449
+ /***
450
+ * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
451
+ */
452
+
453
+ /**
454
+ * Removes HTML or Markdown comments from a string.
455
+ *
456
+ * @param {string} content - The string to remove comments from.
457
+ * @returns {string} The input string with all comments removed.
458
+ */
459
+ function removeContentComments(content) {
460
+ return spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
461
+ }
462
+
463
+ /**
464
+ * Parses the given script and returns the list of all used variables that are not defined in the script
465
+ *
466
+ * @param script from which to extract the variables
467
+ * @returns the list of variable names
468
+ * @throws {PromptbookSyntaxError} if the script is invalid
469
+ *
470
+ * @private within the promptbookStringToJson
471
+ */
472
+ function extractVariables(script) {
473
+ var variables = [];
474
+ script = "(()=>{".concat(script, "})()");
475
+ try {
476
+ for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
477
+ try {
478
+ eval(script);
479
+ }
480
+ catch (error) {
481
+ if (!(error instanceof ReferenceError)) {
482
+ throw error;
483
+ }
484
+ var undefinedName = error.message.split(' ')[0];
485
+ /*
486
+ Note: Remapping error
487
+ From: [ReferenceError: thing is not defined],
488
+ To: [Error: Parameter {thing} is not defined],
489
+ */
490
+ if (!undefinedName) {
491
+ throw error;
492
+ }
493
+ if (script.includes(undefinedName + '(')) {
494
+ script = "const ".concat(undefinedName, " = ()=>'';") + script;
495
+ }
496
+ else {
497
+ variables.push(undefinedName);
498
+ script = "const ".concat(undefinedName, " = '';") + script;
499
+ }
500
+ }
501
+ }
502
+ catch (error) {
503
+ if (!(error instanceof Error)) {
504
+ throw error;
505
+ }
506
+ throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
507
+ }
508
+ return variables;
509
+ }
510
+
511
+ /**
512
+ * Removes emojis from a string and fix whitespaces
513
+ *
514
+ * @param text with emojis
515
+ * @returns text without emojis
516
+ */
517
+ function removeEmojis(text) {
518
+ // Replace emojis (and also ZWJ sequence) with hyphens
519
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
520
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
521
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
522
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
523
+ return text;
524
+ }
525
+
526
+ /**
527
+ * Function normalizes title to name which can be used as identifier
528
+ */
529
+ function titleToName(value) {
530
+ value = removeEmojis(value);
531
+ value = normalizeToKebabCase(value);
532
+ // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
533
+ return value;
534
+ }
535
+
162
536
  /**
163
537
  * Creates a Mermaid graph based on the promptbook
164
538
  *
@@ -177,7 +551,7 @@ function renderPromptbookMermaid(promptbookJson) {
177
551
  if (!template) {
178
552
  throw new Error("Could not find template for {".concat(parameterName, "}"));
179
553
  }
180
- return 'template' + normalizeTo_PascalCase(template.title);
554
+ return normalizeTo_camelCase('template-' + titleToName(template.title));
181
555
  };
182
556
  var promptbookMermaid = spaceTrim(function (block) { return "\n\n %% \uD83D\uDD2E Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually\n\n flowchart LR\n subgraph \"".concat(promptbookJson.title, "\"\n\n direction TB\n\n input((Input)):::input\n ").concat(block(promptbookJson.promptTemplates
183
557
  .flatMap(function (_a) {
@@ -198,6 +572,7 @@ function renderPromptbookMermaid(promptbookJson) {
198
572
  return "".concat(parameterNameToTemplateName(name), "--\"{").concat(name, "}\"-->output");
199
573
  })
200
574
  .join('\n')), "\n output((Output)):::output\n\n classDef input color: grey;\n classDef output color: grey;\n\n end;\n\n "); });
575
+ // TODO: !!!!! Allow to put link callback into `renderPromptbookMermaid`
201
576
  return promptbookMermaid;
202
577
  }
203
578
  /**
@@ -205,20 +580,6 @@ function renderPromptbookMermaid(promptbookJson) {
205
580
  * TODO: [🕌] When more than 2 functionalities, split into separate functions
206
581
  */
207
582
 
208
- /**
209
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
210
- */
211
- var PromptbookSyntaxError = /** @class */ (function (_super) {
212
- __extends(PromptbookSyntaxError, _super);
213
- function PromptbookSyntaxError(message) {
214
- var _this = _super.call(this, message) || this;
215
- _this.name = 'PromptbookSyntaxError';
216
- Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
217
- return _this;
218
- }
219
- return PromptbookSyntaxError;
220
- }(Error));
221
-
222
583
  /**
223
584
  * Function parseNumber will parse number from string
224
585
  *
@@ -560,9 +921,14 @@ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
560
921
  */
561
922
 
562
923
  /**
563
- * The maximum number of iterations for a loops
924
+ *
564
925
  */
565
- var LOOP_LIMIT = 1000;
926
+ function removeDiacritics(input) {
927
+ /*eslint no-control-regex: "off"*/
928
+ return input.replace(/[^\u0000-\u007E]/g, function (a) {
929
+ return DIACRITIC_VARIANTS_LETTERS[a] || a;
930
+ });
931
+ }
566
932
 
567
933
  /**
568
934
  * This error occurs during the parameter replacement in the template
@@ -600,154 +966,16 @@ function prettifyMarkdown(html) {
600
966
  printWidth: 120,
601
967
  htmlWhitespaceSensitivity: 'ignore',
602
968
  jsxBracketSameLine: false,
603
- bracketSpacing: true,
604
- });
605
- }
606
- catch (error) {
607
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
608
- error: error,
609
- html: html,
610
- });
611
- return html;
612
- }
613
- }
614
-
615
- /**
616
- * Makes first letter of a string uppercase
617
- *
618
- */
619
- function capitalize(word) {
620
- return word.substring(0, 1).toUpperCase() + word.substring(1);
621
- }
622
-
623
- /**
624
- * Extracts all code blocks from markdown.
625
- *
626
- * Note: There are 3 simmilar function:
627
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
628
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
629
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
630
- *
631
- * @param markdown any valid markdown
632
- * @returns code blocks with language and content
633
- *
634
- */
635
- function extractAllBlocksFromMarkdown(markdown) {
636
- var e_1, _a;
637
- var codeBlocks = [];
638
- var lines = markdown.split('\n');
639
- var currentCodeBlock = null;
640
- try {
641
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
642
- var line = lines_1_1.value;
643
- if (line.startsWith('```')) {
644
- var language = line.slice(3).trim() || null;
645
- if (currentCodeBlock === null) {
646
- currentCodeBlock = { language: language, content: '' };
647
- }
648
- else {
649
- if (language !== null) {
650
- // [🌻]
651
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
652
- }
653
- codeBlocks.push(currentCodeBlock);
654
- currentCodeBlock = null;
655
- }
656
- }
657
- else if (currentCodeBlock !== null) {
658
- if (currentCodeBlock.content !== '') {
659
- currentCodeBlock.content += '\n';
660
- }
661
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
662
- }
663
- }
664
- }
665
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
666
- finally {
667
- try {
668
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
669
- }
670
- finally { if (e_1) throw e_1.error; }
671
- }
672
- if (currentCodeBlock !== null) {
673
- // [🌻]
674
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
675
- }
676
- return codeBlocks;
677
- }
678
-
679
- /**
680
- * Utility function to extract all list items from markdown
681
- *
682
- * Note: It works with both ul and ol
683
- * Note: It omits list items in code blocks
684
- * Note: It flattens nested lists
685
- * Note: It can not work with html syntax and comments
686
- *
687
- * @param markdown any valid markdown
688
- * @returns
689
- */
690
- function extractAllListItemsFromMarkdown(markdown) {
691
- var e_1, _a;
692
- var lines = markdown.split('\n');
693
- var listItems = [];
694
- var isInCodeBlock = false;
695
- try {
696
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
697
- var line = lines_1_1.value;
698
- var trimmedLine = line.trim();
699
- if (trimmedLine.startsWith('```')) {
700
- isInCodeBlock = !isInCodeBlock;
701
- }
702
- if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
703
- var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
704
- listItems.push(listItem);
705
- }
706
- }
707
- }
708
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
709
- finally {
710
- try {
711
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
712
- }
713
- finally { if (e_1) throw e_1.error; }
714
- }
715
- return listItems;
716
- }
717
-
718
- /**
719
- * Extracts exactly ONE code block from markdown.
720
- *
721
- * Note: If there are multiple or no code blocks the function throws an error
722
- *
723
- * Note: There are 3 simmilar function:
724
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
725
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
726
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
727
- *
728
- * @param markdown any valid markdown
729
- * @returns code block with language and content
730
- */
731
- function extractOneBlockFromMarkdown(markdown) {
732
- var codeBlocks = extractAllBlocksFromMarkdown(markdown);
733
- if (codeBlocks.length !== 1) {
734
- // TODO: Report more specific place where the error happened
735
- throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
969
+ bracketSpacing: true,
970
+ });
971
+ }
972
+ catch (error) {
973
+ console.error('There was an error with prettifying the markdown, using the original as the fallback', {
974
+ error: error,
975
+ html: html,
976
+ });
977
+ return html;
736
978
  }
737
- return codeBlocks[0];
738
- }
739
- /***
740
- * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
741
- */
742
-
743
- /**
744
- * Removes HTML or Markdown comments from a string.
745
- *
746
- * @param {string} content - The string to remove comments from.
747
- * @returns {string} The input string with all comments removed.
748
- */
749
- function removeContentComments(content) {
750
- return spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
751
979
  }
752
980
 
753
981
  /**
@@ -831,11 +1059,11 @@ function normalizeTo_SCREAMING_CASE(sentence) {
831
1059
  */
832
1060
 
833
1061
  /* tslint:disable */
834
- function normalizeTo_camelCase(sentence, __firstLetterCapital) {
1062
+ function normalizeToKebabCase(sentence) {
835
1063
  var e_1, _a;
836
- if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1064
+ sentence = removeDiacritics(sentence);
837
1065
  var charType;
838
- var lastCharType = null;
1066
+ var lastCharType = 'OTHER';
839
1067
  var normalizedName = '';
840
1068
  try {
841
1069
  for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
@@ -853,20 +1081,19 @@ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
853
1081
  charType = 'NUMBER';
854
1082
  normalizedChar = char;
855
1083
  }
1084
+ else if (/^\/$/.test(char)) {
1085
+ charType = 'SLASH';
1086
+ normalizedChar = char;
1087
+ }
856
1088
  else {
857
1089
  charType = 'OTHER';
858
- normalizedChar = '';
1090
+ normalizedChar = '-';
859
1091
  }
860
- if (!lastCharType) {
861
- if (__firstLetterCapital) {
862
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
863
- }
864
- }
865
- else if (charType !== lastCharType &&
866
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1092
+ if (charType !== lastCharType &&
1093
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
867
1094
  !(lastCharType === 'NUMBER') &&
868
1095
  !(charType === 'NUMBER')) {
869
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1096
+ normalizedName += '-';
870
1097
  }
871
1098
  normalizedName += normalizedChar;
872
1099
  lastCharType = charType;
@@ -879,207 +1106,67 @@ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
879
1106
  }
880
1107
  finally { if (e_1) throw e_1.error; }
881
1108
  }
1109
+ normalizedName = normalizedName.split(/-+/g).join('-');
1110
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
1111
+ normalizedName = normalizedName.replace(/^-/, '');
1112
+ normalizedName = normalizedName.replace(/-$/, '');
882
1113
  return normalizedName;
883
1114
  }
884
- /**
885
- * TODO: [🌺] Use some intermediate util splitWords
886
- */
887
-
888
- function normalizeTo_PascalCase(sentence) {
889
- return normalizeTo_camelCase(sentence, true);
890
- }
891
-
892
- /**
893
- * Supported script languages
894
- */
895
- var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
896
1115
 
897
- /**
898
- * Parses the template and returns the list of all parameter names
899
- *
900
- * @param template the template with parameters in {curly} braces
901
- * @returns the list of parameter names
902
- *
903
- * @private within the library
904
- */
905
- function extractParameters(template) {
1116
+ /* tslint:disable */
1117
+ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
906
1118
  var e_1, _a;
907
- var matches = template.matchAll(/{\w+}/g);
908
- var parameterNames = [];
1119
+ if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1120
+ var charType;
1121
+ var lastCharType = null;
1122
+ var normalizedName = '';
909
1123
  try {
910
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
911
- var match = matches_1_1.value;
912
- var parameterName = match[0].slice(1, -1);
913
- if (!parameterNames.includes(parameterName)) {
914
- parameterNames.push(parameterName);
1124
+ for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
1125
+ var char = sentence_1_1.value;
1126
+ var normalizedChar = void 0;
1127
+ if (/^[a-z]$/.test(char)) {
1128
+ charType = 'LOWERCASE';
1129
+ normalizedChar = char;
915
1130
  }
916
- }
917
- }
918
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
919
- finally {
920
- try {
921
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
922
- }
923
- finally { if (e_1) throw e_1.error; }
924
- }
925
- return parameterNames;
926
- }
927
-
928
- /**
929
- * Computes the deepness of the markdown structure.
930
- *
931
- * @private within the library
932
- */
933
- function countMarkdownStructureDeepness(markdownStructure) {
934
- var e_1, _a;
935
- var maxDeepness = 0;
936
- try {
937
- for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
938
- var section = _c.value;
939
- maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
940
- }
941
- }
942
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
943
- finally {
944
- try {
945
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
946
- }
947
- finally { if (e_1) throw e_1.error; }
948
- }
949
- return maxDeepness + 1;
950
- }
951
-
952
- /**
953
- * Parse a markdown string into a MarkdownStructure object.
954
- *
955
- * Note: This function does work with code blocks
956
- * Note: This function does not work with markdown comments
957
- *
958
- * @param markdown The markdown string to parse.
959
- * @returns The MarkdownStructure object.
960
- *
961
- * @private within the library
962
- */
963
- function markdownToMarkdownStructure(markdown) {
964
- var e_1, _a;
965
- var lines = markdown.split('\n');
966
- var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
967
- var current = root;
968
- var isInsideCodeBlock = false;
969
- try {
970
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
971
- var line = lines_1_1.value;
972
- var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
973
- if (isInsideCodeBlock || !headingMatch) {
974
- if (line.startsWith('```')) {
975
- isInsideCodeBlock = !isInsideCodeBlock;
976
- }
977
- current.contentLines.push(line);
1131
+ else if (/^[A-Z]$/.test(char)) {
1132
+ charType = 'UPPERCASE';
1133
+ normalizedChar = char.toLowerCase();
1134
+ }
1135
+ else if (/^[0-9]$/.test(char)) {
1136
+ charType = 'NUMBER';
1137
+ normalizedChar = char;
978
1138
  }
979
1139
  else {
980
- var level = headingMatch.groups.mark.length;
981
- var title = headingMatch.groups.title.trim();
982
- var parent_1 = void 0;
983
- if (level > current.level) {
984
- // Note: Going deeper (next section is child of current)
985
- parent_1 = current;
986
- }
987
- else {
988
- // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
989
- parent_1 = current;
990
- var loopLimit = LOOP_LIMIT;
991
- while (parent_1.level !== level - 1) {
992
- if (loopLimit-- < 0) {
993
- throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
994
- }
995
- if (parent_1.parent === null /* <- Note: We are in root */) {
996
- // [🌻]
997
- throw new Error(spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
998
- }
999
- parent_1 = parent_1.parent;
1000
- }
1140
+ charType = 'OTHER';
1141
+ normalizedChar = '';
1142
+ }
1143
+ if (!lastCharType) {
1144
+ if (__firstLetterCapital) {
1145
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
1001
1146
  }
1002
- var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
1003
- parent_1.sections.push(section);
1004
- current = section;
1005
1147
  }
1148
+ else if (charType !== lastCharType &&
1149
+ !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1150
+ !(lastCharType === 'NUMBER') &&
1151
+ !(charType === 'NUMBER')) {
1152
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1153
+ }
1154
+ normalizedName += normalizedChar;
1155
+ lastCharType = charType;
1006
1156
  }
1007
1157
  }
1008
1158
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
1009
1159
  finally {
1010
1160
  try {
1011
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
1161
+ if (sentence_1_1 && !sentence_1_1.done && (_a = sentence_1.return)) _a.call(sentence_1);
1012
1162
  }
1013
1163
  finally { if (e_1) throw e_1.error; }
1014
1164
  }
1015
- if (root.sections.length === 1) {
1016
- var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
1017
- return markdownStructure;
1018
- }
1019
- // [🌻]
1020
- throw new Error('The markdown file must have exactly one top-level section.');
1021
- // return root;
1022
- }
1023
- /**
1024
- * @private
1025
- */
1026
- function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
1027
- var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
1028
- return {
1029
- level: level,
1030
- title: title,
1031
- content: spaceTrim(contentLines.join('\n')),
1032
- sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
1033
- };
1165
+ return normalizedName;
1034
1166
  }
1035
-
1036
1167
  /**
1037
- * Parses the given script and returns the list of all used variables that are not defined in the script
1038
- *
1039
- * @param script from which to extract the variables
1040
- * @returns the list of variable names
1041
- * @throws {PromptbookSyntaxError} if the script is invalid
1042
- *
1043
- * @private within the promptbookStringToJson
1168
+ * TODO: [🌺] Use some intermediate util splitWords
1044
1169
  */
1045
- function extractVariables(script) {
1046
- var variables = [];
1047
- script = "(()=>{".concat(script, "})()");
1048
- try {
1049
- for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
1050
- try {
1051
- eval(script);
1052
- }
1053
- catch (error) {
1054
- if (!(error instanceof ReferenceError)) {
1055
- throw error;
1056
- }
1057
- var undefinedName = error.message.split(' ')[0];
1058
- /*
1059
- Note: Remapping error
1060
- From: [ReferenceError: thing is not defined],
1061
- To: [Error: Parameter {thing} is not defined],
1062
- */
1063
- if (!undefinedName) {
1064
- throw error;
1065
- }
1066
- if (script.includes(undefinedName + '(')) {
1067
- script = "const ".concat(undefinedName, " = ()=>'';") + script;
1068
- }
1069
- else {
1070
- variables.push(undefinedName);
1071
- script = "const ".concat(undefinedName, " = '';") + script;
1072
- }
1073
- }
1074
- }
1075
- catch (error) {
1076
- if (!(error instanceof Error)) {
1077
- throw error;
1078
- }
1079
- throw new PromptbookSyntaxError(spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
1080
- }
1081
- return variables;
1082
- }
1083
1170
 
1084
1171
  /**
1085
1172
  * Execution type describes the way how the block is executed
@@ -1589,7 +1676,7 @@ function promptbookStringToJson(promptbookString) {
1589
1676
  }
1590
1677
  dependentParameterNames = __spreadArray([], __read(new Set(dependentParameterNames)), false);
1591
1678
  promptbookJson.promptTemplates.push({
1592
- name: normalizeTo_PascalCase(section.title),
1679
+ name: titleToName(section.title),
1593
1680
  title: section.title,
1594
1681
  description: description_1,
1595
1682
  dependentParameterNames: dependentParameterNames,