@promptbook/cli 0.47.0 → 0.48.0-1

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.
Files changed (46) hide show
  1. package/README.md +12 -1
  2. package/esm/index.es.js +449 -363
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/_packages/core.index.d.ts +2 -1
  5. package/esm/typings/_packages/utils.index.d.ts +2 -1
  6. package/esm/typings/conversion/prettify/prettifyPromptbookStringCli.d.ts +1 -1
  7. package/esm/typings/conversion/promptbookJsonToString.d.ts +8 -0
  8. package/esm/typings/conversion/utils/titleToName.d.ts +4 -0
  9. package/esm/typings/conversion/utils/titleToName.test.d.ts +1 -0
  10. package/esm/typings/execution/ExecutionTools.d.ts +1 -1
  11. package/esm/typings/execution/LlmExecutionTools.d.ts +1 -0
  12. package/esm/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +1 -1
  13. package/esm/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  14. package/esm/typings/execution/plugins/llm-execution-tools/openai/computeOpenaiUsage.d.ts +4 -1
  15. package/esm/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -0
  16. package/esm/typings/library/SimplePromptbookLibrary.d.ts +2 -1
  17. package/esm/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +10 -1
  18. package/esm/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +20 -1
  19. package/esm/typings/library/constructors/createPromptbookLibraryFromSources.d.ts +5 -6
  20. package/esm/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +13 -0
  21. package/esm/typings/library/constructors/createPromptbookSublibrary.d.ts +10 -1
  22. package/esm/typings/utils/markdown/extractOneBlockFromMarkdown.d.ts +1 -1
  23. package/package.json +2 -2
  24. package/umd/index.umd.js +449 -363
  25. package/umd/index.umd.js.map +1 -1
  26. package/umd/typings/_packages/core.index.d.ts +2 -1
  27. package/umd/typings/_packages/utils.index.d.ts +2 -1
  28. package/umd/typings/conversion/prettify/prettifyPromptbookStringCli.d.ts +1 -1
  29. package/umd/typings/conversion/promptbookJsonToString.d.ts +8 -0
  30. package/umd/typings/conversion/utils/titleToName.d.ts +4 -0
  31. package/umd/typings/conversion/utils/titleToName.test.d.ts +1 -0
  32. package/umd/typings/execution/ExecutionTools.d.ts +1 -1
  33. package/umd/typings/execution/LlmExecutionTools.d.ts +1 -0
  34. package/umd/typings/execution/plugins/llm-execution-tools/langtail/LangtailExecutionTools.d.ts +1 -1
  35. package/umd/typings/execution/plugins/llm-execution-tools/openai/OpenAiExecutionTools.d.ts +1 -1
  36. package/umd/typings/execution/plugins/llm-execution-tools/openai/computeOpenaiUsage.d.ts +4 -1
  37. package/umd/typings/execution/plugins/llm-execution-tools/remote/RemoteLlmExecutionTools.d.ts +1 -0
  38. package/umd/typings/library/SimplePromptbookLibrary.d.ts +2 -1
  39. package/umd/typings/library/constructors/createPromptbookLibraryFromDirectory.d.ts +10 -1
  40. package/umd/typings/library/constructors/createPromptbookLibraryFromPromise.d.ts +20 -1
  41. package/umd/typings/library/constructors/createPromptbookLibraryFromSources.d.ts +5 -6
  42. package/umd/typings/library/constructors/createPromptbookLibraryFromUrl.d.ts +13 -0
  43. package/umd/typings/library/constructors/createPromptbookSublibrary.d.ts +10 -1
  44. package/umd/typings/utils/markdown/extractOneBlockFromMarkdown.d.ts +1 -1
  45. package/esm/typings/library/constructors/createPromptbookLibraryFromList.d.ts +0 -5
  46. package/umd/typings/library/constructors/createPromptbookLibraryFromList.d.ts +0 -5
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-0';
146
+ var PROMPTBOOK_VERSION = '0.48.0-0';
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
  *
@@ -540,11 +901,10 @@ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
540
901
  var letters = defaultDiacriticsRemovalMap[i].letters;
541
902
  // tslint:disable-next-line: prefer-for-of
