legal-markdown-js 2.15.0 → 2.16.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.
Files changed (120) hide show
  1. package/dist/cli/interactive/index.js +88 -35
  2. package/dist/cli/interactive/index.js.map +1 -1
  3. package/dist/cli/interactive/prompts/file-selector.js +5 -80
  4. package/dist/cli/interactive/prompts/file-selector.js.map +1 -1
  5. package/dist/cli/interactive/prompts/ftux-handler.d.ts +20 -0
  6. package/dist/cli/interactive/prompts/ftux-handler.d.ts.map +1 -0
  7. package/dist/cli/interactive/prompts/ftux-handler.js +356 -0
  8. package/dist/cli/interactive/prompts/ftux-handler.js.map +1 -0
  9. package/dist/cli/interactive/utils/file-input-helpers.d.ts +17 -0
  10. package/dist/cli/interactive/utils/file-input-helpers.d.ts.map +1 -0
  11. package/dist/cli/interactive/utils/file-input-helpers.js +96 -0
  12. package/dist/cli/interactive/utils/file-input-helpers.js.map +1 -0
  13. package/dist/cli/interactive/utils/installation-detector.d.ts +33 -0
  14. package/dist/cli/interactive/utils/installation-detector.d.ts.map +1 -0
  15. package/dist/cli/interactive/utils/installation-detector.js +107 -0
  16. package/dist/cli/interactive/utils/installation-detector.js.map +1 -0
  17. package/dist/examples/README.md +267 -0
  18. package/dist/examples/advanced/complex-nda/README.md +40 -0
  19. package/dist/examples/advanced/complex-nda/examples/output/nda-metadata.yaml +16 -0
  20. package/dist/examples/advanced/complex-nda/nda-data.json +71 -0
  21. package/dist/examples/advanced/complex-nda/nda-template.md +52 -0
  22. package/dist/examples/advanced/complex-nda/nda-with-data.md +107 -0
  23. package/dist/examples/advanced/complex-nda/run.sh +59 -0
  24. package/dist/examples/advanced/office-lease-complete/README.md +41 -0
  25. package/dist/examples/advanced/office-lease-complete/lease-agreement.md +217 -0
  26. package/dist/examples/advanced/office-lease-complete/lease-data.json +123 -0
  27. package/dist/examples/advanced/office-lease-complete/lease-with-data.md +283 -0
  28. package/dist/examples/advanced/office-lease-complete/run.sh +62 -0
  29. package/dist/examples/basic-processing/simple-document/README.md +39 -0
  30. package/dist/examples/basic-processing/simple-document/example.html +64 -0
  31. package/dist/examples/basic-processing/simple-document/example.md +92 -0
  32. package/dist/examples/basic-processing/simple-document/example.output.md +64 -0
  33. package/dist/examples/basic-processing/simple-document/examples/output/metadata.json +20 -0
  34. package/dist/examples/basic-processing/simple-document/input.html +34 -0
  35. package/dist/examples/basic-processing/simple-document/input.md +12 -0
  36. package/dist/examples/basic-processing/simple-document/input.output.md +6 -0
  37. package/dist/examples/basic-processing/simple-document/run.sh +46 -0
  38. package/dist/examples/basic-processing/yaml-frontmatter/README.md +37 -0
  39. package/dist/examples/basic-processing/yaml-frontmatter/document.md +72 -0
  40. package/dist/examples/basic-processing/yaml-frontmatter/run.sh +45 -0
  41. package/dist/examples/cross-references/basic-references/README.md +37 -0
  42. package/dist/examples/cross-references/basic-references/agreement.md +111 -0
  43. package/dist/examples/cross-references/basic-references/correct-example.md +60 -0
  44. package/dist/examples/cross-references/basic-references/internal-references.md +48 -0
  45. package/dist/examples/cross-references/basic-references/run.sh +46 -0
  46. package/dist/examples/cross-references/complex-references/agreement-data.json +24 -0
  47. package/dist/examples/data/advanced-metadata.json +8 -0
  48. package/dist/examples/data/agreement-metadata.json +24 -0
  49. package/dist/examples/data/ticket-data.json +71 -0
  50. package/dist/examples/force-commands/README.md +164 -0
  51. package/dist/examples/force-commands/contract-with-forced-options.md +75 -0
  52. package/dist/examples/headers/header-tracking/README.md +35 -0
  53. package/dist/examples/headers/header-tracking/run.sh +40 -0
  54. package/dist/examples/headers/header-tracking/tracked-document.md +32 -0
  55. package/dist/examples/headers/mixed-header-styles/README.md +35 -0
  56. package/dist/examples/headers/mixed-header-styles/document.md +48 -0
  57. package/dist/examples/headers/mixed-header-styles/run.sh +40 -0
  58. package/dist/examples/headers/multiple-headers/README.md +35 -0
  59. package/dist/examples/headers/multiple-headers/contract.md +61 -0
  60. package/dist/examples/headers/multiple-headers/run.sh +40 -0
  61. package/dist/examples/imports/frontmatter-merging/README.md +268 -0
  62. package/dist/examples/imports/frontmatter-merging/components/client-info.md +139 -0
  63. package/dist/examples/imports/frontmatter-merging/components/service-levels.md +178 -0
  64. package/dist/examples/imports/frontmatter-merging/components/standard-terms.md +100 -0
  65. package/dist/examples/imports/frontmatter-merging/main-contract.md +169 -0
  66. package/dist/examples/imports/frontmatter-merging/output/contract-metadata.json +220 -0
  67. package/dist/examples/imports/frontmatter-merging/output/contract-metadata.yaml +182 -0
  68. package/dist/examples/imports/frontmatter-merging/run.sh +274 -0
  69. package/dist/examples/imports/frontmatter-merging/templates/basic-service-agreement.md +83 -0
  70. package/dist/examples/imports/frontmatter-merging/templates/complex-enterprise-contract.md +260 -0
  71. package/dist/examples/imports/frontmatter-merging/templates/output/enterprise-contract-metadata.json +226 -0
  72. package/dist/examples/imports/frontmatter-merging/templates/output/enterprise-contract-metadata.yaml +188 -0
  73. package/dist/examples/imports/partial-imports/README.md +38 -0
  74. package/dist/examples/imports/partial-imports/clauses/confidentiality.md +12 -0
  75. package/dist/examples/imports/partial-imports/main-contract.md +52 -0
  76. package/dist/examples/imports/partial-imports/partials/footer.md +3 -0
  77. package/dist/examples/imports/partial-imports/partials/header.md +3 -0
  78. package/dist/examples/imports/partial-imports/partials/terms.md +3 -0
  79. package/dist/examples/imports/partial-imports/run.sh +48 -0
  80. package/dist/examples/input/README.md +66 -0
  81. package/dist/examples/input/demo-contract.md +60 -0
  82. package/dist/examples/input/example.md +92 -0
  83. package/dist/examples/input/examples/output/metadata.json +20 -0
  84. package/dist/examples/input/metadata-example.md +94 -0
  85. package/dist/examples/input/office-lease-with-data.md +297 -0
  86. package/dist/examples/input/purchase-ticket.md +94 -0
  87. package/dist/examples/input/simple-contract.md +61 -0
  88. package/dist/examples/input/ticket-with-data.md +92 -0
  89. package/dist/examples/input/ticket.md +52 -0
  90. package/dist/examples/integration/cli-usage/README.md +40 -0
  91. package/dist/examples/integration/cli-usage/demo-contract.md +60 -0
  92. package/dist/examples/integration/cli-usage/run.sh +62 -0
  93. package/dist/examples/integration/cli-usage/simple-contract.md +61 -0
  94. package/dist/examples/mixins/helper-functions/README.md +36 -0
  95. package/dist/examples/mixins/helper-functions/contract-data.json +8 -0
  96. package/dist/examples/mixins/helper-functions/formatted-contract.md +45 -0
  97. package/dist/examples/mixins/helper-functions/run.sh +55 -0
  98. package/dist/examples/mixins/template-loops/README.md +34 -0
  99. package/dist/examples/mixins/template-loops/items-list.md +56 -0
  100. package/dist/examples/mixins/template-loops/run.sh +40 -0
  101. package/dist/examples/optional-clauses/boolean-logic/README.md +34 -0
  102. package/dist/examples/optional-clauses/boolean-logic/complex-conditions.md +101 -0
  103. package/dist/examples/optional-clauses/boolean-logic/examples/output/nda-metadata.yaml +10 -0
  104. package/dist/examples/optional-clauses/boolean-logic/run.sh +40 -0
  105. package/dist/examples/optional-clauses/conditional-content/README.md +35 -0
  106. package/dist/examples/optional-clauses/conditional-content/nda-template.md +82 -0
  107. package/dist/examples/optional-clauses/conditional-content/run.sh +40 -0
  108. package/dist/examples/output/demo-contract-simple.md +44 -0
  109. package/dist/examples/output-formats/metadata-export/README.md +36 -0
  110. package/dist/examples/output-formats/metadata-export/document-with-meta.md +94 -0
  111. package/dist/examples/output-formats/metadata-export/run.sh +44 -0
  112. package/dist/examples/output-formats/pdf-generation/README.md +36 -0
  113. package/dist/examples/output-formats/pdf-generation/printable-agreement.md +200 -0
  114. package/dist/examples/output-formats/pdf-generation/run.sh +44 -0
  115. package/dist/examples/run-all.sh +105 -0
  116. package/dist/examples/styles/contract.css +346 -0
  117. package/dist/examples/styles/ticket.css +100 -0
  118. package/dist/examples/templates/README.md +30 -0
  119. package/dist/examples/templates/run.sh +101 -0
  120. package/package.json +3 -2
