@jsenv/plugin-supervisor 1.3.9 → 1.4.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.
@@ -44,114 +44,109 @@ const getOriginalPosition = ({
44
44
  return originalPosition;
45
45
  };
46
46
 
47
- // consider switching to https://babeljs.io/docs/en/babel-code-frame
48
- // https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/css-syntax-error.js#L43
49
- // https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/terminal-highlight.js#L50
50
- // https://github.com/babel/babel/blob/eea156b2cb8deecfcf82d52aa1b71ba4995c7d68/packages/babel-code-frame/src/index.js#L1
51
-
52
- const stringifyUrlSite = ({
53
- url,
54
- line,
55
- column,
56
- content
57
- }, {
58
- showCodeFrame = true,
59
- numberOfSurroundingLinesToShow,
60
- lineMaxLength,
61
- color
62
- } = {}) => {
63
- let string = url;
64
- if (typeof line === "number") {
65
- string += ":".concat(line);
66
- if (typeof column === "number") {
67
- string += ":".concat(column);
68
- }
69
- }
70
- if (!showCodeFrame || typeof line !== "number" || !content) {
71
- return string;
72
- }
73
- const sourceLoc = showSourceLocation({
74
- content,
75
- line,
76
- column,
77
- numberOfSurroundingLinesToShow,
78
- lineMaxLength,
79
- color
80
- });
81
- return "".concat(string, "\n").concat(sourceLoc);
82
- };
83
- const showSourceLocation = ({
47
+ const formatDefault = v => v;
48
+ const inspectFileContent = ({
84
49
  content,
85
50
  line,
86
51
  column,
87
- numberOfSurroundingLinesToShow = 1,
88
- lineMaxLength = 120
52
+ linesAbove = 3,
53
+ linesBelow = 0,
54
+ lineMaxWidth = 120,
55
+ lineNumbersOnTheLeft = true,
56
+ lineMarker = true,
57
+ columnMarker = true,
58
+ format = formatDefault
89
59
  } = {}) => {
90
- let mark = string => string;
91
- let aside = string => string;
92
- // if (color) {
93
- // mark = (string) => ANSI.color(string, ANSI.RED)
94
- // aside = (string) => ANSI.color(string, ANSI.GREY)
95
- // }
96
-
97
- const lines = content.split(/\r?\n/);
60
+ const lineStrings = content.split(/\r?\n/);
98
61
  if (line === 0) line = 1;
99
- let lineRange = {
100
- start: line - 1,
101
- end: line
102
- };
103
- lineRange = moveLineRangeUp(lineRange, numberOfSurroundingLinesToShow);
104
- lineRange = moveLineRangeDown(lineRange, numberOfSurroundingLinesToShow);
105
- lineRange = lineRangeWithinLines(lineRange, lines);
106
- const linesToShow = lines.slice(lineRange.start, lineRange.end);
107
- const endLineNumber = lineRange.end;
108
- const lineNumberMaxWidth = String(endLineNumber).length;
109
- if (column === 0) column = 1;
110
- const columnRange = {};
111
62
  if (column === undefined) {
112
- columnRange.start = 0;
113
- columnRange.end = lineMaxLength;
114
- } else if (column > lineMaxLength) {
115
- columnRange.start = column - Math.floor(lineMaxLength / 2);
116
- columnRange.end = column + Math.ceil(lineMaxLength / 2);
63
+ columnMarker = false;
64
+ column = 1;
65
+ }
66
+ if (column === 0) column = 1;
67
+ let lineStartIndex = line - 1 - linesAbove;
68
+ if (lineStartIndex < 0) {
69
+ lineStartIndex = 0;
70
+ }
71
+ let lineEndIndex = line - 1 + linesBelow;
72
+ if (lineEndIndex > lineStrings.length - 1) {
73
+ lineEndIndex = lineStrings.length - 1;
74
+ }
75
+ if (columnMarker) {
76
+ // human reader deduce the line when there is a column marker
77
+ lineMarker = false;
78
+ }
79
+ if (line - 1 === lineEndIndex) {
80
+ lineMarker = false; // useless because last line
81
+ }
82
+ let lineIndex = lineStartIndex;
83
+ let columnsBefore;
84
+ let columnsAfter;
85
+ if (column > lineMaxWidth) {
86
+ columnsBefore = column - Math.ceil(lineMaxWidth / 2);
87
+ columnsAfter = column + Math.floor(lineMaxWidth / 2);
117
88
  } else {
118
- columnRange.start = 0;
119
- columnRange.end = lineMaxLength;
89
+ columnsBefore = 0;
90
+ columnsAfter = lineMaxWidth;
120
91
  }
121
- return linesToShow.map((lineSource, index) => {
122
- const lineNumber = lineRange.start + index + 1;
92
+ let columnMarkerIndex = column - 1 - columnsBefore;
93
+ let source = "";
94
+ while (lineIndex <= lineEndIndex) {
95
+ const lineString = lineStrings[lineIndex];
96
+ const lineNumber = lineIndex + 1;
97
+ const isLastLine = lineIndex === lineEndIndex;
123
98
  const isMainLine = lineNumber === line;
124
- const lineSourceTruncated = applyColumnRange(columnRange, lineSource);
125
- const lineNumberWidth = String(lineNumber).length;
126
- // ensure if line moves from 7,8,9 to 10 the display is still great
127
- const lineNumberRightSpacing = " ".repeat(lineNumberMaxWidth - lineNumberWidth);
128
- const asideSource = "".concat(lineNumber).concat(lineNumberRightSpacing, " |");
129
- const lineFormatted = "".concat(aside(asideSource), " ").concat(lineSourceTruncated);
130
- if (isMainLine) {
131
- if (column === undefined) {
132
- return "".concat(mark(">"), " ").concat(lineFormatted);
99
+ lineIndex++;
100
+ {
101
+ if (lineMarker) {
102
+ if (isMainLine) {
103
+ source += "".concat(format(">", "marker_line"), " ");
104
+ } else {
105
+ source += " ";
106
+ }
133
107
  }
134
- const spacing = stringToSpaces("".concat(asideSource, " ").concat(lineSourceTruncated.slice(0, column - columnRange.start - 1)));
135
- return "".concat(mark(">"), " ").concat(lineFormatted, "\n ").concat(spacing).concat(mark("^"));
108
+ if (lineNumbersOnTheLeft) {
109
+ // fill with spaces to ensure if line moves from 7,8,9 to 10 the display is still great
110
+ const asideSource = "".concat(fillLeft(lineNumber, lineEndIndex + 1), " |");
111
+ source += "".concat(format(asideSource, "line_number_aside"), " ");
112
+ }
113
+ }
114
+ {
115
+ source += truncateLine(lineString, {
116
+ start: columnsBefore,
117
+ end: columnsAfter,
118
+ prefix: "…",
119
+ suffix: "…",
120
+ format
121
+ });
122
+ }
123
+ {
124
+ if (columnMarker && isMainLine) {
125
+ source += "\n";
126
+ if (lineMarker) {
127
+ source += " ";
128
+ }
129
+ if (lineNumbersOnTheLeft) {
130
+ const asideSpaces = "".concat(fillLeft(lineNumber, lineEndIndex + 1), " | ").length;
131
+ source += " ".repeat(asideSpaces);
132
+ }
133
+ source += " ".repeat(columnMarkerIndex);
134
+ source += format("^", "marker_column");
135
+ }
136
+ }
137
+ if (!isLastLine) {
138
+ source += "\n";
136
139
  }
137
- return " ".concat(lineFormatted);
138
- }).join("\n");
140
+ }
141
+ return source;
139
142
  };
140
- const applyColumnRange = ({
143
+ const truncateLine = (line, {
141
144
  start,
142
- end
143
- }, line) => {
144
- if (typeof start !== "number") {
145
- throw new TypeError("start must be a number, received ".concat(start));
146
- }
147
- if (typeof end !== "number") {
148
- throw new TypeError("end must be a number, received ".concat(end));
149
- }
150
- if (end < start) {
151
- throw new Error("end must be greater than start, but ".concat(end, " is smaller than ").concat(start));
152
- }
153
- const prefix = "…";
154
- const suffix = "…";
145
+ end,
146
+ prefix,
147
+ suffix,
148
+ format
149
+ }) => {
155
150
  const lastIndex = line.length;
156
151
  if (line.length === 0) {
157
152
  // don't show any ellipsis if the line is empty
@@ -168,53 +163,33 @@ const applyColumnRange = ({
168
163
  }
169
164
  let result = "";
170
165
  while (from < to) {
171
- result += line[from];
166
+ result += format(line[from], "char");
172
167
  from++;
173
168
  }
174
169
  if (result.length === 0) {
175
170
  return "";
176
171
  }
177
172
  if (startTruncated && endTruncated) {
178
- return "".concat(prefix).concat(result).concat(suffix);
173
+ return "".concat(format(prefix, "marker_overflow_left")).concat(result).concat(format(suffix, "marker_overflow_right"));
179
174
  }
180
175
  if (startTruncated) {
181
- return "".concat(prefix).concat(result);
176
+ return "".concat(format(prefix, "marker_overflow_left")).concat(result);
182
177
  }
183
178
  if (endTruncated) {
184
- return "".concat(result).concat(suffix);
179
+ return "".concat(result).concat(format(suffix, "marker_overflow_right"));
185
180
  }
186
181
  return result;
187
182
  };
188
- const stringToSpaces = string => string.replace(/[^\t]/g, " ");
189
-
190
- // const getLineRangeLength = ({ start, end }) => end - start
191
-
192
- const moveLineRangeUp = ({
193
- start,
194
- end
195
- }, number) => {
196
- return {
197
- start: start - number,
198
- end
199
- };
200
- };
201
- const moveLineRangeDown = ({
202
- start,
203
- end
204
- }, number) => {
205
- return {
206
- start,
207
- end: end + number
208
- };
209
- };
210
- const lineRangeWithinLines = ({
211
- start,
212
- end
213
- }, lines) => {
214
- return {
215
- start: start < 0 ? 0 : start,
216
- end: end > lines.length ? lines.length : end
217
- };
183
+ const fillLeft = (value, biggestValue, char = " ") => {
184
+ const width = String(value).length;
185
+ const biggestWidth = String(biggestValue).length;
186
+ let missingWidth = biggestWidth - width;
187
+ let padded = "";
188
+ while (missingWidth--) {
189
+ padded += char;
190
+ }
191
+ padded += value;
192
+ return padded;
218
193
  };
219
194
 
220
195
  const getCommonPathname = (pathname, otherPathname) => {
@@ -465,11 +440,11 @@ const replaceSourceMappingUrl = (source, regexp, callback) => {
465
440
  */
466
441
 
467
442
  const injectSupervisorIntoJs = async ({
468
- webServer,
469
443
  content,
470
444
  url,
471
445
  type,
472
- inlineSrc
446
+ inlineSrc,
447
+ sourcemaps
473
448
  }) => {
474
449
  const babelPluginJsSupervisor = type === "js_module" ? babelPluginJsModuleSupervisor : babelPluginJsClassicSupervisor;
475
450
  const result = await applyBabelPlugins({
@@ -481,14 +456,16 @@ const injectSupervisorIntoJs = async ({
481
456
  inputUrl: url
482
457
  });
483
458
  let code = result.code;
484
- let map = result.map;
485
- const sourcemapDataUrl = generateSourcemapDataUrl(map);
486
- code = SOURCEMAP.writeComment({
487
- contentType: "text/javascript",
488
- content: code,
489
- specifier: sourcemapDataUrl
490
- });
491
- code = "".concat(code, "\n//# sourceURL=").concat(urlToRelativeUrl(url, webServer.rootDirectoryUrl));
459
+ if (sourcemaps === "inline") {
460
+ const map = result.map;
461
+ const sourcemapDataUrl = generateSourcemapDataUrl(map);
462
+ code = SOURCEMAP.writeComment({
463
+ contentType: "text/javascript",
464
+ content: code,
465
+ specifier: sourcemapDataUrl
466
+ });
467
+ }
468
+ code = "".concat(code, "\n//# sourceURL=").concat(inlineSrc);
492
469
  return code;
493
470
  };
494
471
  const babelPluginJsModuleSupervisor = babel => {
@@ -594,7 +571,6 @@ const convertStaticImportIntoDynamicImport = (staticImportNode, t) => {
594
571
  true // shorthand
595
572
  );
596
573
  }));
597
-
598
574
  const variableDeclarator = t.variableDeclarator(objectPattern, awaitExpression);
599
575
  const variableDeclaration = t.variableDeclaration("const", [variableDeclarator]);
600
576
  return variableDeclaration;
@@ -702,7 +678,8 @@ const injectSupervisorIntoHTML = async ({
702
678
  generateInlineScriptSrc = ({
703
679
  inlineScriptUrl
704
680
  }) => urlToRelativeUrl(inlineScriptUrl, webServer.rootDirectoryUrl),
705
- inlineAsRemote
681
+ inlineAsRemote,
682
+ sourcemaps = "inline"
706
683
  }) => {
707
684
  const htmlAst = parseHtml({
708
685
  html: content,
@@ -777,7 +754,8 @@ const injectSupervisorIntoHTML = async ({
777
754
  content: textContent,
778
755
  url: inlineScriptUrl,
779
756
  type,
780
- inlineSrc: inlineScriptSrc
757
+ inlineSrc: inlineScriptSrc,
758
+ sourcemaps
781
759
  });
782
760
  mutations.push(() => {
783
761
  setHtmlNodeText(scriptNode, inlineJsSupervised, {
@@ -873,7 +851,7 @@ const injectSupervisorIntoHTML = async ({
873
851
  }, " ");
874
852
  injectHtmlNodeAsEarlyAsPossible(htmlAst, createHtmlNode({
875
853
  tagName: "script",
876
- textContent: "window.__supervisor__.setup({".concat(setupParamsSource, "})")
854
+ textContent: "window.__supervisor__.setup({\n ".concat(setupParamsSource, "\n});")
877
855
  }), "jsenv:supervisor");
878
856
  injectHtmlNodeAsEarlyAsPossible(htmlAst, createHtmlNode({
879
857
  tagName: "script",
@@ -929,12 +907,12 @@ const jsenvPluginSupervisor = ({
929
907
  name: "jsenv:supervisor",
930
908
  appliesDuring: "dev",
931
909
  serve: async serveInfo => {
932
- if (serveInfo.request.pathname.startsWith("/__get_code_frame__/")) {
910
+ if (serveInfo.request.pathname.startsWith("/__get_cause_trace__/")) {
933
911
  const {
934
912
  pathname,
935
913
  searchParams
936
914
  } = new URL(serveInfo.request.url);
937
- let urlWithLineAndColumn = pathname.slice("/__get_code_frame__/".length);
915
+ let urlWithLineAndColumn = pathname.slice("/__get_cause_trace__/".length);
938
916
  urlWithLineAndColumn = decodeURIComponent(urlWithLineAndColumn);
939
917
  const match = urlWithLineAndColumn.match(/:([0-9]+):([0-9]+)$/);
940
918
  if (!match) {
@@ -973,20 +951,25 @@ const jsenvPluginSupervisor = ({
973
951
  }
974
952
  }
975
953
  }
976
- const codeFrame = stringifyUrlSite({
954
+ const causeTrace = {
977
955
  url: file,
978
956
  line,
979
957
  column,
980
- content: urlInfo.originalContent
981
- });
958
+ codeFrame: inspectFileContent({
959
+ line,
960
+ column,
961
+ content: urlInfo.originalContent
962
+ })
963
+ };
964
+ const causeTraceJson = JSON.stringify(causeTrace, null, " ");
982
965
  return {
983
966
  status: 200,
984
967
  headers: {
985
968
  "cache-control": "no-store",
986
- "content-type": "text/plain",
987
- "content-length": Buffer.byteLength(codeFrame)
969
+ "content-type": "application/json",
970
+ "content-length": Buffer.byteLength(causeTraceJson)
988
971
  },
989
- body: codeFrame
972
+ body: causeTraceJson
990
973
  };
991
974
  }
992
975
  if (serveInfo.request.pathname.startsWith("/__get_error_cause__/")) {
@@ -1025,7 +1008,7 @@ const jsenvPluginSupervisor = ({
1025
1008
  message: causeInfo.message,
1026
1009
  reason: causeInfo.reason,
1027
1010
  stack: errorBaseUrl ? "stack mocked for snapshot" : causeInfo.stack,
1028
- codeFrame: causeInfo.traceMessage
1011
+ trace: causeInfo.trace
1029
1012
  } : null, null, " ");
1030
1013
  return {
1031
1014
  status: 200,
@@ -1106,7 +1089,8 @@ const jsenvPluginSupervisor = ({
1106
1089
  content: textContent
1107
1090
  });
1108
1091
  return inlineScriptReference.generatedSpecifier;
1109
- }
1092
+ },
1093
+ sourcemaps: htmlUrlInfo.kitchen.context.sourcemaps
1110
1094
  });
1111
1095
  }
1112
1096
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/plugin-supervisor",
3
- "version": "1.3.9",
3
+ "version": "1.4.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,9 +26,9 @@
26
26
  "/dist/"
27
27
  ],
28
28
  "dependencies": {
29
- "@jsenv/ast": "6.0.1",
30
- "@jsenv/urls": "2.2.1",
31
- "@jsenv/sourcemap": "1.2.4",
29
+ "@jsenv/ast": "6.0.2",
30
+ "@jsenv/urls": "2.2.2",
31
+ "@jsenv/sourcemap": "1.2.5",
32
32
  "launch-editor": "2.6.1"
33
33
  },
34
34
  "scripts": {