542
903
  for (var j = 0; j < letters.length; j++) {
543
- DIACRITIC_VARIANTS_LETTERS[letters[j]] =
544
- defaultDiacriticsRemovalMap[i].base;
904
+ DIACRITIC_VARIANTS_LETTERS[letters[j]] = defaultDiacriticsRemovalMap[i].base;
545
905
  }
546
906
  }
547
- // <- TODO: !!!! Put to maker function
907
+ // <- TODO: [🍓] Put to maker function to save execution time if not needed
548
908
  /*
549
909
  @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
550
910
  Licensed under the Apache License, Version 2.0 (the "License");
@@ -561,9 +921,14 @@ for (var i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
561
921
  */
562
922
 
563
923
  /**
564
- * The maximum number of iterations for a loops
924
+ *
565
925
  */
566
- 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
+ }
567
932
 
568
933
  /**
569
934
  * This error occurs during the parameter replacement in the template
@@ -600,155 +965,17 @@ function prettifyMarkdown(html) {
600
965
  arrowParens: 'always',
601
966
  printWidth: 120,
602
967
  htmlWhitespaceSensitivity: 'ignore',
603
- jsxBracketSameLine: false,
604
- bracketSpacing: true,
605
- });
606
- }
607
- catch (error) {
608
- console.error('There was an error with prettifying the markdown, using the original as the fallback', {
609
- error: error,
610
- html: html,
611
- });
612
- return html;
613
- }
614
- }
615
-
616
- /**
617
- * Makes first letter of a string uppercase
618
- *
619
- */
620
- function capitalize(word) {
621
- return word.substring(0, 1).toUpperCase() + word.substring(1);
622
- }
623
-
624
- /**
625
- * Extracts all code blocks from markdown.
626
- *
627
- * Note: There are 3 simmilar function:
628
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
629
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
630
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
631
- *
632
- * @param markdown any valid markdown
633
- * @returns code blocks with language and content
634
- *
635
- */
636
- function extractAllBlocksFromMarkdown(markdown) {
637
- var e_1, _a;
638
- var codeBlocks = [];
639
- var lines = markdown.split('\n');
640
- var currentCodeBlock = null;
641
- try {
642
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
643
- var line = lines_1_1.value;
644
- if (line.startsWith('```')) {
645
- var language = line.slice(3).trim() || null;
646
- if (currentCodeBlock === null) {
647
- currentCodeBlock = { language: language, content: '' };
648
- }
649
- else {
650
- if (language !== null) {
651
- // [🌻]
652
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed and already opening new ").concat(language, " code block"));
653
- }
654
- codeBlocks.push(currentCodeBlock);
655
- currentCodeBlock = null;
656
- }
657
- }
658
- else if (currentCodeBlock !== null) {
659
- if (currentCodeBlock.content !== '') {
660
- currentCodeBlock.content += '\n';
661
- }
662
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make propper unescape */;
663
- }
664
- }
665
- }
666
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
667
- finally {
668
- try {
669
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
670
- }
671
- finally { if (e_1) throw e_1.error; }
672
- }
673
- if (currentCodeBlock !== null) {
674
- // [🌻]
675
- throw new Error("".concat(capitalize(currentCodeBlock.language || 'the'), " code block was not closed at the end of the markdown"));
676
- }
677
- return codeBlocks;
678
- }
679
-
680
- /**
681
- * Utility function to extract all list items from markdown
682
- *
683
- * Note: It works with both ul and ol
684
- * Note: It omits list items in code blocks
685
- * Note: It flattens nested lists
686
- * Note: It can not work with html syntax and comments
687
- *
688
- * @param markdown any valid markdown
689
- * @returns
690
- */
691
- function extractAllListItemsFromMarkdown(markdown) {
692
- var e_1, _a;
693
- var lines = markdown.split('\n');
694
- var listItems = [];
695
- var isInCodeBlock = false;
696
- try {
697
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
698
- var line = lines_1_1.value;
699
- var trimmedLine = line.trim();
700
- if (trimmedLine.startsWith('```')) {
701
- isInCodeBlock = !isInCodeBlock;
702
- }
703
- if (!isInCodeBlock && (trimmedLine.startsWith('-') || trimmedLine.match(/^\d+\./))) {
704
- var listItem = trimmedLine.replace(/^-|\d+\./, '').trim();
705
- listItems.push(listItem);
706
- }
707
- }
708
- }
709
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
710
- finally {
711
- try {
712
- if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
713
- }
714
- finally { if (e_1) throw e_1.error; }
715
- }
716
- return listItems;
717
- }
718
-
719
- /**
720
- * Extracts exactly ONE code block from markdown.
721
- *
722
- * Note: If there are multiple or no code blocks the function throws an error
723
- *
724
- * Note: There are 3 simmilar function:
725
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
726
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
727
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
728
- *
729
- * @param markdown any valid markdown
730
- * @returns code block with language and content
731
- */
732
- function extractOneBlockFromMarkdown(markdown) {
733
- var codeBlocks = extractAllBlocksFromMarkdown(markdown);
734
- if (codeBlocks.length !== 1) {
735
- // TODO: Report more specific place where the error happened
736
- throw new Error(/* <- [🌻] */ 'There should be exactly one code block in the markdown');
968
+ jsxBracketSameLine: false,
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;
737
978
  }
738
- return codeBlocks[0];
739
- }
740
- /***
741
- * TODO: [🌻] !!! Decide of this is internal util, external util OR validator/postprocessor
742
- */
743
-
744
- /**
745
- * Removes HTML or Markdown comments from a string.
746
- *
747
- * @param {string} content - The string to remove comments from.
748
- * @returns {string} The input string with all comments removed.
749
- */
750
- function removeContentComments(content) {
751
- return spaceTrim(content.replace(/<!--(.*?)-->/gs, ''));
752
979
  }
