@promptbook/core 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/umd/index.umd.js CHANGED
@@ -128,15 +128,84 @@
128
128
  }
129
129
 
130
130
  /**
131
- * Removes HTML or Markdown comments from a string.
131
+ * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
132
+ */
133
+ var PromptbookSyntaxError = /** @class */ (function (_super) {
134
+ __extends(PromptbookSyntaxError, _super);
135
+ function PromptbookSyntaxError(message) {
136
+ var _this = _super.call(this, message) || this;
137
+ _this.name = 'PromptbookSyntaxError';
138
+ Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
139
+ return _this;
140
+ }
141
+ return PromptbookSyntaxError;
142
+ }(Error));
143
+
144
+ /**
145
+ * Supported script languages
146
+ */
147
+ var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
148
+
149
+ /**
150
+ * Parses the template and returns the list of all parameter names
132
151
  *
133
- * @param {string} content - The string to remove comments from.
134
- * @returns {string} The input string with all comments removed.
152
+ * @param template the template with parameters in {curly} braces
153
+ * @returns the list of parameter names
154
+ *
155
+ * @private within the library
135
156
  */
136
- function removeContentComments(content) {
137
- return spaceTrim.spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
157
+ function extractParameters(template) {
158
+ var e_1, _a;
159
+ var matches = template.matchAll(/{\w+}/g);
160
+ var parameterNames = [];
161
+ try {
162
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
163
+ var match = matches_1_1.value;
164
+ var parameterName = match[0].slice(1, -1);
165
+ if (!parameterNames.includes(parameterName)) {
166
+ parameterNames.push(parameterName);
167
+ }
168
+ }
169
+ }
170
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
171
+ finally {
172
+ try {
173
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
174
+ }
175
+ finally { if (e_1) throw e_1.error; }
176
+ }
177
+ return parameterNames;
178
+ }
179
+
180
+ /**
181
+ * Computes the deepness of the markdown structure.
182
+ *
183
+ * @private within the library
184
+ */
185
+ function countMarkdownStructureDeepness(markdownStructure) {
186
+ var e_1, _a;
187
+ var maxDeepness = 0;
188
+ try {
189
+ for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
190
+ var section = _c.value;
191
+ maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
192
+ }
193
+ }
194
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
195
+ finally {
196
+ try {
197
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
198
+ }
199
+ finally { if (e_1) throw e_1.error; }
200
+ }
201
+ return maxDeepness + 1;
138
202
  }
139
203
 
204
+ /**
205
+ * The maximum number of iterations for a loops
206
+ */
207
+ var LOOP_LIMIT = 1000;
208
+
140
209
  /**
141
210
  * This error type indicates that the error should not happen and its last check before crashing with some other error
142
211
  */
@@ -152,18 +221,304 @@
152
221
  }(Error));
153
222
 
154
223
  /**
155
- * This error indicates that the promptbook in a markdown format cannot be parsed into a valid promptbook object
224
+ * Parse a markdown string into a MarkdownStructure object.
225
+ *
226
+ * Note: This function does work with code blocks
227
+ * Note: This function does not work with markdown comments
228
+ *
229
+ * @param markdown The markdown string to parse.
230
+ * @returns The MarkdownStructure object.
231
+ *
232
+ * @private within the library
156
233
  */
