@mapled/cli 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/doctor.js +48 -2
- package/dist/live.d.ts +120 -12
- package/dist/live.js +1098 -261
- package/dist/scan.d.ts +8 -3
- package/dist/scan.js +68 -12
- package/package.json +1 -1
package/dist/scan.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export declare function detectRoutes(files: string[], framework: string | null):
|
|
|
61
61
|
name; `unclosed`: a quoted string a line break (or the end) cut off
|
|
62
62
|
before its closing quote — JSX lets an attribute run on. */
|
|
63
63
|
export type Token = {
|
|
64
|
-
kind: "ident" | "string" | "punct";
|
|
64
|
+
kind: "ident" | "string" | "punct" | "regex";
|
|
65
65
|
value: string;
|
|
66
66
|
nl?: true;
|
|
67
67
|
escaped?: true;
|
|
@@ -71,8 +71,13 @@ export type Token = {
|
|
|
71
71
|
comments and template bodies dropped. A regex literal after an
|
|
72
72
|
operator is skipped — only one that closes on its line, and never the
|
|
73
73
|
`/>` after a JSX attribute's `}`; JSX text is read as code, so an apostrophe in
|
|
74
|
-
prose can swallow a stretch — a false negative, never a crash.
|
|
75
|
-
|
|
74
|
+
prose can swallow a stretch — a false negative, never a crash.
|
|
75
|
+
`hidden`, when given, gets the code of each template's `${…}`, which
|
|
76
|
+
the tokens leave out; `ambiguous`, where a `/` right after `}` was read
|
|
77
|
+
as a regex — after an object, JavaScript reads a division there, and
|
|
78
|
+
what follows is code (`{} / f(x) / 1`). With `regexes`, a regex is a
|
|
79
|
+
token of its own rather than skipped. */
|
|
80
|
+
export declare function tokenize(text: string, hidden?: string[], ambiguous?: number[], regexes?: boolean): Token[];
|
|
76
81
|
export declare function routeKey(route: string): string;
|
|
77
82
|
export declare function scanRepository(dir: string, opts: ScanOptions): Promise<ScanResult>;
|
|
78
83
|
export type MergeResult = {
|
package/dist/scan.js
CHANGED
|
@@ -813,12 +813,69 @@ function unescapeAt(text, at) {
|
|
|
813
813
|
return [String.fromCharCode(parseInt(octal[0], 8)), at + 1 + octal[0].length];
|
|
814
814
|
return [e, at + 2];
|
|
815
815
|
}
|
|
816
|
+
/** The index of the `}` that closes the template substitution whose code
|
|
817
|
+
starts at `from`, with strings, templates and comments in it read as
|
|
818
|
+
JavaScript reads them — `${"}"}` closes at the second brace; the end of
|
|
819
|
+
the text when nothing closes it. A `/` in it that starts no comment may
|
|
820
|
+
start a regex, which can hold a brace or a quote: `doubt` hears of it. */
|
|
821
|
+
function substitutionEnd(text, from, doubt) {
|
|
822
|
+
// what the scan is in: code with that many open braces, or a template's text (0), innermost last
|
|
823
|
+
const stack = [1];
|
|
824
|
+
for (let j = from; j < text.length; j++) {
|
|
825
|
+
const c = text[j];
|
|
826
|
+
const top = stack[stack.length - 1];
|
|
827
|
+
if (top === 0) {
|
|
828
|
+
if (c === "\\")
|
|
829
|
+
j++;
|
|
830
|
+
else if (c === "`")
|
|
831
|
+
stack.pop();
|
|
832
|
+
else if (c === "$" && text[j + 1] === "{") {
|
|
833
|
+
stack.push(1);
|
|
834
|
+
j++;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
else if (c === "{")
|
|
838
|
+
stack[stack.length - 1] = top + 1;
|
|
839
|
+
else if (c === "}") {
|
|
840
|
+
if (top > 1)
|
|
841
|
+
stack[stack.length - 1] = top - 1;
|
|
842
|
+
else {
|
|
843
|
+
stack.pop();
|
|
844
|
+
if (stack.length === 0)
|
|
845
|
+
return j;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
else if (c === '"' || c === "'") {
|
|
849
|
+
for (j++; j < text.length && text[j] !== c && text[j] !== "\n" && text[j] !== "\r"; j++)
|
|
850
|
+
if (text[j] === "\\")
|
|
851
|
+
j++;
|
|
852
|
+
}
|
|
853
|
+
else if (c === "`")
|
|
854
|
+
stack.push(0);
|
|
855
|
+
else if (c === "/" && text[j + 1] === "/") {
|
|
856
|
+
while (j + 1 < text.length && text[j + 1] !== "\n" && text[j + 1] !== "\r")
|
|
857
|
+
j++;
|
|
858
|
+
}
|
|
859
|
+
else if (c === "/" && text[j + 1] === "*") {
|
|
860
|
+
const end = text.indexOf("*/", j + 2);
|
|
861
|
+
j = end === -1 ? text.length : end + 1;
|
|
862
|
+
}
|
|
863
|
+
else if (c === "/")
|
|
864
|
+
doubt?.();
|
|
865
|
+
}
|
|
866
|
+
return text.length;
|
|
867
|
+
}
|
|
816
868
|
/** JavaScript tokens: identifiers, string literals and punctuation, with
|
|
817
869
|
comments and template bodies dropped. A regex literal after an
|
|
818
870
|
operator is skipped — only one that closes on its line, and never the
|
|
819
871
|
`/>` after a JSX attribute's `}`; JSX text is read as code, so an apostrophe in
|
|
820
|
-
prose can swallow a stretch — a false negative, never a crash.
|
|
821
|
-
|
|
872
|
+
prose can swallow a stretch — a false negative, never a crash.
|
|
873
|
+
`hidden`, when given, gets the code of each template's `${…}`, which
|
|
874
|
+
the tokens leave out; `ambiguous`, where a `/` right after `}` was read
|
|
875
|
+
as a regex — after an object, JavaScript reads a division there, and
|
|
876
|
+
what follows is code (`{} / f(x) / 1`). With `regexes`, a regex is a
|
|
877
|
+
token of its own rather than skipped. */
|
|
878
|
+
export function tokenize(text, hidden, ambiguous, regexes = false) {
|
|
822
879
|
const out = [];
|
|
823
880
|
let i = 0;
|
|
824
881
|
const n = text.length;
|
|
@@ -864,16 +921,11 @@ export function tokenize(text) {
|
|
|
864
921
|
continue;
|
|
865
922
|
}
|
|
866
923
|
if (c === "`" && text[j] === "$" && text[j + 1] === "{") {
|
|
867
|
-
// a substitution:
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
depth++;
|
|
873
|
-
else if (text[j] === "}")
|
|
874
|
-
depth--;
|
|
875
|
-
j++;
|
|
876
|
-
}
|
|
924
|
+
// a substitution: its code, to the brace that closes it as JavaScript reads it
|
|
925
|
+
const from = j + 2;
|
|
926
|
+
const end = substitutionEnd(text, from, ambiguous ? () => ambiguous.push(from) : undefined);
|
|
927
|
+
hidden?.push(text.slice(from, end));
|
|
928
|
+
j = end + 1;
|
|
877
929
|
value += "${}";
|
|
878
930
|
continue;
|
|
879
931
|
}
|
|
@@ -932,9 +984,13 @@ export function tokenize(text) {
|
|
|
932
984
|
}
|
|
933
985
|
// a regex closes on its own line; a `/` that doesn't is the code's
|
|
934
986
|
if (text[j] === "/") {
|
|
987
|
+
if (prev?.kind === "punct" && prev.value === "}")
|
|
988
|
+
ambiguous?.push(i);
|
|
935
989
|
j++;
|
|
936
990
|
while (j < n && /[a-z]/.test(text[j]))
|
|
937
991
|
j++; // flags
|
|
992
|
+
if (regexes)
|
|
993
|
+
push({ kind: "regex", value: text.slice(i, j) });
|
|
938
994
|
i = j;
|
|
939
995
|
continue;
|
|
940
996
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapled/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Mapled CLI — sign in, link a project, generate TypeScript types for its content, create forms, preview drafts and check the site's integration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://mapled.io",
|