753
980
 
754
981
  /**
@@ -832,11 +1059,11 @@ function normalizeTo_SCREAMING_CASE(sentence) {
832
1059
  */
833
1060
 
834
1061
  /* tslint:disable */
835
- function normalizeTo_camelCase(sentence, __firstLetterCapital) {
1062
+ function normalizeToKebabCase(sentence) {
836
1063
  var e_1, _a;
837
- if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1064
+ sentence = removeDiacritics(sentence);
838
1065
  var charType;
839
- var lastCharType = null;
1066
+ var lastCharType = 'OTHER';
840
1067
  var normalizedName = '';
841
1068
  try {
842
1069
  for (var sentence_1 = __values(sentence), sentence_1_1 = sentence_1.next(); !sentence_1_1.done; sentence_1_1 = sentence_1.next()) {
@@ -854,20 +1081,19 @@ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
854
1081
  charType = 'NUMBER';
855
1082
  normalizedChar = char;
856
1083
  }
1084
+ else if (/^\/$/.test(char)) {
1085
+ charType = 'SLASH';
1086
+ normalizedChar = char;
1087
+ }
857
1088
  else {
858
1089
  charType = 'OTHER';
859
- normalizedChar = '';
1090
+ normalizedChar = '-';
860
1091
  }
861
- if (!lastCharType) {
862
- if (__firstLetterCapital) {
863
- normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
864
- }
865
- }
866
- else if (charType !== lastCharType &&
867
- !(charType === 'LOWERCASE' && lastCharType === 'UPPERCASE') &&
1092
+ if (charType !== lastCharType &&
1093
+ !(lastCharType === 'UPPERCASE' && charType === 'LOWERCASE') &&
868
1094
  !(lastCharType === 'NUMBER') &&
869
1095
  !(charType === 'NUMBER')) {
870
- normalizedChar = normalizedChar.toUpperCase(); //TODO: [🌺] DRY
1096
+ normalizedName += '-';
871
1097
  }
872
1098
  normalizedName += normalizedChar;
873
1099
  lastCharType = charType;
@@ -880,207 +1106,67 @@ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
880
1106
  }
881
1107
  finally { if (e_1) throw e_1.error; }
882
1108
  }
1109
+ normalizedName = normalizedName.split(/-+/g).join('-');
1110
+ normalizedName = normalizedName.split(/-?\/-?/g).join('/');
1111
+ normalizedName = normalizedName.replace(/^-/, '');
1112
+ normalizedName = normalizedName.replace(/-$/, '');
883
1113
  return normalizedName;
884
1114
  }
885
- /**
886
- * TODO: [🌺] Use some intermediate util splitWords
887
- */
888
-
889
- function normalizeTo_PascalCase(sentence) {
890
- return normalizeTo_camelCase(sentence, true);
891
- }
892
-
893
- /**
894
- * Supported script languages
895
- */
896
- var SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
897
1115
 
898
- /**
899
- * Parses the template and returns the list of all parameter names
900
- *
901
- * @param template the template with parameters in {curly} braces
902
- * @returns the list of parameter names
903
- *
904
- * @private within the library
905
- */
906
- function extractParameters(template) {
1116
+ /* tslint:disable */
1117
+ function normalizeTo_camelCase(sentence, __firstLetterCapital) {
907
1118
  var e_1, _a;
908
- var matches = template.matchAll(/{\w+}/g);
909
- var parameterNames = [];
1119
+ if (__firstLetterCapital === void 0) { __firstLetterCapital = false; }
1120
+ var charType;
1121
+ var lastCharType = null;
1122
+ var normalizedName = '';
910
1123
  try {
911
- for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
912
- var match = matches_1_1.value;
913
- var parameterName = match[0].slice(1, -1);
914
- if (!parameterNames.includes(parameterName)) {
915
- 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;
916
1130
  }
917
- }
918
- }
919
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
920
- finally {
921
- try {
922
- if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
923
- }
924
- finally { if (e_1) throw e_1.error; }
925
- }
926
- return parameterNames;
927
- }
928
-
929
- /**
930
- * Computes the deepness of the markdown structure.
931
- *
932
- * @private within the library
933
- */
934
- function countMarkdownStructureDeepness(markdownStructure) {
935
- var e_1, _a;
936
- var maxDeepness = 0;
937
- try {
938
- for (var _b = __values(markdownStructure.sections), _c = _b.next(); !_c.done; _c = _b.next()) {
939
- var section = _c.value;
940
- maxDeepness = Math.max(maxDeepness, countMarkdownStructureDeepness(section));
941
- }
942
- }
943
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
944
- finally {
945
- try {
946
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
947
- }
948
- finally { if (e_1) throw e_1.error; }
949
- }
950
- return maxDeepness + 1;
951
- }
952
-
953
- /**
954
- * Parse a markdown string into a MarkdownStructure object.
955
- *
956
- * Note: This function does work with code blocks
957
- * Note: This function does not work with markdown comments
958
- *
959
- * @param markdown The markdown string to parse.
960
- * @returns The MarkdownStructure object.
961
- *
962
- * @private within the library
963
- */
964
- function markdownToMarkdownStructure(markdown) {
965
- var e_1, _a;
966
- var lines = markdown.split('\n');
967
- var root = { level: 0, title: '', contentLines: [], sections: [], parent: null };
968
- var current = root;
969
- var isInsideCodeBlock = false;
970
- try {
971
- for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
972
- var line = lines_1_1.value;
973
- var headingMatch = line.match(/^(?<mark>#{1,6})\s(?<title>.*)/);
974
- if (isInsideCodeBlock || !headingMatch) {
975
- if (line.startsWith('```')) {
976
- isInsideCodeBlock = !isInsideCodeBlock;
977
- }
978
- 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;
979
1138
  }
980
1139
  else {
981
- var level = headingMatch.groups.mark.length;
982
- var title = headingMatch.groups.title.trim();
983
- var parent_1 = void 0;
984
- if (level > current.level) {
985
- // Note: Going deeper (next section is child of current)
986
- parent_1 = current;
987
- }
988
- else {
989
- // Note: Going up or staying at the same level (next section is sibling or parent or grandparent,... of current)
990
- parent_1 = current;
991
- var loopLimit = LOOP_LIMIT;
992
- while (parent_1.level !== level - 1) {
993
- if (loopLimit-- < 0) {
994
- throw new UnexpectedError('Loop limit reached during parsing of markdown structure in `markdownToMarkdownStructure`');
995
- }
996
- if (parent_1.parent === null /* <- Note: We are in root */) {
997
- // [🌻]
998
- throw new Error(spaceTrim("\n The file has an invalid structure.\n The markdown file must have exactly one top-level section.\n "));
999
- }
1000
- parent_1 = parent_1.parent;
1001
- }
1140
+ charType = 'OTHER';
1141
+ normalizedChar = '';
1142
+ }
1143
+ if (!lastCharType) {
1144
+ if (__firstLetterCapital) {
1145
+ normalizedChar = normalizedChar.toUpperCase(); //TODO: DRY
1002
1146
  }
1003
- var section = { level: level, title: title, contentLines: [], sections: [], parent: parent_1 };
1004
- parent_1.sections.push(section);
1005
- current = section;
1006
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;
1007
1156
  }
1008
1157
  }
1009
1158
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
1010
1159
  finally {
1011
1160
  try {
1012
- 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);
1013
1162
  }
1014
1163
  finally { if (e_1) throw e_1.error; }
1015
1164
  }
1016
- if (root.sections.length === 1) {
1017
- var markdownStructure = parsingMarkdownStructureToMarkdownStructure(root.sections[0]);
1018
- return markdownStructure;
1019
- }
1020
- // [🌻]
1021
- throw new Error('The markdown file must have exactly one top-level section.');
1022
- // return root;
1023
- }
1024
- /**
1025
- * @private
1026
- */
1027
- function parsingMarkdownStructureToMarkdownStructure(parsingMarkdownStructure) {
1028
- var level = parsingMarkdownStructure.level, title = parsingMarkdownStructure.title, contentLines = parsingMarkdownStructure.contentLines, sections = parsingMarkdownStructure.sections;
1029
- return {
1030
- level: level,
1031
- title: title,
1032
- content: spaceTrim(contentLines.join('\n')),
1033
- sections: sections.map(parsingMarkdownStructureToMarkdownStructure),
1034
- };
1165
+ return normalizedName;
1035
1166
  }
1036
-
1037
1167
  /**
1038
- * Parses the given script and returns the list of all used variables that are not defined in the script
1039
- *
1040
- * @param script from which to extract the variables
1041
- * @returns the list of variable names
1042
- * @throws {PromptbookSyntaxError} if the script is invalid
1043
- *
1044
- * @private within the promptbookStringToJson
1168
+ * TODO: [🌺] Use some intermediate util splitWords
1045
1169
  */
1046
- function extractVariables(script) {
1047
- var variables = [];
1048
- script = "(()=>{".concat(script, "})()");
1049
- try {
1050
- for (var i = 0; i < 100 /* <- TODO: This limit to configuration */; i++)
1051
- try {
1052
- eval(script);
1053
- }
1054
- catch (error) {
1055
- if (!(error instanceof ReferenceError)) {
1056
- throw error;
1057
- }
1058
- var undefinedName = error.message.split(' ')[0];
1059
- /*
1060
- Note: Remapping error
1061
- From: [ReferenceError: thing is not defined],
1062
- To: [Error: Parameter {thing} is not defined],
1063
- */
1064
- if (!undefinedName) {
1065
- throw error;
1066
- }
1067
- if (script.includes(undefinedName + '(')) {
1068
- script = "const ".concat(undefinedName, " = ()=>'';") + script;
1069
- }
1070
- else {
1071
- variables.push(undefinedName);
1072
- script = "const ".concat(undefinedName, " = '';") + script;
1073
- }
1074
- }
1075
- }
1076
- catch (error) {
1077
- if (!(error instanceof Error)) {
1078
- throw error;
1079
- }
1080
- 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 "); }));
1081
- }
1082
- return variables;
1083
- }
1084
1170
 
1085
1171
  /**
1086
1172
  * Execution type describes the way how the block is executed
@@ -1590,7 +1676,7 @@ function promptbookStringToJson(promptbookString) {
1590
1676
  }
1591
1677
  dependentParameterNames = __spreadArray([], __read(new Set(dependentParameterNames)), false);
1592
1678
  promptbookJson.promptTemplates.push({
1593
- name: normalizeTo_PascalCase(section.title),
1679
+ name: titleToName(section.title),
1594
1680
  title: section.title,
1595
1681
  description: description_1,
1596
1682
  dependentParameterNames: dependentParameterNames,
@@ -1673,7 +1759,7 @@ function prettifyPromptbookString(promptbookString, options) {
1673
1759
  */
1674
1760
 
1675
1761
  /**
1676
- * !!! Initialize
1762
+ * Runs CLI script for prettifying promptbooks
1677
1763
  */
1678
1764
  function prettifyPromptbookStringCli() {
1679
1765
  return __awaiter(this, void 0, void 0, function () {