157
- var PromptbookSyntaxError = /** @class */ (function (_super) {
158
- __extends(PromptbookSyntaxError, _super);
159
- function PromptbookSyntaxError(message) {
160
- var _this = _super.call(this, message) || this;
161
- _this.name = 'PromptbookSyntaxError';
162
- Object.setPrototypeOf(_this, PromptbookSyntaxError.prototype);
163
- return _this;
234
+ function markdownToMarkdownStructure(markdown) {
235
+ var e_1, _a;
236
+ var lines = markdown.split('\n');
237
+ var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
238
+ var current = root;
239
+ var isInsideCodeBlock = false;
240
+ try {
241
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
242
+ var line = lines_1_1.value;
243
+ var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
244
+ if (isInsideCodeBlock || !headingMatch) {
245
+ if (line.startsWith('```')) {
246
+ isInsideCodeBlock = !isInsideCodeBlock;
247
+ }
248
+ current.contentLines.push(line);
249
+ }
250
+ else {
251
+ var level = headingMatch.groups.mark.length;
252
+ var title = headingMatch.groups.title.trim();
253
+ var parent_1 = void 0;
254
+ if (level > current.level) {
255
+ // Note: Going deeper (next section is child of current)
256
+ parent_1 = current;
257
+ }
258
+ else {
259
+ // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
260
+ parent_1 = current;
261
+ var loopLimit = LOOP_LIMIT;
262
+ while (parent_1.level !== level - 1) {
263
+ if (loopLimit-- < 0) {
264
+ throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
265
+ }
266
+ if (parent_1.parent === null /* <- Note: We are in root */) {
267
+ // [🌻]
268
+ throw new Error(spaceTrim.spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
269
+ }
270
+ parent_1 = parent_1.parent;
271
+ }
272
+ }
273
+ var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
274
+ parent_1.sections.push(section);
275
+ current = section;
276
+ }
277
+ }
164
278
  }
165
- return PromptbookSyntaxError;
166
- }(Error));
279
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
280
+ finally {
281
+ try {
282
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
283
+ }
284
+ finally { if (e_1) throw e_1.error; }
285
+ }
286
+ if (root.sections.length === 1) {
287
+ var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
288
+ return markdownStructure;
289
+ }
290
+ // [🌻]
291
+ throw new Error('The markdown file must have exactly one top-level section.');
292
+ // return root;
293
+ }
294
+ /**
295
+ * @private
296
+ */
297
+ function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
298
+ var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
299
+ return {
300
+ level: level,
301
+ title: title,
302
+ content: spaceTrim.spaceTrim(contentLines.join('\n')),
303
+ sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
304
+ };
305
+ }
306
+
307
+ /**
308
+ * Utility function to extract all list items from markdown
309
+ *
310
+ * Note: It works with both ul and ol
311
+ * Note: It omits list items in code blocks
312
+ * Note: It flattens nested lists
313
+ * Note: It can not work with html syntax and comments
314
+ *
315
+ * @param markdown any valid markdown
316
+ * @returns
317
+ */
318
+ function extractAllListItemsFromMarkdown(markdown) {
319
+ var e_1, _a;
320
+ var lines = markdown.split('\n');
321
+ var listItems = [];
322
+ var isInCodeBlock = false;
323
+ try {
324
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
325
+ var line = lines_1_1.value;
326
+ var trimmedLine = line.trim();
327
+ if (trimmedLine.startsWith('```')) {
328
+ isInCodeBlock = !isInCodeBlock;
329
+ }
330
+ if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
331
+ var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
332
+ listItems.push(listItem);
333
+ }
334
+ }
335
+ }
336
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
337
+ finally {
338
+ try {
339
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
340
+ }
341
+ finally { if (e_1) throw e_1.error; }
342
+ }
343
+ return listItems;
344
+ }
345
+
346
+ /**
347
+ * Makes first letter of a string uppercase
348
+ *
349
+ */
350
+ function capitalize(word) {
351
+ return word.substring(0, 1).toUpperCase() + word.substring(1);
352
+ }
353
+
354
+ /**
355
+ * Extracts all code blocks from markdown.
356
+ *
357
+ * Note: There are 3 simmilar function:
358
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
359
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
360
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
361
+ *
362
+ * @param markdown any valid markdown
363
+ * @returns code blocks with language and content
364
+ *
365
+ */
366
+ function extractAllBlocksFromMarkdown(markdown) {
367
+ var e_1, _a;
368
+ var codeBlocks = [];
369
+ var lines = markdown.split('\n');
370
+ var currentCodeBlock = null;
371
+ try {
372
+ for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
373
+ var line = lines_1_1.value;
374
+ if (line.startsWith('```')) {
375
+ var language = line.slice(3).trim() || null;
376
+ if (currentCodeBlock === null) {
377
+ currentCodeBlock = { language: language, content: '' };
378
+ }
379
+ else {
380
+ if (language !== null) {
381
+ // [🌻]
382
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
383
+ }
384
+ codeBlocks.push(currentCodeBlock);
385
+ currentCodeBlock = null;
386
+ }
387
+ }
388
+ else if (currentCodeBlock !== null) {
389
+ if (currentCodeBlock.content !== '') {
390
+ currentCodeBlock.content += '\n';
391
+ }
392
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
393
+ }
394
+ }
395
+ }
396
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
397
+ finally {
398
+ try {
399
+ if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
400
+ }
401
+ finally { if (e_1) throw e_1.error; }
402
+ }
403
+ if (currentCodeBlock !== null) {
404
+ // [🌻]
405
+ throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
406
+ }
407
+ return codeBlocks;
408
+ }
409
+
410
+ /**
411
+ * Extracts exactly ONE code block from markdown.
412
+ *
413
+ * Note: If there are multiple or no code blocks the function throws an error
414
+ *
415
+ * Note: There are 3 simmilar function:
416
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
417
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
418
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
419
+ *
420
+ * @param markdown any valid markdown
421
+ * @returns code block with language and content
422
+ */
423
+ function extractOneBlockFromMarkdown(markdown) {
424
+ var codeBlocks = extractAllBlocksFromMarkdown(markdown);
425
+ if (codeBlocks.length !== 1) {
426
+ // TODO: Report more specific place where the error happened
427
+ throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
428
+ }
429
+ return codeBlocks[0];
430
+ }
431
+ /***
432
+ * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
433
+ */
434
+
435
+ /**
436
+ * Removes HTML or Markdown comments from a string.
437
+ *
438
+ * @param {string} content - The string to remove comments from.
439
+ * @returns {string} The input string with all comments removed.
440
+ */
441
+ function removeContentComments(content) {
442
+ return spaceTrim.spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
443
+ }
444
+
445
+ /**
446
+ * The version of the Promptbook library
447
+ */
448
+ var PROMPTBOOK_VERSION = '0.48.0-1';
449
+
450
+ /**
451
+ * Parses the given script and returns the list of all used variables that are not defined in the script
452
+ *
453
+ * @param script from which to extract the variables
454
+ * @returns the list of variable names
455
+ * @throws {PromptbookSyntaxError} if the script is invalid
456
+ *
457
+ * @private within the promptbookStringToJson
458
+ */
459
+ function extractVariables(script) {
460
+ var variables = [];
461
+ script = "(()=>{".concat(script, "})()");
462
+ try {
463
+ for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
464
+ try {
465
+ eval(script);
466
+ }
467
+ catch (error) {
468
+ if (!(error instanceof ReferenceError)) {
469
+ throw error;
470
+ }
471
+ var undefinedName = error.message.split(' ')[0];
472
+ /*
473
+ Note: Remapping error
474
+ From: [ReferenceError: thing is not defined],
475
+ To: [Error: Parameter {thing} is not defined],
476
+ */
477
+ if (!undefinedName) {
478
+ throw error;
479
+ }
480
+ if (script.includes(undefinedName + '(')) {
481
+ script = "const ".concat(undefinedName, " = ()=>'';") + script;
482
+ }
483
+ else {
484
+ variables.push(undefinedName);
485
+ script = "const ".concat(undefinedName, " = '';") + script;
486
+ }
487
+ }
488
+ }
489
+ catch (error) {
490
+ if (!(error instanceof Error)) {
491
+ throw error;
492
+ }
493
+ throw new PromptbookSyntaxError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
494
+ }
495
+ return variables;
496
+ }
497
+
498
+ /**
499
+ * Removes emojis from a string and fix whitespaces
500
+ *
501
+ * @param text with emojis
502
+ * @returns text without emojis
503
+ */
504
+ function removeEmojis(text) {
505
+ // Replace emojis (and also ZWJ sequence) with hyphens
506
+ text = text.replace(/(\p{Extended_Pictographic})\p{Modifier_Symbol}/gu, '$1');
507
+ text = text.replace(/(\p{Extended_Pictographic})[\u{FE00}-\u{FE0F}]/gu, '$1');
508
+ text = text.replace(/(\p{Extended_Pictographic})(\u{200D}\p{Extended_Pictographic})*/gu, '$1');
509
+ text = text.replace(/\p{Extended_Pictographic}/gu, '');
510
+ return text;
511
+ }
512
+
513
+ /**
514
+ * Function normalizes title to name which can be used as identifier
515
+ */
516
+ function titleToName(value) {
517
+ value = removeEmojis(value);
518
+ value = normalizeToKebabCase(value);
519
+ // TODO: [🧠] Maybe warn or add some padding to short name which are not good identifiers
520
+ return value;
521
+ }
167
522
 