@@ -29,8 +29,85 @@ import { selectCssFile } from './prompts/css-selector.js';
29
29
  import { promptOutputFilename } from './prompts/filename.js';
30
30
  import { promptArchiveOptions } from './prompts/archive-options.js';
31
31
  import { confirmConfiguration } from './prompts/confirmation.js';
32
+ import { handleFirstTimeUserExperience } from './prompts/ftux-handler.js';
32
33
  import { InteractiveService } from './service.js';
33
34
  import { formatSuccessMessage, formatErrorMessage } from './utils/format-helpers.js';
35
+ /**
36
+ * Run FTUX (First-Time User Experience) mode
37
+ *
38
+ * Provides a guided onboarding experience for new users with options to:
39
+ * - Set up configuration files
40
+ * - Try demo examples
41
+ * - Get help and tutorials
42
+ * - Browse for files manually
43
+ *
44
+ * @returns Promise that resolves when FTUX completes
45
+ * @throws Error when FTUX fails or user cancels
46
+ */
47
+ async function runFtuxMode() {
48
+ try {
49
+ console.log(chalk.bold.blue('\n🌟 Legal Markdown - First-Time User Experience\n'));
50
+ console.log(chalk.gray("Welcome! Let's get you started with Legal Markdown processing.\n"));
51
+ // Run the FTUX flow
52
+ const selectedFile = await handleFirstTimeUserExperience();
53
+ // If a file was selected from FTUX, continue with normal processing
54
+ if (selectedFile) {
55
+ console.log(chalk.green(`\nāœ… Selected: ${selectedFile}`));
56
+ console.log(chalk.gray('Continuing with normal processing flow...\n'));
57
+ // Continue with the normal interactive flow starting from step 2
58
+ await continueInteractiveFlow(selectedFile);
59
+ }
60
+ }
61
+ catch (error) {
62
+ if (error instanceof Error && error.message.includes('User force closed')) {
63
+ console.log(chalk.yellow('\nšŸ‘‹ Thanks for trying Legal Markdown!\n'));
64
+ return;
65
+ }
66
+ console.log(formatErrorMessage(error instanceof Error ? error.message : String(error)));
67
+ process.exit(1);
68
+ }
69
+ }
70
+ /**
71
+ * Continue interactive flow from a selected file (used after FTUX)
72
+ *
73
+ * @param inputFile - The file selected from FTUX
74
+ */
75
+ async function continueInteractiveFlow(inputFile) {
76
+ // Step 2: Select output formats
77
+ const outputFormats = await selectOutputFormats();
78
+ // Step 3: Configure processing options
79
+ const processingOptions = await promptProcessingOptions(outputFormats);
80
+ // Step 4: Select CSS file (if needed)
81
+ const cssFile = await selectCssFile(outputFormats);
82
+ // Step 5: Enter output filename
83
+ const outputFilename = await promptOutputFilename(inputFile);
84
+ // Step 6: Configure archive options
85
+ const archiveResult = await promptArchiveOptions();
86
+ const archiveOptions = {
87
+ enabled: archiveResult.enableArchiving,
88
+ directory: archiveResult.archiveDirectory,
89
+ };
90
+ // Build configuration
91
+ const config = {
92
+ inputFile,
93
+ outputFilename,
94
+ outputFormats,
95
+ processingOptions,
96
+ archiveOptions,
97
+ cssFile,
98
+ };
99
+ // Step 7: Confirm configuration
100
+ const confirmed = await confirmConfiguration(config);
101
+ if (!confirmed) {
102
+ console.log(chalk.yellow('\nāŒ Operation cancelled.\n'));
103
+ return;
104
+ }
105
+ // Step 8: Process files
106
+ const service = new InteractiveService(config);
107
+ const result = await service.processFile(inputFile);
108
+ // Step 9: Show results
109
+ console.log(formatSuccessMessage(result.outputFiles, result.archiveResult));
110
+ }
34
111
  /**
35
112
  * Main interactive flow that guides users through the complete Legal Markdown processing workflow
36
113
  *
@@ -53,40 +130,8 @@ async function runInteractiveMode() {
53
130
  console.log(chalk.gray('Follow the prompts to configure your document processing.\n'));
54
131
  // Step 1: Select input file
55
132
  const inputFile = await selectInputFile();
56
- // Step 2: Select output formats
57
- const outputFormats = await selectOutputFormats();
58
- // Step 3: Configure processing options
59
- const processingOptions = await promptProcessingOptions(outputFormats);
60
- // Step 4: Select CSS file (if needed)
61
- const cssFile = await selectCssFile(outputFormats);
62
- // Step 5: Enter output filename
63
- const outputFilename = await promptOutputFilename(inputFile);
64
- // Step 6: Configure archive options
65
- const archiveResult = await promptArchiveOptions();
66
- const archiveOptions = {
67
- enabled: archiveResult.enableArchiving,
68
- directory: archiveResult.archiveDirectory,
69
- };
70
- // Build configuration
71
- const config = {
72
- inputFile,
73
- outputFilename,
74
- outputFormats,
75
- processingOptions,
76
- archiveOptions,
77
- cssFile,
78
- };
79
- // Step 7: Confirm configuration
80
- const confirmed = await confirmConfiguration(config);
81
- if (!confirmed) {
82
- console.log(chalk.yellow('\nāŒ Operation cancelled.\n'));
83
- return;
84
- }
85
- // Step 8: Process files
86
- const service = new InteractiveService(config);
87
- const result = await service.processFile(inputFile);
88
- // Step 9: Show results
89
- console.log(formatSuccessMessage(result.outputFiles, result.archiveResult));
133
+ // Continue with the rest of the flow
134
+ await continueInteractiveFlow(inputFile);
90
135
  }
91
136
  catch (error) {
92
137
  if (error instanceof Error && error.message.includes('User force closed')) {
@@ -104,7 +149,15 @@ program
104
149
  .name('legal-md-ui')
105
150
  .description('Interactive CLI for Legal Markdown document processing')
106
151
  .version('0.1.0')
107
- .action(runInteractiveMode);
152
+ .option('--ftux', 'Launch First-Time User Experience (setup wizard)')
153
+ .action(async (options) => {
154
+ if (options.ftux) {
155
+ await runFtuxMode();
156
+ }
157
+ else {
158
+ await runInteractiveMode();
159
+ }
160
+ });
108
161
  // Parse command line arguments
109
162
  program.parse();
110
163
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/interactive/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/interactive/index.ts"],"names":[],"mappings":"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"}
@@ -7,13 +7,13 @@
7
7
  *
8
8
  * @module
9
9
  */
