webpipe-js 0.1.8 → 0.1.10

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/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ __export(index_exports, {
30
30
  parseProgram: () => parseProgram,
31
31
  parseProgramWithDiagnostics: () => parseProgramWithDiagnostics,
32
32
  prettyPrint: () => prettyPrint,
33
+ printComment: () => printComment,
33
34
  printCondition: () => printCondition,
34
35
  printConfig: () => printConfig,
35
36
  printDescribe: () => printDescribe,
@@ -73,39 +74,103 @@ var Parser = class {
73
74
  while (i < this.text.length && this.text[i] !== "\n") i++;
74
75
  return i;
75
76
  }
77
+ getLineNumber(pos) {
78
+ return this.text.slice(0, pos).split("\n").length;
79
+ }
80
+ parseInlineComment() {
81
+ this.skipInlineSpaces();
82
+ const start = this.pos;
83
+ if (this.text.startsWith("#", this.pos)) {
84
+ this.pos++;
85
+ const text = this.consumeWhile((ch) => ch !== "\n");
86
+ return {
87
+ type: "inline",
88
+ text: text.trim(),
89
+ style: "#",
90
+ lineNumber: this.getLineNumber(start)
91
+ };
92
+ }
93
+ if (this.text.startsWith("//", this.pos)) {
94
+ this.pos += 2;
95
+ const text = this.consumeWhile((ch) => ch !== "\n");
96
+ return {
97
+ type: "inline",
98
+ text: text.trim(),
99
+ style: "//",
100
+ lineNumber: this.getLineNumber(start)
101
+ };
102
+ }
103
+ return null;
104
+ }
105
+ parseStandaloneComment() {
106
+ const start = this.pos;
107
+ if (this.text.startsWith("#", this.pos)) {
108
+ this.pos++;
109
+ const text = this.consumeWhile((ch) => ch !== "\n");
110
+ return {
111
+ type: "standalone",
112
+ text: text.trim(),
113
+ style: "#",
114
+ lineNumber: this.getLineNumber(start)
115
+ };
116
+ }
117
+ if (this.text.startsWith("//", this.pos)) {
118
+ this.pos += 2;
119
+ const text = this.consumeWhile((ch) => ch !== "\n");
120
+ return {
121
+ type: "standalone",
122
+ text: text.trim(),
123
+ style: "//",
124
+ lineNumber: this.getLineNumber(start)
125
+ };
126
+ }
127
+ return null;
128
+ }
76
129
  parseProgram() {
77
- this.skipSpaces();
130
+ this.skipWhitespaceOnly();
78
131
  const configs = [];
79
132
  const pipelines = [];
80
133
  const variables = [];
81
134
  const routes = [];
82
135
  const describes = [];
136
+ const comments = [];
83
137
  while (!this.eof()) {
84
- this.skipSpaces();
138
+ this.skipWhitespaceOnly();
85
139
  if (this.eof()) break;
86
140
  const start = this.pos;
141
+ const comment = this.tryParse(() => this.parseStandaloneComment());
142
+ if (comment) {
143
+ comments.push(comment);
144
+ if (this.cur() === "\n") this.pos++;
145
+ continue;
146
+ }
87
147
  const cfg = this.tryParse(() => this.parseConfig());
88
148
  if (cfg) {
149
+ cfg.lineNumber = this.getLineNumber(start);
89
150
  configs.push(cfg);
90
151
  continue;
91
152
  }
92
153
  const namedPipe = this.tryParse(() => this.parseNamedPipeline());
93
154
  if (namedPipe) {
155
+ namedPipe.lineNumber = this.getLineNumber(start);
94
156
  pipelines.push(namedPipe);
95
157
  continue;
96
158
  }
97
159
  const variable = this.tryParse(() => this.parseVariable());
98
160
  if (variable) {
161
+ variable.lineNumber = this.getLineNumber(start);
99
162
  variables.push(variable);
100
163
  continue;
101
164
  }
102
165
  const route = this.tryParse(() => this.parseRoute());
103
166
  if (route) {
167
+ route.lineNumber = this.getLineNumber(start);
104
168
  routes.push(route);
105
169
  continue;
106
170
  }
107
171
  const describe = this.tryParse(() => this.parseDescribe());
108
172
  if (describe) {
173
+ describe.lineNumber = this.getLineNumber(start);
109
174
  describes.push(describe);
110
175
  continue;
111
176
  }
@@ -124,7 +189,7 @@ var Parser = class {
124
189
  const start = Math.max(0, idx);
125
190
  this.report("Unclosed backtick-delimited string", start, start + 1, "warning");
126
191
  }
127
- return { configs, pipelines, variables, routes, describes };
192
+ return { configs, pipelines, variables, routes, describes, comments };
128
193
  }
129
194
  eof() {
130
195
  return this.pos >= this.len;
@@ -164,6 +229,9 @@ var Parser = class {
164
229
  break;
165
230
  }
166
231
  }
232
+ skipWhitespaceOnly() {
233
+ this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r" || ch === "\n");
234
+ }
167
235
  skipInlineSpaces() {
168
236
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r");
169
237
  }
@@ -291,6 +359,7 @@ var Parser = class {
291
359
  const name = this.parseIdentifier();
292
360
  this.skipInlineSpaces();
293
361
  this.expect("{");
362
+ const inlineComment = this.parseInlineComment();
294
363
  this.skipSpaces();
295
364
  const properties = [];
296
365
  while (true) {
@@ -301,8 +370,8 @@ var Parser = class {
301
370
  }
302
371
  this.skipSpaces();
303
372
  this.expect("}");
304
- this.skipSpaces();
305
- return { name, properties };
373
+ this.skipWhitespaceOnly();
374
+ return { name, properties, inlineComment: inlineComment || void 0 };
306
375
  }
307
376
  parsePipelineStep() {
308
377
  const result = this.tryParse(() => this.parseResultStep());
@@ -310,22 +379,22 @@ var Parser = class {
310
379
  return this.parseRegularStep();
311
380
  }
312
381
  parseRegularStep() {
313
- this.skipSpaces();
382
+ this.skipWhitespaceOnly();
314
383
  this.expect("|>");
315
384
  this.skipInlineSpaces();
316
385
  const name = this.parseIdentifier();
317
386
  this.expect(":");
318
387
  this.skipInlineSpaces();
319
388
  const { config, configType } = this.parseStepConfig();
320
- this.skipSpaces();
389
+ this.skipWhitespaceOnly();
321
390
  return { kind: "Regular", name, config, configType };
322
391
  }
323
392
  parseResultStep() {
324
- this.skipSpaces();
393
+ this.skipWhitespaceOnly();
325
394
  this.expect("|>");
326
395
  this.skipInlineSpaces();
327
396
  this.expect("result");
328
- this.skipSpaces();
397
+ this.skipWhitespaceOnly();
329
398
  const branches = [];
330
399
  while (true) {
331
400
  const br = this.tryParse(() => this.parseResultBranch());
@@ -361,7 +430,7 @@ var Parser = class {
361
430
  const steps = [];
362
431
  while (true) {
363
432
  const save = this.pos;
364
- this.skipSpaces();
433
+ this.skipWhitespaceOnly();
365
434
  if (!this.text.startsWith("|>", this.pos)) {
366
435
  this.pos = save;
367
436
  break;
@@ -378,19 +447,20 @@ var Parser = class {
378
447
  const name = this.parseIdentifier();
379
448
  this.skipInlineSpaces();
380
449
  this.expect("=");
450
+ const inlineComment = this.parseInlineComment();
381
451
  this.skipInlineSpaces();
382
452
  const beforePipeline = this.pos;
383
453
  const pipeline = this.parsePipeline();
384
454
  const end = this.pos;
385
455
  this.pipelineRanges.set(name, { start, end });
386
- this.skipSpaces();
387
- return { name, pipeline };
456
+ this.skipWhitespaceOnly();
457
+ return { name, pipeline, inlineComment: inlineComment || void 0 };
388
458
  }
389
459
  parsePipelineRef() {
390
460
  const inline = this.tryParse(() => this.parsePipeline());
391
461
  if (inline && inline.steps.length > 0) return { kind: "Inline", pipeline: inline };
392
462
  const named = this.tryParse(() => {
393
- this.skipSpaces();
463
+ this.skipWhitespaceOnly();
394
464
  this.expect("|>");
395
465
  this.skipInlineSpaces();
396
466
  this.expect("pipeline:");
@@ -410,19 +480,21 @@ var Parser = class {
410
480
  this.expect("=");
411
481
  this.skipInlineSpaces();
412
482
  const value = this.parseBacktickString();
483
+ const inlineComment = this.parseInlineComment();
413
484
  const end = this.pos;
414
485
  this.variableRanges.set(`${varType}::${name}`, { start, end });
415
- this.skipSpaces();
416
- return { varType, name, value };
486
+ this.skipWhitespaceOnly();
487
+ return { varType, name, value, inlineComment: inlineComment || void 0 };
417
488
  }
418
489
  parseRoute() {
419
490
  const method = this.parseMethod();
420
491
  this.skipInlineSpaces();
421
- const path = this.consumeWhile((c) => c !== " " && c !== "\n");
492
+ const path = this.consumeWhile((c) => c !== " " && c !== "\n" && c !== "#");
493
+ const inlineComment = this.parseInlineComment();
422
494
  this.skipSpaces();
423
495
  const pipeline = this.parsePipelineRef();
424
- this.skipSpaces();
425
- return { method, path, pipeline };
496
+ this.skipWhitespaceOnly();
497
+ return { method, path, pipeline, inlineComment: inlineComment || void 0 };
426
498
  }
427
499
  parseWhen() {
428
500
  const calling = this.tryParse(() => {
@@ -548,6 +620,7 @@ var Parser = class {
548
620
  this.expect('"');
549
621
  const name = this.consumeWhile((c) => c !== '"');
550
622
  this.expect('"');
623
+ const inlineComment = this.parseInlineComment();
551
624
  this.skipSpaces();
552
625
  const mocks = [];
553
626
  while (true) {
@@ -562,7 +635,7 @@ var Parser = class {
562
635
  if (!it) break;
563
636
  tests.push(it);
564
637
  }
565
- return { name, mocks, tests };
638
+ return { name, mocks, tests, inlineComment: inlineComment || void 0 };
566
639
  }
567
640
  };
568
641
  function parseProgram(text) {
@@ -592,14 +665,24 @@ var ParseFailure = class extends Error {
592
665
  };
593
666
  function printRoute(route) {
594
667
  const lines = [];
595
- lines.push(`${route.method} ${route.path}`);
668
+ const routeLine = `${route.method} ${route.path}`;
669
+ if (route.inlineComment) {
670
+ lines.push(`${routeLine} ${printComment(route.inlineComment)}`);
671
+ } else {
672
+ lines.push(routeLine);
673
+ }
596
674
  const pipelineLines = formatPipelineRef(route.pipeline);
597
675
  pipelineLines.forEach((line) => lines.push(line));
598
676
  return lines.join("\n");
599
677
  }
600
678
  function printConfig(config) {
601
679
  const lines = [];
602
- lines.push(`config ${config.name} {`);
680
+ const configLine = `config ${config.name} {`;
681
+ if (config.inlineComment) {
682
+ lines.push(`${configLine} ${printComment(config.inlineComment)}`);
683
+ } else {
684
+ lines.push(configLine);
685
+ }
603
686
  config.properties.forEach((prop) => {
604
687
  const value = formatConfigValue(prop.value);
605
688
  lines.push(` ${prop.key}: ${value}`);
@@ -609,14 +692,23 @@ function printConfig(config) {
609
692
  }
610
693
  function printPipeline(pipeline) {
611
694
  const lines = [];
612
- lines.push(`pipeline ${pipeline.name} =`);
695
+ const pipelineLine = `pipeline ${pipeline.name} =`;
696
+ if (pipeline.inlineComment) {
697
+ lines.push(`${pipelineLine} ${printComment(pipeline.inlineComment)}`);
698
+ } else {
699
+ lines.push(pipelineLine);
700
+ }
613
701
  pipeline.pipeline.steps.forEach((step) => {
614
702
  lines.push(formatPipelineStep(step));
615
703
  });
616
704
  return lines.join("\n");
617
705
  }
618
706
  function printVariable(variable) {
619
- return `${variable.varType} ${variable.name} = \`${variable.value}\``;
707
+ const variableLine = `${variable.varType} ${variable.name} = \`${variable.value}\``;
708
+ if (variable.inlineComment) {
709
+ return `${variableLine} ${printComment(variable.inlineComment)}`;
710
+ }
711
+ return variableLine;
620
712
  }
621
713
  function printMock(mock, indent = " ") {
622
714
  return `${indent}with mock ${mock.target} returning \`${mock.returnValue}\``;
@@ -642,9 +734,17 @@ function printTest(test) {
642
734
  });
643
735
  return lines.join("\n");
644
736
  }
737
+ function printComment(comment) {
738
+ return `${comment.style} ${comment.text}`;
739
+ }
645
740
  function printDescribe(describe) {
646
741
  const lines = [];
647
- lines.push(`describe "${describe.name}"`);
742
+ const describeLine = `describe "${describe.name}"`;
743
+ if (describe.inlineComment) {
744
+ lines.push(`${describeLine} ${printComment(describe.inlineComment)}`);
745
+ } else {
746
+ lines.push(describeLine);
747
+ }
648
748
  describe.mocks.forEach((mock) => {
649
749
  lines.push(printMock(mock));
650
750
  });
@@ -659,28 +759,58 @@ function printDescribe(describe) {
659
759
  }
660
760
  function prettyPrint(program) {
661
761
  const lines = [];
662
- if (program.configs.length > 0) {
663
- lines.push("## Config");
664
- program.configs.forEach((config) => {
665
- lines.push(printConfig(config));
666
- lines.push("");
667
- });
668
- }
762
+ const allItems = [];
763
+ program.configs.forEach((config) => {
764
+ allItems.push({ type: "config", item: config, lineNumber: config.lineNumber || 0 });
765
+ });
669
766
  program.routes.forEach((route) => {
670
- lines.push(printRoute(route));
671
- lines.push("");
767
+ allItems.push({ type: "route", item: route, lineNumber: route.lineNumber || 0 });
672
768
  });
673
769
  program.pipelines.forEach((pipeline) => {
674
- lines.push(printPipeline(pipeline));
675
- lines.push("");
770
+ allItems.push({ type: "pipeline", item: pipeline, lineNumber: pipeline.lineNumber || 0 });
676
771
  });
677
772
  program.variables.forEach((variable) => {
678
- lines.push(printVariable(variable));
773
+ allItems.push({ type: "variable", item: variable, lineNumber: variable.lineNumber || 0 });
679
774
  });
680
- if (program.variables.length > 0) lines.push("");
681
775
  program.describes.forEach((describe) => {
682
- lines.push(printDescribe(describe));
683
- lines.push("");
776
+ allItems.push({ type: "describe", item: describe, lineNumber: describe.lineNumber || 0 });
777
+ });
778
+ program.comments.forEach((comment) => {
779
+ allItems.push({ type: "comment", item: comment, lineNumber: comment.lineNumber || 0 });
780
+ });
781
+ allItems.sort((a, b) => a.lineNumber - b.lineNumber);
782
+ let hasConfigs = false;
783
+ allItems.forEach((entry, index) => {
784
+ if (entry.type === "config" && !hasConfigs) {
785
+ lines.push("## Config");
786
+ hasConfigs = true;
787
+ }
788
+ switch (entry.type) {
789
+ case "comment":
790
+ lines.push(printComment(entry.item));
791
+ break;
792
+ case "config":
793
+ lines.push(printConfig(entry.item));
794
+ lines.push("");
795
+ break;
796
+ case "route":
797
+ lines.push(printRoute(entry.item));
798
+ lines.push("");
799
+ break;
800
+ case "pipeline":
801
+ lines.push(printPipeline(entry.item));
802
+ lines.push("");
803
+ break;
804
+ case "variable":
805
+ lines.push(printVariable(entry.item));
806
+ const nextNonVariable = allItems.slice(index + 1).find((item) => item.type !== "variable");
807
+ if (nextNonVariable) lines.push("");
808
+ break;
809
+ case "describe":
810
+ lines.push(printDescribe(entry.item));
811
+ lines.push("");
812
+ break;
813
+ }
684
814
  });
685
815
  return lines.join("\n").trim();
686
816
  }
@@ -754,6 +884,7 @@ function formatWhen(when) {
754
884
  parseProgram,
755
885
  parseProgramWithDiagnostics,
756
886
  prettyPrint,
887
+ printComment,
757
888
  printCondition,
758
889
  printConfig,
759
890
  printDescribe,
package/dist/index.d.cts CHANGED
@@ -4,10 +4,19 @@ interface Program {
4
4
  variables: Variable[];
5
5
  routes: Route[];
6
6
  describes: Describe[];
7
+ comments: Comment[];
8
+ }
9
+ interface Comment {
10
+ type: 'standalone' | 'inline';
11
+ text: string;
12
+ style: '#' | '//';
13
+ lineNumber?: number;
7
14
  }
8
15
  interface Config {
9
16
  name: string;
10
17
  properties: ConfigProperty[];
18
+ lineNumber?: number;
19
+ inlineComment?: Comment;
11
20
  }
12
21
  interface ConfigProperty {
13
22
  key: string;
@@ -30,16 +39,22 @@ type ConfigValue = {
30
39
  interface NamedPipeline {
31
40
  name: string;
32
41
  pipeline: Pipeline;
42
+ lineNumber?: number;
43
+ inlineComment?: Comment;
33
44
  }
34
45
  interface Variable {
35
46
  varType: string;
36
47
  name: string;
37
48
  value: string;
49
+ lineNumber?: number;
50
+ inlineComment?: Comment;
38
51
  }
39
52
  interface Route {
40
53
  method: string;
41
54
  path: string;
42
55
  pipeline: PipelineRef;
56
+ lineNumber?: number;
57
+ inlineComment?: Comment;
43
58
  }
44
59
  type PipelineRef = {
45
60
  kind: 'Inline';
@@ -78,6 +93,8 @@ interface Describe {
78
93
  name: string;
79
94
  mocks: Mock[];
80
95
  tests: It[];
96
+ lineNumber?: number;
97
+ inlineComment?: Comment;
81
98
  }
82
99
  interface Mock {
83
100
  target: string;
@@ -136,6 +153,7 @@ declare function printVariable(variable: Variable): string;
136
153
  declare function printMock(mock: Mock, indent?: string): string;
137
154
  declare function printCondition(condition: Condition, indent?: string): string;
138
155
  declare function printTest(test: It): string;
156
+ declare function printComment(comment: Comment): string;
139
157
  declare function printDescribe(describe: Describe): string;
140
158
  declare function prettyPrint(program: Program): string;
141
159
  declare function formatConfigValue(value: ConfigValue): string;
@@ -144,4 +162,4 @@ declare function formatStepConfig(config: string, configType: ConfigType): strin
144
162
  declare function formatPipelineRef(ref: PipelineRef): string[];
145
163
  declare function formatWhen(when: When): string;
146
164
 
147
- export { type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type It, type Mock, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type ResultBranch, type ResultBranchType, type Route, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printCondition, printConfig, printDescribe, printMock, printPipeline, printRoute, printTest, printVariable };
165
+ export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type It, type Mock, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type ResultBranch, type ResultBranchType, type Route, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printMock, printPipeline, printRoute, printTest, printVariable };
package/dist/index.d.ts CHANGED
@@ -4,10 +4,19 @@ interface Program {
4
4
  variables: Variable[];
5
5
  routes: Route[];
6
6
  describes: Describe[];
7
+ comments: Comment[];
8
+ }
9
+ interface Comment {
10
+ type: 'standalone' | 'inline';
11
+ text: string;
12
+ style: '#' | '//';
13
+ lineNumber?: number;
7
14
  }
8
15
  interface Config {
9
16
  name: string;
10
17
  properties: ConfigProperty[];
18
+ lineNumber?: number;
19
+ inlineComment?: Comment;
11
20
  }
12
21
  interface ConfigProperty {
13
22
  key: string;
@@ -30,16 +39,22 @@ type ConfigValue = {
30
39
  interface NamedPipeline {
31
40
  name: string;
32
41
  pipeline: Pipeline;
42
+ lineNumber?: number;
43
+ inlineComment?: Comment;
33
44
  }
34
45
  interface Variable {
35
46
  varType: string;
36
47
  name: string;
37
48
  value: string;
49
+ lineNumber?: number;
50
+ inlineComment?: Comment;
38
51
  }
39
52
  interface Route {
40
53
  method: string;
41
54
  path: string;
42
55
  pipeline: PipelineRef;
56
+ lineNumber?: number;
57
+ inlineComment?: Comment;
43
58
  }
44
59
  type PipelineRef = {
45
60
  kind: 'Inline';
@@ -78,6 +93,8 @@ interface Describe {
78
93
  name: string;
79
94
  mocks: Mock[];
80
95
  tests: It[];
96
+ lineNumber?: number;
97
+ inlineComment?: Comment;
81
98
  }
82
99
  interface Mock {
83
100
  target: string;
@@ -136,6 +153,7 @@ declare function printVariable(variable: Variable): string;
136
153
  declare function printMock(mock: Mock, indent?: string): string;
137
154
  declare function printCondition(condition: Condition, indent?: string): string;
138
155
  declare function printTest(test: It): string;
156
+ declare function printComment(comment: Comment): string;
139
157
  declare function printDescribe(describe: Describe): string;
140
158
  declare function prettyPrint(program: Program): string;
141
159
  declare function formatConfigValue(value: ConfigValue): string;
@@ -144,4 +162,4 @@ declare function formatStepConfig(config: string, configType: ConfigType): strin
144
162
  declare function formatPipelineRef(ref: PipelineRef): string[];
145
163
  declare function formatWhen(when: When): string;
146
164
 
147
- export { type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type It, type Mock, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type ResultBranch, type ResultBranchType, type Route, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printCondition, printConfig, printDescribe, printMock, printPipeline, printRoute, printTest, printVariable };
165
+ export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type It, type Mock, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type ResultBranch, type ResultBranchType, type Route, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printMock, printPipeline, printRoute, printTest, printVariable };
package/dist/index.mjs CHANGED
@@ -30,39 +30,103 @@ var Parser = class {
30
30
  while (i < this.text.length && this.text[i] !== "\n") i++;
31
31
  return i;
32
32
  }
33
+ getLineNumber(pos) {
34
+ return this.text.slice(0, pos).split("\n").length;
35
+ }
36
+ parseInlineComment() {
37
+ this.skipInlineSpaces();
38
+ const start = this.pos;
39
+ if (this.text.startsWith("#", this.pos)) {
40
+ this.pos++;
41
+ const text = this.consumeWhile((ch) => ch !== "\n");
42
+ return {
43
+ type: "inline",
44
+ text: text.trim(),
45
+ style: "#",
46
+ lineNumber: this.getLineNumber(start)
47
+ };
48
+ }
49
+ if (this.text.startsWith("//", this.pos)) {
50
+ this.pos += 2;
51
+ const text = this.consumeWhile((ch) => ch !== "\n");
52
+ return {
53
+ type: "inline",
54
+ text: text.trim(),
55
+ style: "//",
56
+ lineNumber: this.getLineNumber(start)
57
+ };
58
+ }
59
+ return null;
60
+ }
61
+ parseStandaloneComment() {
62
+ const start = this.pos;
63
+ if (this.text.startsWith("#", this.pos)) {
64
+ this.pos++;
65
+ const text = this.consumeWhile((ch) => ch !== "\n");
66
+ return {
67
+ type: "standalone",
68
+ text: text.trim(),
69
+ style: "#",
70
+ lineNumber: this.getLineNumber(start)
71
+ };
72
+ }
73
+ if (this.text.startsWith("//", this.pos)) {
74
+ this.pos += 2;
75
+ const text = this.consumeWhile((ch) => ch !== "\n");
76
+ return {
77
+ type: "standalone",
78
+ text: text.trim(),
79
+ style: "//",
80
+ lineNumber: this.getLineNumber(start)
81
+ };
82
+ }
83
+ return null;
84
+ }
33
85
  parseProgram() {
34
- this.skipSpaces();
86
+ this.skipWhitespaceOnly();
35
87
  const configs = [];
36
88
  const pipelines = [];
37
89
  const variables = [];
38
90
  const routes = [];
39
91
  const describes = [];
92
+ const comments = [];
40
93
  while (!this.eof()) {
41
- this.skipSpaces();
94
+ this.skipWhitespaceOnly();
42
95
  if (this.eof()) break;
43
96
  const start = this.pos;
97
+ const comment = this.tryParse(() => this.parseStandaloneComment());
98
+ if (comment) {
99
+ comments.push(comment);
100
+ if (this.cur() === "\n") this.pos++;
101
+ continue;
102
+ }
44
103
  const cfg = this.tryParse(() => this.parseConfig());
45
104
  if (cfg) {
105
+ cfg.lineNumber = this.getLineNumber(start);
46
106
  configs.push(cfg);
47
107
  continue;
48
108
  }
49
109
  const namedPipe = this.tryParse(() => this.parseNamedPipeline());
50
110
  if (namedPipe) {
111
+ namedPipe.lineNumber = this.getLineNumber(start);
51
112
  pipelines.push(namedPipe);
52
113
  continue;
53
114
  }
54
115
  const variable = this.tryParse(() => this.parseVariable());
55
116
  if (variable) {
117
+ variable.lineNumber = this.getLineNumber(start);
56
118
  variables.push(variable);
57
119
  continue;
58
120
  }
59
121
  const route = this.tryParse(() => this.parseRoute());
60
122
  if (route) {
123
+ route.lineNumber = this.getLineNumber(start);
61
124
  routes.push(route);
62
125
  continue;
63
126
  }
64
127
  const describe = this.tryParse(() => this.parseDescribe());
65
128
  if (describe) {
129
+ describe.lineNumber = this.getLineNumber(start);
66
130
  describes.push(describe);
67
131
  continue;
68
132
  }
@@ -81,7 +145,7 @@ var Parser = class {
81
145
  const start = Math.max(0, idx);
82
146
  this.report("Unclosed backtick-delimited string", start, start + 1, "warning");
83
147
  }
84
- return { configs, pipelines, variables, routes, describes };
148
+ return { configs, pipelines, variables, routes, describes, comments };
85
149
  }
86
150
  eof() {
87
151
  return this.pos >= this.len;
@@ -121,6 +185,9 @@ var Parser = class {
121
185
  break;
122
186
  }
123
187
  }
188
+ skipWhitespaceOnly() {
189
+ this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r" || ch === "\n");
190
+ }
124
191
  skipInlineSpaces() {
125
192
  this.consumeWhile((ch) => ch === " " || ch === " " || ch === "\r");
126
193
  }
@@ -248,6 +315,7 @@ var Parser = class {
248
315
  const name = this.parseIdentifier();
249
316
  this.skipInlineSpaces();
250
317
  this.expect("{");
318
+ const inlineComment = this.parseInlineComment();
251
319
  this.skipSpaces();
252
320
  const properties = [];
253
321
  while (true) {
@@ -258,8 +326,8 @@ var Parser = class {
258
326
  }
259
327
  this.skipSpaces();
260
328
  this.expect("}");
261
- this.skipSpaces();
262
- return { name, properties };
329
+ this.skipWhitespaceOnly();
330
+ return { name, properties, inlineComment: inlineComment || void 0 };
263
331
  }
264
332
  parsePipelineStep() {
265
333
  const result = this.tryParse(() => this.parseResultStep());
@@ -267,22 +335,22 @@ var Parser = class {
267
335
  return this.parseRegularStep();
268
336
  }
269
337
  parseRegularStep() {
270
- this.skipSpaces();
338
+ this.skipWhitespaceOnly();
271
339
  this.expect("|>");
272
340
  this.skipInlineSpaces();
273
341
  const name = this.parseIdentifier();
274
342
  this.expect(":");
275
343
  this.skipInlineSpaces();
276
344
  const { config, configType } = this.parseStepConfig();
277
- this.skipSpaces();
345
+ this.skipWhitespaceOnly();
278
346
  return { kind: "Regular", name, config, configType };
279
347
  }
280
348
  parseResultStep() {
281
- this.skipSpaces();
349
+ this.skipWhitespaceOnly();
282
350
  this.expect("|>");
283
351
  this.skipInlineSpaces();
284
352
  this.expect("result");
285
- this.skipSpaces();
353
+ this.skipWhitespaceOnly();
286
354
  const branches = [];
287
355
  while (true) {
288
356
  const br = this.tryParse(() => this.parseResultBranch());
@@ -318,7 +386,7 @@ var Parser = class {
318
386
  const steps = [];
319
387
  while (true) {
320
388
  const save = this.pos;
321
- this.skipSpaces();
389
+ this.skipWhitespaceOnly();
322
390
  if (!this.text.startsWith("|>", this.pos)) {
323
391
  this.pos = save;
324
392
  break;
@@ -335,19 +403,20 @@ var Parser = class {
335
403
  const name = this.parseIdentifier();
336
404
  this.skipInlineSpaces();
337
405
  this.expect("=");
406
+ const inlineComment = this.parseInlineComment();
338
407
  this.skipInlineSpaces();
339
408
  const beforePipeline = this.pos;
340
409
  const pipeline = this.parsePipeline();
341
410
  const end = this.pos;
342
411
  this.pipelineRanges.set(name, { start, end });
343
- this.skipSpaces();
344
- return { name, pipeline };
412
+ this.skipWhitespaceOnly();
413
+ return { name, pipeline, inlineComment: inlineComment || void 0 };
345
414
  }
346
415
  parsePipelineRef() {
347
416
  const inline = this.tryParse(() => this.parsePipeline());
348
417
  if (inline && inline.steps.length > 0) return { kind: "Inline", pipeline: inline };
349
418
  const named = this.tryParse(() => {
350
- this.skipSpaces();
419
+ this.skipWhitespaceOnly();
351
420
  this.expect("|>");
352
421
  this.skipInlineSpaces();
353
422
  this.expect("pipeline:");
@@ -367,19 +436,21 @@ var Parser = class {
367
436
  this.expect("=");
368
437
  this.skipInlineSpaces();
369
438
  const value = this.parseBacktickString();
439
+ const inlineComment = this.parseInlineComment();
370
440
  const end = this.pos;
371
441
  this.variableRanges.set(`${varType}::${name}`, { start, end });
372
- this.skipSpaces();
373
- return { varType, name, value };
442
+ this.skipWhitespaceOnly();
443
+ return { varType, name, value, inlineComment: inlineComment || void 0 };
374
444
  }
375
445
  parseRoute() {
376
446
  const method = this.parseMethod();
377
447
  this.skipInlineSpaces();
378
- const path = this.consumeWhile((c) => c !== " " && c !== "\n");
448
+ const path = this.consumeWhile((c) => c !== " " && c !== "\n" && c !== "#");
449
+ const inlineComment = this.parseInlineComment();
379
450
  this.skipSpaces();
380
451
  const pipeline = this.parsePipelineRef();
381
- this.skipSpaces();
382
- return { method, path, pipeline };
452
+ this.skipWhitespaceOnly();
453
+ return { method, path, pipeline, inlineComment: inlineComment || void 0 };
383
454
  }
384
455
  parseWhen() {
385
456
  const calling = this.tryParse(() => {
@@ -505,6 +576,7 @@ var Parser = class {
505
576
  this.expect('"');
506
577
  const name = this.consumeWhile((c) => c !== '"');
507
578
  this.expect('"');
579
+ const inlineComment = this.parseInlineComment();
508
580
  this.skipSpaces();
509
581
  const mocks = [];
510
582
  while (true) {
@@ -519,7 +591,7 @@ var Parser = class {
519
591
  if (!it) break;
520
592
  tests.push(it);
521
593
  }
522
- return { name, mocks, tests };
594
+ return { name, mocks, tests, inlineComment: inlineComment || void 0 };
523
595
  }
524
596
  };
525
597
  function parseProgram(text) {
@@ -549,14 +621,24 @@ var ParseFailure = class extends Error {
549
621
  };
550
622
  function printRoute(route) {
551
623
  const lines = [];
552
- lines.push(`${route.method} ${route.path}`);
624
+ const routeLine = `${route.method} ${route.path}`;
625
+ if (route.inlineComment) {
626
+ lines.push(`${routeLine} ${printComment(route.inlineComment)}`);
627
+ } else {
628
+ lines.push(routeLine);
629
+ }
553
630
  const pipelineLines = formatPipelineRef(route.pipeline);
554
631
  pipelineLines.forEach((line) => lines.push(line));
555
632
  return lines.join("\n");
556
633
  }
557
634
  function printConfig(config) {
558
635
  const lines = [];
559
- lines.push(`config ${config.name} {`);
636
+ const configLine = `config ${config.name} {`;
637
+ if (config.inlineComment) {
638
+ lines.push(`${configLine} ${printComment(config.inlineComment)}`);
639
+ } else {
640
+ lines.push(configLine);
641
+ }
560
642
  config.properties.forEach((prop) => {
561
643
  const value = formatConfigValue(prop.value);
562
644
  lines.push(` ${prop.key}: ${value}`);
@@ -566,14 +648,23 @@ function printConfig(config) {
566
648
  }
567
649
  function printPipeline(pipeline) {
568
650
  const lines = [];
569
- lines.push(`pipeline ${pipeline.name} =`);
651
+ const pipelineLine = `pipeline ${pipeline.name} =`;
652
+ if (pipeline.inlineComment) {
653
+ lines.push(`${pipelineLine} ${printComment(pipeline.inlineComment)}`);
654
+ } else {
655
+ lines.push(pipelineLine);
656
+ }
570
657
  pipeline.pipeline.steps.forEach((step) => {
571
658
  lines.push(formatPipelineStep(step));
572
659
  });
573
660
  return lines.join("\n");
574
661
  }
575
662
  function printVariable(variable) {
576
- return `${variable.varType} ${variable.name} = \`${variable.value}\``;
663
+ const variableLine = `${variable.varType} ${variable.name} = \`${variable.value}\``;
664
+ if (variable.inlineComment) {
665
+ return `${variableLine} ${printComment(variable.inlineComment)}`;
666
+ }
667
+ return variableLine;
577
668
  }
578
669
  function printMock(mock, indent = " ") {
579
670
  return `${indent}with mock ${mock.target} returning \`${mock.returnValue}\``;
@@ -599,9 +690,17 @@ function printTest(test) {
599
690
  });
600
691
  return lines.join("\n");
601
692
  }
693
+ function printComment(comment) {
694
+ return `${comment.style} ${comment.text}`;
695
+ }
602
696
  function printDescribe(describe) {
603
697
  const lines = [];
604
- lines.push(`describe "${describe.name}"`);
698
+ const describeLine = `describe "${describe.name}"`;
699
+ if (describe.inlineComment) {
700
+ lines.push(`${describeLine} ${printComment(describe.inlineComment)}`);
701
+ } else {
702
+ lines.push(describeLine);
703
+ }
605
704
  describe.mocks.forEach((mock) => {
606
705
  lines.push(printMock(mock));
607
706
  });
@@ -616,28 +715,58 @@ function printDescribe(describe) {
616
715
  }
617
716
  function prettyPrint(program) {
618
717
  const lines = [];
619
- if (program.configs.length > 0) {
620
- lines.push("## Config");
621
- program.configs.forEach((config) => {
622
- lines.push(printConfig(config));
623
- lines.push("");
624
- });
625
- }
718
+ const allItems = [];
719
+ program.configs.forEach((config) => {
720
+ allItems.push({ type: "config", item: config, lineNumber: config.lineNumber || 0 });
721
+ });
626
722
  program.routes.forEach((route) => {
627
- lines.push(printRoute(route));
628
- lines.push("");
723
+ allItems.push({ type: "route", item: route, lineNumber: route.lineNumber || 0 });
629
724
  });
630
725
  program.pipelines.forEach((pipeline) => {
631
- lines.push(printPipeline(pipeline));
632
- lines.push("");
726
+ allItems.push({ type: "pipeline", item: pipeline, lineNumber: pipeline.lineNumber || 0 });
633
727
  });
634
728
  program.variables.forEach((variable) => {
635
- lines.push(printVariable(variable));
729
+ allItems.push({ type: "variable", item: variable, lineNumber: variable.lineNumber || 0 });
636
730
  });
637
- if (program.variables.length > 0) lines.push("");
638
731
  program.describes.forEach((describe) => {
639
- lines.push(printDescribe(describe));
640
- lines.push("");
732
+ allItems.push({ type: "describe", item: describe, lineNumber: describe.lineNumber || 0 });
733
+ });
734
+ program.comments.forEach((comment) => {
735
+ allItems.push({ type: "comment", item: comment, lineNumber: comment.lineNumber || 0 });
736
+ });
737
+ allItems.sort((a, b) => a.lineNumber - b.lineNumber);
738
+ let hasConfigs = false;
739
+ allItems.forEach((entry, index) => {
740
+ if (entry.type === "config" && !hasConfigs) {
741
+ lines.push("## Config");
742
+ hasConfigs = true;
743
+ }
744
+ switch (entry.type) {
745
+ case "comment":
746
+ lines.push(printComment(entry.item));
747
+ break;
748
+ case "config":
749
+ lines.push(printConfig(entry.item));
750
+ lines.push("");
751
+ break;
752
+ case "route":
753
+ lines.push(printRoute(entry.item));
754
+ lines.push("");
755
+ break;
756
+ case "pipeline":
757
+ lines.push(printPipeline(entry.item));
758
+ lines.push("");
759
+ break;
760
+ case "variable":
761
+ lines.push(printVariable(entry.item));
762
+ const nextNonVariable = allItems.slice(index + 1).find((item) => item.type !== "variable");
763
+ if (nextNonVariable) lines.push("");
764
+ break;
765
+ case "describe":
766
+ lines.push(printDescribe(entry.item));
767
+ lines.push("");
768
+ break;
769
+ }
641
770
  });
642
771
  return lines.join("\n").trim();
643
772
  }
@@ -710,6 +839,7 @@ export {
710
839
  parseProgram,
711
840
  parseProgramWithDiagnostics,
712
841
  prettyPrint,
842
+ printComment,
713
843
  printCondition,
714
844
  printConfig,
715
845
  printDescribe,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpipe-js",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Web Pipe parser",
5
5
  "license": "ISC",
6
6
  "author": "William Cotton",