168
523
  /**
169
524
  * Function parseNumber will parse number from string
@@ -625,11 +980,6 @@
625
980
  * TODO: [💝] Unite object for expecting amount and format
626
981
  */
627
982
 
628
- /**
629
- * The maximum number of iterations for a loops
630
- */
631
- var LOOP_LIMIT = 1000;
632
-
633
983
  /**
634
984
  * This error occurs during the parameter replacement in the template
635
985
  *
@@ -697,161 +1047,33 @@
697
1047
  }
698
1048
  // [💫] Check if there are parameters that are not closed properly
699
1049
  if (/{\w+$/.test(replacedTemplate)) {
700
- throw new TemplateError('Parameter is not closed');
701
- }
702
- // [💫] Check if there are parameters that are not opened properly
703
- if (/^\w+}/.test(replacedTemplate)) {
704
- throw new TemplateError('Parameter is not opened');
705
- }
706
- return replacedTemplate;
707
- }
708
-
709
- /**
710
- * Function isValidJsonString will tell you if the string is valid JSON or not
711
- */
712
- function isValidJsonString(value) {
713
- try {
714
- JSON.parse(value);
715
- return true;
716
- }
717
- catch (error) {
718
- if (!(error instanceof Error)) {
719
- throw error;
720
- }
721
- if (error.message.includes('Unexpected token')) {
722
- return false;
723
- }
724
- return false;
725
- }
726
- }
727
-
728
- /**
729
- * Makes first letter of a string uppercase
730
- *
731
- */
732
- function capitalize(word) {
733
- return word.substring(0, 1).toUpperCase() + word.substring(1);
734
- }
735
-
736
- /**
737
- * Extracts all code blocks from markdown.
738
- *
739
- * Note: There are 3 simmilar function:
740
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
741
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
742
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
743
- *
744
- * @param markdown any valid markdown
745
- * @returns code blocks with language and content
746
- *
747
- */
748
- function extractAllBlocksFromMarkdown(markdown) {
749
- var e_1, _a;
750
- var codeBlocks = [];
751
- var lines = markdown.split('\n');
752
- var currentCodeBlock = null;
753
- try {
754
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
755
- var line = lines_1_1.value;
756
- if (line.startsWith('```')) {
757
- var language = line.slice(3).trim() || null;
758
- if (currentCodeBlock === null) {
759
- currentCodeBlock = { language: language, content: '' };
760
- }
761
- else {
762
- if (language !== null) {
763
- // [🌻]
764
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
765
- }
766
- codeBlocks.push(currentCodeBlock);
767
- currentCodeBlock = null;
768
- }
769
- }
770
- else if (currentCodeBlock !== null) {
771
- if (currentCodeBlock.content !== '') {
772
- currentCodeBlock.content += '\n';
773
- }
774
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
775
- }
776
- }
777
- }
778
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
779
- finally {
780
- try {
781
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
782
- }
783
- finally { if (e_1) throw e_1.error; }
784
- }
785
- if (currentCodeBlock !== null) {
786
- // [🌻]
787
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
788
- }
789
- return codeBlocks;
790
- }
791
-
792
- /**
793
- * Utility function to extract all list items from markdown
794
- *
795
- * Note: It works with both ul and ol
796
- * Note: It omits list items in code blocks
797
- * Note: It flattens nested lists
798
- * Note: It can not work with html syntax and comments
799
- *
800
- * @param markdown any valid markdown
801
- * @returns
802
- */
803
- function extractAllListItemsFromMarkdown(markdown) {
804
- var e_1, _a;
805
- var lines = markdown.split('\n');
806
- var listItems = [];
807
- var isInCodeBlock = false;
808
- try {
809
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
810
- var line = lines_1_1.value;
811
- var trimmedLine = line.trim();
812
- if (trimmedLine.startsWith('```')) {
813
- isInCodeBlock = !isInCodeBlock;
814
- }
815
- if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
816
- var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
817
- listItems.push(listItem);
818
- }
819
- }
1050
+ throw new TemplateError('Parameter is not closed');
820
1051
  }