10
- import { select, input } from '@inquirer/prompts';
11
- import * as path from 'path';
12
- import * as fs from 'fs';
10
+ import { select } from '@inquirer/prompts';
13
11
  import chalk from 'chalk';
14
12
  import { RESOLVED_PATHS } from '../../../constants/index.js';
15
- import { scanDirectory, isValidFile } from '../utils/file-scanner.js';
13
+ import { scanDirectory } from '../utils/file-scanner.js';
16
14
  import { formatWarningMessage } from '../utils/format-helpers.js';
15
+ import { handleFirstTimeUserExperience } from './ftux-handler.js';
16
+ import { handleBrowseFolder, handleManualInput } from '../utils/file-input-helpers.js';
17
17
  /** Option for browsing alternative directories */
18
18
  const BROWSE_OPTION = 'šŸ“ Browse other folder...';
19
19
  /** Option for manual path entry */
@@ -35,7 +35,7 @@ export async function selectInputFile() {
35
35
  const files = scanDirectory(RESOLVED_PATHS.DEFAULT_INPUT_DIR);
36
36
  if (files.length === 0) {
37
37
  console.log(formatWarningMessage('No supported files found in the default directory.'));
38
- return await handleManualInput();
38
+ return await handleFirstTimeUserExperience();
39
39
  }
40
40
  const choices = [
41
41
  ...files.map(file => ({
@@ -63,79 +63,4 @@ export async function selectInputFile() {
63
63
  return selectedFile;
64
64
  }
65
65
  }
66
- /**
67
- * Handle browsing to a different folder
68
- */
69
- async function handleBrowseFolder() {
70
- const folderPath = await input({
71
- message: 'Enter folder path to browse:',
72
- default: RESOLVED_PATHS.DEFAULT_INPUT_DIR,
73
- validate: (value) => {
74
- const resolvedPath = path.resolve(value);
75
- try {
76
- if (!fs.existsSync(resolvedPath)) {
77
- return 'Folder does not exist';
78
- }
79
- if (!fs.statSync(resolvedPath).isDirectory()) {
80
- return 'Path is not a directory';
81
- }
82
- return true;
83
- }
84
- catch {
85
- return 'Invalid folder path';
86
- }
87
- },
88
- });
89
- const resolvedPath = path.resolve(folderPath);
90
- console.log(chalk.cyan(`šŸ” Searching for files in: ${resolvedPath}\n`));
91
- const files = scanDirectory(resolvedPath);
92
- if (files.length === 0) {
93
- console.log(formatWarningMessage('No supported files found in this directory.'));
94
- return await handleManualInput();
95
- }
96
- const choices = [
97
- ...files.map(file => ({
98
- name: file.name,
99
- value: file.path,
100
- })),
101
- { name: MANUAL_OPTION, value: MANUAL_OPTION },
102
- { name: EXIT_OPTION, value: EXIT_OPTION },
103
- ];
104
- const selectedFile = await select({
105
- message: 'Select an input file:',
106
- choices,
107
- });
108
- if (selectedFile === MANUAL_OPTION) {
109
- return await handleManualInput();
110
- }
111
- if (selectedFile === EXIT_OPTION) {
112
- console.log(chalk.yellow('šŸ‘‹ Goodbye!'));
113
- process.exit(0);
114
- }
115
- return selectedFile;
116
- }
117
- /**
118
- * Handle manual file path input
119
- */
120
- async function handleManualInput() {
121
- const filePath = await input({
122
- message: 'Enter file path:',
123
- validate: (value) => {
124
- if (!value.trim()) {
125
- return 'File path is required';
126
- }
127
- const resolvedPath = path.resolve(value.trim());
128
- if (!isValidFile(resolvedPath)) {
129
- return 'File does not exist or is not readable';
130
- }
131
- const ext = path.extname(resolvedPath).toLowerCase();
132
- const supportedExts = ['.md', '.markdown', '.rst', '.tex', '.latex', '.txt'];
133
- if (!supportedExts.includes(ext)) {
134
- return `Unsupported file type. Supported: ${supportedExts.join(', ')}`;
135
- }
136
- return true;
137
- },
138
- });
139
- return path.resolve(filePath.trim());
140
- }
141
66
  //# sourceMappingURL=file-selector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-selector.js","sourceRoot":"","sources":["../../../../src/cli/interactive/prompts/file-selector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-selector.js","sourceRoot":"","sources":["../../../../src/cli/interactive/prompts/file-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEpF,kDAAkD;AAClD,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAClD,mCAAmC;AACnC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAClD,yCAAyC;AACzC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAE7B;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,cAAc,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC;IAE5F,MAAM,KAAK,GAAG,aAAa,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAE9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,oDAAoD,CAAC,CAAC,CAAC;QACxF,OAAO,MAAM,6BAA6B,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,OAAO,GAAG;QACd,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,IAAI;SACjB,CAAC,CAAC;QACH,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;QAC7C,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;QAC7C,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;KAC1C,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC;QAChC,OAAO,EAAE,uBAAuB;QAChC,OAAO;KACR,CAAC,CAAC;IAEH,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,MAAM,kBAAkB,EAAE,CAAC;QACpC,KAAK,aAAa;YAChB,OAAO,MAAM,iBAAiB,EAAE,CAAC;QACnC,KAAK,WAAW;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,MAAM;QACR;YACE,OAAO,YAAY,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * First Time User Experience (FTUX) handler for Interactive CLI
3
+ *
4
+ * This module provides an improved onboarding experience for new users
5
+ * when no files are found in the default directory, offering setup
6
+ * assistance, demo examples, and guided configuration.
7
+ *
8
+ * @module
9
+ */
10
+ /**
11
+ * Handle first-time user experience when no files are found
12
+ *
13
+ * Provides a friendly onboarding flow with multiple options to help
14
+ * new users get started with Legal Markdown processing.
15
+ *
16
+ * @returns Promise resolving to the selected input file path
17
+ * @throws Error when user cancels or no valid option is selected
18
+ */
19
+ export declare function handleFirstTimeUserExperience(): Promise<string>;
20
+ //# sourceMappingURL=ftux-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ftux-handler.d.ts","sourceRoot":"","sources":["../../../../src/cli/interactive/prompts/ftux-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAwCH;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,MAAM,CAAC,CAuCrE"}
@@ -0,0 +1,356 @@
1
+ /**
2
+ * First Time User Experience (FTUX) handler for Interactive CLI
3
+ *
4
+ * This module provides an improved onboarding experience for new users
5
+ * when no files are found in the default directory, offering setup
6
+ * assistance, demo examples, and guided configuration.
7
+ *
8
+ * @module
9
+ */
10
+ import { select, input, confirm } from '@inquirer/prompts';
11
+ import * as path from 'path';
12
+ import * as fs from 'fs';
13
+ import chalk from 'chalk';
14
+ // import { RESOLVED_PATHS } from '../../../constants/index.js';
15
+ import { scanDirectory } from '../utils/file-scanner.js';
16
+ import { formatWarningMessage } from '../utils/format-helpers.js';
17
+ import { handleBrowseFolder, handleManualInput } from '../utils/file-input-helpers.js';
18
+ import { getEnvFilePath, getInstallationDescription } from '../utils/installation-detector.js';
19
+ /**
20
+ * Get current directory path in a way that works for both ESM and CJS
21
+ * Since we're building from dist, we can use relative paths from the script location
22
+ */
23
+ function getCurrentDir() {
24
+ // Use process.argv[1] to determine script location - works for both ESM and CJS
25
+ const scriptPath = process.argv[1] || process.cwd();
26
+ return path.dirname(scriptPath);
27
+ }
28
+ /** Option for setting up configuration */
29
+ const SETUP_CONFIG_OPTION = 'šŸ› ļø Setup configuration (.env)';
30
+ /** Option for trying a demo example */
31
+ const TRY_DEMO_OPTION = 'šŸŽÆ Try a demo example';
32
+ /** Option for browsing different folder */
33
+ const BROWSE_FOLDER_OPTION = 'šŸ“ Browse different folder';
34
+ /** Option for manual file input */
35
+ const MANUAL_INPUT_OPTION = 'šŸ“ Enter file path manually';
36
+ /** Option for getting help/tutorial */
37
+ const GET_HELP_OPTION = 'šŸ“– Show help & tutorial';
38
+ /** Option for exiting */
39
+ const EXIT_OPTION = 'āŒ Exit';
40
+ /**
41
+ * Handle first-time user experience when no files are found
42
+ *
43
+ * Provides a friendly onboarding flow with multiple options to help
44
+ * new users get started with Legal Markdown processing.
45
+ *
46
+ * @returns Promise resolving to the selected input file path
47
+ * @throws Error when user cancels or no valid option is selected
48
+ */
49
+ export async function handleFirstTimeUserExperience() {
50
+ console.log(chalk.yellow('\n🌟 Welcome to Legal Markdown!'));
51
+ console.log(chalk.gray("It looks like you're getting started. Let me help you with that.\n"));
52
+ const choice = await select({
53
+ message: 'What would you like to do?',
54
+ choices: [
55
+ { name: SETUP_CONFIG_OPTION, value: 'setup' },
56
+ { name: TRY_DEMO_OPTION, value: 'demo' },
57
+ { name: BROWSE_FOLDER_OPTION, value: 'browse' },
58
+ { name: MANUAL_INPUT_OPTION, value: 'manual' },
59
+ { name: GET_HELP_OPTION, value: 'help' },
60
+ { name: EXIT_OPTION, value: 'exit' },
61
+ ],
62
+ });
63
+ switch (choice) {
64
+ case 'setup':
65
+ return await handleSetupConfiguration();
66
+ case 'demo':
67
+ return await handleDemoExample();
68
+ case 'browse':
69
+ return await handleBrowseFolder();
70
+ case 'manual':
71
+ return await handleManualInput();
72
+ case 'help':
73
+ await showHelpAndTutorial();
74
+ // After showing help, ask again
75
+ return await handleFirstTimeUserExperience();
76
+ case 'exit':
77
+ console.log(chalk.yellow('\nšŸ‘‹ Thanks for trying Legal Markdown!'));
78
+ console.log(chalk.gray('Run ') + chalk.cyan('legal-md-ui') + chalk.gray(" again when you're ready."));
79
+ process.exit(0);
80
+ break;
81
+ default:
82
+ throw new Error('Invalid option selected');
83
+ }
84
+ }
85
+ /**
86
+ * Handle setup configuration workflow
87
+ */
88
+ async function handleSetupConfiguration() {
89
+ console.log(chalk.cyan('\nšŸ› ļø Configuration Setup'));
90
+ console.log(chalk.gray("Let's set up your preferred directories for Legal Markdown processing."));
91
+ console.log(chalk.gray(getInstallationDescription() + '\n'));
92
+ // Ask for input directory
93
+ const inputDir = await input({
94
+ message: 'Where do you keep your markdown files? (input directory)',
95
+ default: process.cwd(),
96
+ validate: value => {
97
+ const resolvedPath = path.resolve(value);
98
+ if (!fs.existsSync(resolvedPath)) {
99
+ return 'Directory does not exist. Please enter a valid path.';
100
+ }
101
+ if (!fs.statSync(resolvedPath).isDirectory()) {
102
+ return 'Path is not a directory.';
103
+ }
104
+ return true;
105
+ },
106
+ });
107
+ // Ask for output directory
108
+ const outputDir = await input({
109
+ message: 'Where should processed files be saved? (output directory)',
110
+ default: path.join(path.resolve(inputDir), 'output'),
111
+ validate: value => {
112
+ const resolvedPath = path.resolve(value);
113
+ const parentDir = path.dirname(resolvedPath);
114
+ if (!fs.existsSync(parentDir)) {
115
+ return 'Parent directory does not exist.';
116
+ }
117
+ return true;
118
+ },
119
+ });
120
+ // Create .env configuration using installation-aware path
121
+ const envPath = getEnvFilePath();
122
+ const envContent = `# Legal Markdown Configuration
123
+ # Generated by interactive setup
124
+
125
+ LEGALMD_INPUT_DIR="${path.resolve(inputDir)}"
126
+ LEGALMD_OUTPUT_DIR="${path.resolve(outputDir)}"
127
+ LEGALMD_STYLES_DIR="${path.resolve(inputDir, 'styles')}"
128
+ LEGALMD_ARCHIVE_DIR="${path.resolve(outputDir, 'archive')}"
129
+ `;
130
+ // Check if .env already exists
131
+ if (fs.existsSync(envPath)) {
132
+ const overwrite = await confirm({
133
+ message: 'A .env file already exists. Overwrite it?',
134
+ default: false,
135
+ });
136
+ if (!overwrite) {
137
+ console.log(chalk.yellow('āš ļø Setup cancelled. Using existing configuration.'));
138
+ }
139
+ else {
140
+ fs.writeFileSync(envPath, envContent);
141
+ console.log(chalk.green(`āœ… Configuration saved to ${envPath}`));
142
+ }
143
+ }
144
+ else {
145
+ fs.writeFileSync(envPath, envContent);
146
+ console.log(chalk.green(`āœ… Configuration saved to ${envPath}`));
147
+ }
148
+ // Create output directory if it doesn't exist
149
+ const resolvedOutputDir = path.resolve(outputDir);
150
+ if (!fs.existsSync(resolvedOutputDir)) {
151
+ fs.mkdirSync(resolvedOutputDir, { recursive: true });
152
+ console.log(chalk.green(`āœ… Created output directory: ${resolvedOutputDir}`));
153
+ }
154
+ // Now scan for files in the configured input directory
155
+ console.log(chalk.cyan(`\nšŸ” Scanning for files in: ${path.resolve(inputDir)}\n`));
156
+ const files = scanDirectory(path.resolve(inputDir));
157
+ if (files.length === 0) {
158
+ console.log(formatWarningMessage('No supported files found in the configured directory.'));
159
+ console.log(chalk.gray('You can add .md, .markdown, .rst, .tex, or .txt files to get started.\n'));
160
+ const nextAction = await select({
161
+ message: 'What would you like to do next?',
162
+ choices: [
163
+ { name: TRY_DEMO_OPTION, value: 'demo' },
164
+ { name: MANUAL_INPUT_OPTION, value: 'manual' },
165
+ { name: EXIT_OPTION, value: 'exit' },
166
+ ],
167
+ });
168
+ switch (nextAction) {
169
+ case 'demo':
170
+ return await handleDemoExample();
171
+ case 'manual':
172
+ return await handleManualInput();
173
+ case 'exit':
174
+ process.exit(0);
175
+ }
176
+ }
177
+ // Show available files
178
+ const choices = [
179
+ ...files.map(file => ({
180
+ name: file.name,
181
+ value: file.path,
182
+ })),
183
+ { name: TRY_DEMO_OPTION, value: 'demo' },
184
+ { name: EXIT_OPTION, value: 'exit' },
185
+ ];
186
+ const selectedFile = await select({
187
+ message: 'Select a file to process:',
188
+ choices,
189
+ });
190
+ if (selectedFile === 'demo') {
191
+ return await handleDemoExample();
192
+ }
193
+ if (selectedFile === 'exit') {
194
+ process.exit(0);
195
+ }
196
+ return selectedFile;
197
+ }
198
+ /**
199
+ * Handle demo example selection
200
+ */
201
+ async function handleDemoExample() {
202
+ console.log(chalk.cyan('\nšŸŽÆ Demo Examples'));
203
+ console.log(chalk.gray('Try Legal Markdown with these built-in examples.\n'));
204
+ // Get examples from the package - try multiple locations
205
+ const currentDir = getCurrentDir();
206
+ const possibleExamplesDirs = [
207
+ // In dist for development or when running from source
208
+ path.join(currentDir, '../../..', 'dist', 'examples'),
209
+ // In node_modules for installed package
210
+ path.join(process.cwd(), 'node_modules', 'legal-markdown-js', 'dist', 'examples'),
211
+ path.join(process.cwd(), 'node_modules', 'legal-markdown-js', 'examples'),
212
+ // Global installation paths
213
+ path.join(path.dirname(process.argv[1] || ''), '..', 'examples'),
214
+ path.join(path.dirname(process.argv[1] || ''), '..', 'dist', 'examples'),
215
+ ];
216
+ const availableExamples = [];
217
+ let examplesDir = '';
218
+ // Find the first existing examples directory
219
+ for (const dir of possibleExamplesDirs) {
220
+ if (fs.existsSync(dir)) {
221
+ examplesDir = dir;
222
+ break;
223
+ }
224
+ }
225
+ if (examplesDir) {
226
+ const basicExample = path.join(examplesDir, 'basic-processing', 'simple-document', 'example.md');
227
+ const advancedExample = path.join(examplesDir, 'advanced', 'complex-nda', 'nda-with-data.md');
228
+ if (fs.existsSync(basicExample)) {
229
+ availableExamples.push({
230
+ name: 'šŸ“ Basic Document Processing',
231
+ path: basicExample,
232
+ description: 'Simple markdown with template fields',
233
+ });
234
+ }
235
+ if (fs.existsSync(advancedExample)) {
236
+ availableExamples.push({
237
+ name: 'šŸ“‹ Advanced NDA Contract',
238
+ path: advancedExample,
239
+ description: 'Complex contract with conditional clauses',
240
+ });
241
+ }
242
+ }
243
+ // Fallback: create a simple demo file in current directory
244
+ if (availableExamples.length === 0) {
245
+ const demoPath = path.join(process.cwd(), 'legal-markdown-demo.md');
246
+ const demoContent = `---
247
+ title: "Sample Legal Document"
248
+ party1: "Acme Corporation"
249
+ party2: "[Enter Client Name]"
250
+ date: "{{formatDate(today, 'MMMM dd, yyyy')}}"
251
+ jurisdiction: "California"
252
+ ---
253
+
254
+ # {{title}}
255
+
256
+ This agreement is entered into on {{date}} between {{party1}} and {{party2}}.
257
+
258
+ ## 1. Terms and Conditions
259
+
260
+ l. **Effective Date**: This agreement becomes effective on {{date}}.
261
+
262
+ l. **Jurisdiction**: This agreement shall be governed by the laws of {{jurisdiction}}.
263
+
264
+ {{#if party2}}
265
+ l. **Parties**: The contracting parties are {{party1}} and {{party2}}.
266
+ {{else}}
267
+ l. **Party**: The contracting party is {{party1}}.
268
+ {{/if}}
269
+
270
+ ---
271
+
272
+ *This is a demo document showing Legal Markdown features:*
273
+ - *Template fields: {{party1}}, {{party2}}*
274
+ - *Date formatting: {{date}}*
275
+ - *Conditional clauses: {{#if party2}}*
276
+ - *Automatic numbering: l.*
277
+ `;
278
+ try {
279
+ fs.writeFileSync(demoPath, demoContent);
280
+ availableExamples.push({
281
+ name: 'šŸŽÆ Generated Demo Document',
282
+ path: demoPath,
283
+ description: 'A sample document created just for you',
284
+ });
285
+ console.log(chalk.green(`āœ… Created demo file: ${demoPath}`));
286
+ }
287
+ catch (error) {
288
+ console.log(chalk.yellow(`āš ļø Could not create demo file: ${error instanceof Error ? error.message : String(error)}`));
289
+ }
290
+ }
291
+ if (availableExamples.length === 0) {
292
+ console.log(chalk.red('āŒ No demo examples available.'));
293
+ return await handleManualInput();
294
+ }
295
+ const choices = [
296
+ ...availableExamples.map(example => ({
297
+ name: `${example.name}\n ${chalk.gray(example.description)}`,
298
+ value: example.path,
299
+ })),
300
+ { name: '← Back to main menu', value: 'back' },
301
+ ];
302
+ const selectedExample = await select({
303
+ message: 'Choose a demo example:',
304
+ choices,
305
+ });
306
+ if (selectedExample === 'back') {
307
+ return await handleFirstTimeUserExperience();
308
+ }
309
+ console.log(chalk.green(`\nāœ… Selected demo: ${selectedExample}`));
310
+ console.log(chalk.gray('You can examine this file after processing to see how Legal Markdown works.\n'));
311
+ return selectedExample;
312
+ }
313
+ /**
314
+ * Show help and tutorial information
315
+ */
316
+ async function showHelpAndTutorial() {
317
+ console.log(chalk.cyan('\nšŸ“– Legal Markdown Help & Tutorial\n'));
318
+ console.log(chalk.bold('What is Legal Markdown?'));
319
+ console.log(chalk.gray('Legal Markdown is a tool for processing legal documents written in Markdown'));
320
+ console.log(chalk.gray('with YAML metadata and template fields.\n'));
321
+ console.log(chalk.bold('Key Features:'));
322
+ console.log(chalk.gray('• šŸ“ Template fields: {{party1}}, {{date}}, etc.'));
323
+ console.log(chalk.gray('• šŸ”¢ Auto-numbering: l. for numbered clauses'));
324
+ console.log(chalk.gray('• ā“ Conditional clauses: {{#if condition}}...{{/if}}'));
325
+ console.log(chalk.gray('• šŸ“… Date formatting: {{formatDate(date, "MMM dd, yyyy")}}'));
326
+ console.log(chalk.gray('• šŸ“„ Multiple output formats: HTML, PDF, Markdown'));
327
+ console.log(chalk.gray('• šŸŽØ Custom styling with CSS\n'));
328
+ console.log(chalk.bold('Example Document Structure:'));
329
+ console.log(chalk.gray('```'));
330
+ console.log(chalk.gray('---'));
331
+ console.log(chalk.gray('title: "My Contract"'));
332
+ console.log(chalk.gray('party1: "Company A"'));
333
+ console.log(chalk.gray('date: "2024-01-15"'));
334
+ console.log(chalk.gray('---'));
335
+ console.log(chalk.gray(''));
336
+ console.log(chalk.gray('# {{title}}'));
337
+ console.log(chalk.gray(''));
338
+ console.log(chalk.gray('Agreement between {{party1}} dated {{formatDate(date, "MMMM dd, yyyy")}}.'));
339
+ console.log(chalk.gray(''));
340
+ console.log(chalk.gray('l. First clause'));
341
+ console.log(chalk.gray('l. Second clause'));
342
+ console.log(chalk.gray('```\n'));
343
+ console.log(chalk.bold('Getting Started:'));
344
+ console.log(chalk.gray('1. šŸ› ļø Setup: Configure your input/output directories'));
345
+ console.log(chalk.gray('2. šŸ“ Files: Create .md files with YAML frontmatter'));
346
+ console.log(chalk.gray('3. šŸŽÆ Process: Use this interactive CLI to convert documents'));
347
+ console.log(chalk.gray('4. šŸ“„ Output: Get HTML, PDF, or processed Markdown\n'));
348
+ console.log(chalk.bold('Useful Commands:'));
349
+ console.log(chalk.gray('• ') + chalk.cyan('legal-md-ui') + chalk.gray(' - Interactive processing'));
350
+ console.log(chalk.gray('• ') + chalk.cyan('legal-md input.md') + chalk.gray(' - Direct processing'));
351
+ console.log(chalk.gray('• ') + chalk.cyan('legal-md --help') + chalk.gray(' - Command line help\n'));
352
+ await input({
353
+ message: 'Press Enter to continue...',
354
+ });
355
+ }
356
+ //# sourceMappingURL=ftux-handler.js.map