821
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
822
- finally {
823
- try {
824
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
825
- }
826
- finally { if (e_1) throw e_1.error; }
1052
+ // [💫] Check if there are parameters that are not opened properly
1053
+ if (/^\w+}/.test(replacedTemplate)) {
1054
+ throw new TemplateError('Parameter is not opened');
827
1055
  }
828
- return listItems;
1056
+ return replacedTemplate;
829
1057
  }
830
1058
 
831
1059
  /**
832
- * Extracts exactly ONE code block from markdown.
833
- *
834
- * Note: If there are multiple or no code blocks the function throws an error
835
- *
836
- * Note: There are 3 simmilar function:
837
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
838
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
839
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
840
- *
841
- * @param markdown any valid markdown
842
- * @returns code block with language and content
1060
+ * Function isValidJsonString will tell you if the string is valid JSON or not
843
1061
  */
844
- function extractOneBlockFromMarkdown(markdown) {
845
- var codeBlocks = extractAllBlocksFromMarkdown(markdown);
846
- if (codeBlocks.length !== 1) {
847
- // TODO: Report more specific place where the error happened
848
- throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
1062
+ function isValidJsonString(value) {
1063
+ try {
1064
+ JSON.parse(value);
1065
+ return true;
1066
+ }
1067
+ catch (error) {
1068
+ if (!(error instanceof Error)) {
1069
+ throw error;
1070
+ }
1071
+ if (error.message.includes('Unexpected token')) {
1072
+ return false;
1073
+ }
1074
+ return false;
849
1075
  }
850
- return codeBlocks[0];
851
1076
  }
852
- /***
853
- * TODO: [🍓][🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
854
- */
855
1077
 
856
1078
  /**
857
1079
  * Removes Markdown formatting tags from a string.
@@ -934,11 +1156,11 @@
934
1156
  */
935
1157
 
936
1158
  /* tslint:disable */
937
- function normalizeTo_camelCase(sentence, __firstLetterCapital) {
1159
+ function normalizeToKebabCase(sentence) {
938
1160
  var e_1, _a;
939
- if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1161
+ sentence = removeDiacritics(sentence);
940
1162
  var charType;
941
- var lastCharType = null;
1163
+ var lastCharType = 'OTHER';
942
1164
  var normalizedName = '';
943
1165
  try {
944
1166
  for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
@@ -956,20 +1178,19 @@
956
1178
  charType = 'NUMBER';
957
1179
  normalizedChar = char;
958
1180
  }
1181
+ else if (/^\/$/.test(char)) {
1182
+ charType = 'SLASH';
1183
+ normalizedChar = char;
1184
+ }
959
1185
  else {
960
1186
  charType = 'OTHER';
961
- normalizedChar = '';
962
- }
963
- if (!lastCharType) {
964
- if (__firstLetterCapital) {
965
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
966
- }
1187
+ normalizedChar = '-';
967
1188
  }
968
- else if (charType !== lastCharType &&
969
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1189
+ if (charType !== lastCharType &&
1190
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
970
1191
  !(lastCharType === 'NUMBER') &&
971
1192
  !(charType === 'NUMBER')) {
972
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1193
+ normalizedName += '-';
973
1194
  }
974
1195
  normalizedName += normalizedChar;
975
1196
  lastCharType = charType;
@@ -982,212 +1203,12 @@
982
1203
  }
983
1204
  finally { if (e_1) throw e_1.error; }
984
1205
  }
1206
+ normalizedName = normalizedName.split(/-+/g).join('-');
1207
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
1208
+ normalizedName = normalizedName.replace(/^-/, '');
1209
+ normalizedName = normalizedName.replace(/-$/, '');
985
1210
  return normalizedName;
986
1211
  }
987
- /**
988
- * TODO: [🌺] Use some intermediate util splitWords
989
- */
990
-
991
- function normalizeTo_PascalCase(sentence) {
992
- return normalizeTo_camelCase(sentence, true);
993
- }
994
-
995
- /**
996
- * Supported script languages
997
- */
998
- var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
999
-
1000
- /**
1001
- * Parses the template and returns the list of all parameter names
1002
- *
1003
- * @param template the template with parameters in {curly} braces
1004
- * @returns the list of parameter names
1005
- *
1006
- * @private within the library
1007
- */
1008
- function extractParameters(template) {
1009
- var e_1, _a;
1010
- var matches = template.matchAll(/{\w+}/g);
1011
- var parameterNames = [];
1012
- try {
1013
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
1014
- var match = matches_1_1.value;
1015
- var parameterName = match[0].slice(1, -1);
1016
- if (!parameterNames.includes(parameterName)) {
1017
- parameterNames.push(parameterName);
1018
- }
1019
- }
1020
- }
1021
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1022
- finally {
1023
- try {
1024
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
1025
- }
1026
- finally { if (e_1) throw e_1.error; }
1027
- }
1028
- return parameterNames;
1029
- }
1030
-
1031
- /**
1032
- * Computes the deepness of the markdown structure.
1033
- *
1034
- * @private within the library
1035
- */
1036
- function countMarkdownStructureDeepness(markdownStructure) {
1037
- var e_1, _a;
1038
- var maxDeepness = 0;
1039
- try {
1040
- for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
1041
- var section = _c.value;
1042
- maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
1043
- }
1044
- }
1045
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1046
- finally {
1047
- try {
1048
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1049
- }
1050
- finally { if (e_1) throw e_1.error; }
1051
- }
1052
- return maxDeepness + 1;
1053
- }
1054
-
1055
- /**
1056
- * Parse a markdown string into a MarkdownStructure object.
1057
- *
1058
- * Note: This function does work with code blocks
1059
- * Note: This function does not work with markdown comments
1060
- *
1061
- * @param markdown The markdown string to parse.
1062
- * @returns The MarkdownStructure object.
1063
- *
1064
- * @private within the library
1065
- */
1066
- function markdownToMarkdownStructure(markdown) {
1067
- var e_1, _a;
1068
- var lines = markdown.split('\n');
1069
- var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
1070
- var current = root;
1071
- var isInsideCodeBlock = false;
1072
- try {
1073
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
1074
- var line = lines_1_1.value;
1075
- var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
1076
- if (isInsideCodeBlock || !headingMatch) {
1077
- if (line.startsWith('```')) {
1078
- isInsideCodeBlock = !isInsideCodeBlock;
1079
- }
1080
- current.contentLines.push(line);
1081
- }
1082
- else {
1083
- var level = headingMatch.groups.mark.length;
1084
- var title = headingMatch.groups.title.trim();
1085
- var parent_1 = void 0;
1086
- if (level > current.level) {
1087
- // Note: Going deeper (next section is child of current)
1088
- parent_1 = current;
1089
- }
1090
- else {
1091
- // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
1092
- parent_1 = current;
1093
- var loopLimit = LOOP_LIMIT;
1094
- while (parent_1.level !== level - 1) {
1095
- if (loopLimit-- < 0) {
1096
- throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
1097
- }
1098
- if (parent_1.parent === null /* <- Note: We are in root */) {
1099
- // [🌻]
1100
- throw new Error(spaceTrim.spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
1101
- }
1102
- parent_1 = parent_1.parent;
1103
- }
1104
- }
1105
- var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
1106
- parent_1.sections.push(section);
1107
- current = section;
1108
- }
1109
- }
1110
- }
1111
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1112
- finally {
1113
- try {
1114
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
1115
- }
1116
- finally { if (e_1) throw e_1.error; }
1117
- }
1118
- if (root.sections.length === 1) {
1119
- var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
1120
- return markdownStructure;
1121
- }
1122
- // [🌻]
1123
- throw new Error('The markdown file must have exactly one top-level section.');
1124
- // return root;
1125
- }
1126
- /**
1127
- * @private
1128
- */
1129
- function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
1130
- var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
1131
- return {
1132
- level: level,
1133
- title: title,
1134
- content: spaceTrim.spaceTrim(contentLines.join('\n')),
1135
- sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
1136
- };
1137
- }
1138
-
1139
- /**
1140
- * The version of the Promptbook library
1141
- */
1142
- var PROMPTBOOK_VERSION = '0.47.0';
1143
-
1144
- /**
1145
- * Parses the given script and returns the list of all used variables that are not defined in the script
1146
- *
1147
- * @param script from which to extract the variables
1148
- * @returns the list of variable names
1149
- * @throws {PromptbookSyntaxError} if the script is invalid
1150
- *
1151
- * @private within the promptbookStringToJson
1152
- */
1153
- function extractVariables(script) {
1154
- var variables = [];
1155
- script = "(()=>{".concat(script, "})()");
1156
- try {
1157
- for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
1158
- try {
1159
- eval(script);
1160
- }
1161
- catch (error) {
1162
- if (!(error instanceof ReferenceError)) {
1163
- throw error;
1164
- }
1165
- var undefinedName = error.message.split(' ')[0];
1166
- /*
1167
- Note: Remapping error
1168
- From: [ReferenceError: thing is not defined],
1169
- To: [Error: Parameter {thing} is not defined],
1170
- */
1171
- if (!undefinedName) {
1172
- throw error;
1173
- }
1174
- if (script.includes(undefinedName + '(')) {
1175
- script = "const ".concat(undefinedName, " = ()=>'';") + script;
1176
- }
1177
- else {
1178
- variables.push(undefinedName);
1179
- script = "const ".concat(undefinedName, " = '';") + script;
1180
- }
1181
- }
1182
- }
1183
- catch (error) {
1184
- if (!(error instanceof Error)) {
1185
- throw error;
1186
- }
1187
- throw new PromptbookSyntaxError(spaceTrim.spaceTrim(function (block) { return "\n Can not extract variables from the script\n\n ".concat(block(error.name), ": ").concat(block(error.message), "\n "); }));
1188
- }
1189
- return variables;
1190
- }
1191
1212
 
1192
1213
  /**
1193
1214
  * Execution type describes the way how the block is executed
@@ -1697,7 +1718,7 @@
1697
1718
  }
1698
1719
  dependentParameterNames = __spreadArray([], __read(new Set(dependentParameterNames)), false);
1699
1720
  promptbookJson.promptTemplates.push({
1700
- name: normalizeTo_PascalCase(section.title),
1721
+ name: titleToName(section.title),
1701
1722
  title: section.title,
1702
1723
  description: description_1,
1703
1724
  dependentParameterNames: dependentParameterNames,
@@ -1738,9 +1759,9 @@
1738
1759
  return spaceTrim__default["default"](function (block) { return "\n\n # ".concat(block(promptbookJson.title), "\n\n "); });
1739
1760
  }
1740
1761
  /**
1741
- * TODO: !!! Implement
1742
- * TODO: !!! Annotate and warn
1743
- * TODO: !!! Test + test together with promptbookStringToJson
1762
+ * TODO: !!!!! Implement
1763
+ * TODO: !!!!! Annotate and warn
1764
+ * TODO: !!!!! Test + test together with promptbookStringToJson
1744
1765
  */
1745
1766
 
1746
1767
  /**