@rindo/core 1.17.4 → 2.5.2

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 (164) hide show
  1. package/LICENSE.md +27 -27
  2. package/bin/cli.ts +20 -0
  3. package/bin/rindo +51 -56
  4. package/cli/index.cjs +1263 -0
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +1232 -495
  7. package/cli/package.json +9 -4
  8. package/compiler/lib.d.ts +24 -0
  9. package/compiler/lib.dom.d.ts +20230 -0
  10. package/compiler/lib.dom.iterable.d.ts +351 -0
  11. package/compiler/lib.es2015.collection.d.ts +89 -0
  12. package/compiler/lib.es2015.core.d.ts +517 -0
  13. package/compiler/lib.es2015.d.ts +30 -0
  14. package/compiler/lib.es2015.generator.d.ts +79 -0
  15. package/compiler/lib.es2015.iterable.d.ts +505 -0
  16. package/compiler/lib.es2015.promise.d.ts +150 -0
  17. package/compiler/lib.es2015.proxy.d.ts +41 -0
  18. package/compiler/lib.es2015.reflect.d.ts +123 -0
  19. package/compiler/lib.es2015.symbol.d.ts +48 -0
  20. package/compiler/lib.es2015.symbol.wellknown.d.ts +324 -0
  21. package/compiler/lib.es2016.array.include.d.ts +118 -0
  22. package/compiler/lib.es2016.d.ts +22 -0
  23. package/compiler/lib.es2016.full.d.ts +25 -0
  24. package/compiler/lib.es2017.d.ts +26 -0
  25. package/compiler/lib.es2017.full.d.ts +25 -0
  26. package/compiler/lib.es2017.intl.d.ts +32 -0
  27. package/compiler/lib.es2017.object.d.ts +51 -0
  28. package/compiler/lib.es2017.sharedmemory.d.ts +137 -0
  29. package/compiler/lib.es2017.string.d.ts +47 -0
  30. package/compiler/lib.es2017.typedarrays.d.ts +55 -0
  31. package/compiler/lib.es2018.asyncgenerator.d.ts +79 -0
  32. package/compiler/lib.es2018.asynciterable.d.ts +45 -0
  33. package/compiler/lib.es2018.d.ts +26 -0
  34. package/compiler/lib.es2018.full.d.ts +25 -0
  35. package/compiler/lib.es2018.intl.d.ts +61 -0
  36. package/compiler/lib.es2018.promise.d.ts +32 -0
  37. package/compiler/lib.es2018.regexp.d.ts +39 -0
  38. package/compiler/lib.es2019.array.d.ts +85 -0
  39. package/compiler/lib.es2019.d.ts +25 -0
  40. package/compiler/lib.es2019.full.d.ts +25 -0
  41. package/compiler/lib.es2019.object.d.ts +35 -0
  42. package/compiler/lib.es2019.string.d.ts +33 -0
  43. package/compiler/lib.es2019.symbol.d.ts +26 -0
  44. package/compiler/lib.es2020.bigint.d.ts +728 -0
  45. package/compiler/lib.es2020.d.ts +27 -0
  46. package/compiler/lib.es2020.full.d.ts +25 -0
  47. package/compiler/lib.es2020.intl.d.ts +310 -0
  48. package/compiler/lib.es2020.promise.d.ts +50 -0
  49. package/compiler/lib.es2020.sharedmemory.d.ts +99 -0
  50. package/compiler/lib.es2020.string.d.ts +30 -0
  51. package/compiler/lib.es2020.symbol.wellknown.d.ts +39 -0
  52. package/compiler/lib.es5.d.ts +4435 -0
  53. package/compiler/lib.es6.d.ts +25 -0
  54. package/compiler/lib.esnext.d.ts +25 -0
  55. package/compiler/lib.esnext.full.d.ts +25 -0
  56. package/compiler/lib.esnext.intl.d.ts +32 -0
  57. package/compiler/lib.esnext.promise.d.ts +43 -0
  58. package/compiler/lib.esnext.string.d.ts +35 -0
  59. package/compiler/lib.esnext.weakref.d.ts +75 -0
  60. package/compiler/lib.scripthost.d.ts +327 -0
  61. package/compiler/lib.webworker.d.ts +6042 -0
  62. package/compiler/lib.webworker.importscripts.d.ts +26 -0
  63. package/compiler/lib.webworker.iterable.d.ts +166 -0
  64. package/compiler/package.json +3 -3
  65. package/compiler/rindo.d.ts +0 -16
  66. package/compiler/rindo.js +42738 -40541
  67. package/compiler/rindo.min.js +2 -15
  68. package/dependencies.json +73 -50
  69. package/dev-server/client/index.js +33 -10
  70. package/dev-server/client/package.json +3 -3
  71. package/dev-server/connector.html +3 -3
  72. package/dev-server/index.d.ts +3 -6
  73. package/dev-server/index.js +256 -252
  74. package/dev-server/package.json +3 -3
  75. package/dev-server/server-process.js +1738 -0
  76. package/dev-server/server-worker-thread.js +39 -0
  77. package/dev-server/templates/initial-load.html +160 -160
  78. package/dev-server/ws.js +1 -1
  79. package/internal/app-data/{index.cjs.js → index.cjs} +7 -5
  80. package/internal/app-data/index.d.ts +1 -0
  81. package/internal/app-data/index.js +7 -6
  82. package/internal/app-data/package.json +11 -5
  83. package/internal/client/css-shim.js +2 -2
  84. package/internal/client/dom.js +1 -1
  85. package/internal/client/index.js +193 -119
  86. package/internal/client/package.json +4 -3
  87. package/internal/client/{patch.js → patch-browser.js} +8 -24
  88. package/internal/client/patch-esm.js +23 -0
  89. package/internal/client/polyfills/css-shim.js +1 -1
  90. package/internal/client/polyfills/index.js +34 -34
  91. package/internal/client/shadow-css.js +9 -3
  92. package/internal/hydrate/index.js +305 -281
  93. package/internal/hydrate/package.json +2 -2
  94. package/internal/hydrate/runner.d.ts +24 -12
  95. package/internal/hydrate/runner.js +153 -124
  96. package/internal/hydrate/shadow-css.js +24 -24
  97. package/internal/package.json +5 -4
  98. package/internal/rindo-core/index.cjs +1 -0
  99. package/internal/rindo-core/index.d.ts +51 -2
  100. package/internal/rindo-core/index.js +15 -1
  101. package/internal/rindo-ext-modules.d.ts +41 -39
  102. package/internal/rindo-private.d.ts +93 -148
  103. package/internal/rindo-public-compiler.d.ts +231 -155
  104. package/internal/rindo-public-runtime.d.ts +42 -39
  105. package/internal/testing/index.js +144 -121
  106. package/internal/testing/package.json +2 -2
  107. package/internal/testing/shadow-css.js +24 -24
  108. package/mock-doc/index.cjs +4610 -0
  109. package/mock-doc/index.d.ts +12 -1
  110. package/mock-doc/index.js +177 -67
  111. package/mock-doc/package.json +11 -5
  112. package/package.json +132 -133
  113. package/readme.md +21 -95
  114. package/screenshot/compare/build/app.js +33 -33
  115. package/screenshot/compare/build/p-f4745c2f.entry.js +1 -1
  116. package/screenshot/connector-base.d.ts +1 -1
  117. package/screenshot/connector-local.d.ts +1 -1
  118. package/screenshot/index.js +63 -46
  119. package/screenshot/package.json +10 -3
  120. package/screenshot/pixel-match.js +54 -57
  121. package/screenshot/screenshot-compare.d.ts +1 -1
  122. package/screenshot/screenshot-fs.d.ts +1 -1
  123. package/sys/deno/index.js +1785 -0
  124. package/sys/deno/node-compat.js +2654 -0
  125. package/sys/deno/worker.js +44 -0
  126. package/sys/node/autoprefixer.js +8 -1
  127. package/sys/node/glob.js +1 -1
  128. package/sys/node/graceful-fs.js +1 -1
  129. package/sys/node/index.d.ts +1 -1
  130. package/sys/node/index.js +689 -705
  131. package/sys/node/node-fetch.js +1 -1
  132. package/sys/node/package.json +3 -3
  133. package/sys/node/prompts.js +1 -1
  134. package/sys/node/worker.js +38 -19
  135. package/testing/index.d.ts +3 -3
  136. package/testing/index.js +863 -749
  137. package/testing/jest/jest-config.d.ts +2 -89
  138. package/testing/jest/jest-environment.d.ts +1 -1
  139. package/testing/jest/jest-runner.d.ts +1 -1
  140. package/testing/jest/jest-screenshot.d.ts +1 -1
  141. package/testing/jest-preset.js +32 -32
  142. package/testing/matchers/events.d.ts +1 -1
  143. package/testing/matchers/screenshot.d.ts +1 -1
  144. package/testing/mock-fetch.d.ts +1 -1
  145. package/testing/mocks.d.ts +1 -1
  146. package/testing/package.json +3 -3
  147. package/testing/puppeteer/index.d.ts +1 -1
  148. package/testing/puppeteer/puppeteer-browser.d.ts +2 -2
  149. package/testing/puppeteer/puppeteer-declarations.d.ts +11 -11
  150. package/testing/puppeteer/puppeteer-element.d.ts +3 -3
  151. package/testing/puppeteer/puppeteer-emulate.d.ts +1 -1
  152. package/testing/puppeteer/puppeteer-events.d.ts +3 -3
  153. package/testing/puppeteer/puppeteer-page.d.ts +1 -1
  154. package/testing/puppeteer/puppeteer-screenshot.d.ts +2 -2
  155. package/testing/reset-build-conditionals.d.ts +1 -1
  156. package/testing/spec-page.d.ts +1 -1
  157. package/testing/test-transpile.d.ts +1 -1
  158. package/testing/testing-logger.d.ts +1 -1
  159. package/testing/testing-utils.d.ts +1 -1
  160. package/testing/testing.d.ts +1 -1
  161. package/cli/index.cjs.js +0 -524
  162. package/dev-server/content-type-db.json +0 -1
  163. package/dev-server/server-worker.js +0 -1570
  164. package/mock-doc/index.cjs.js +0 -4500
package/cli/index.js CHANGED
@@ -1,500 +1,1237 @@
1
- const IS_NODE_ENV = !("undefined" == typeof global || "function" != typeof require || !global.process || "string" != typeof __filename || global.origin && "string" == typeof global.origin), dashToPascalCase = e => (e => e.toLowerCase())(e).split("-").map(e => e.charAt(0).toUpperCase() + e.slice(1)).join(""), isFunction = e => "function" == typeof e, isString = e => "string" == typeof e, hasError = e => null != e && 0 !== e.length && e.some(e => "error" === e.level && "runtime" !== e.type), shouldIgnoreError = e => e === TASK_CANCELED_MSG, TASK_CANCELED_MSG = "task canceled", normalizePath = e => {
2
- if ("string" != typeof e) throw new Error("invalid path to normalize");
3
- e = normalizeSlashes(e.trim());
4
- const t = pathComponents(e, getRootLength(e)), s = reducePathComponents(t), n = s[0], r = s[1], o = n + s.slice(1).join("/");
5
- return "" === o ? "." : "" === n && r && e.includes("/") && !r.startsWith(".") && !r.startsWith("@") ? "./" + o : o;
6
- }, normalizeSlashes = e => e.replace(backslashRegExp, "/"), backslashRegExp = /\\/g, reducePathComponents = e => {
7
- if (!Array.isArray(e) || 0 === e.length) return [];
8
- const t = [ e[0] ];
9
- for (let s = 1; s < e.length; s++) {
10
- const n = e[s];
11
- if (n && "." !== n) {
12
- if (".." === n) if (t.length > 1) {
13
- if (".." !== t[t.length - 1]) {
14
- t.pop();
15
- continue;
16
- }
17
- } else if (t[0]) continue;
18
- t.push(n);
19
- }
20
- }
21
- return t;
22
- }, getRootLength = e => {
23
- const t = getEncodedRootLength(e);
24
- return t < 0 ? ~t : t;
25
- }, getEncodedRootLength = e => {
26
- if (!e) return 0;
27
- const t = e.charCodeAt(0);
28
- if (47 === t || 92 === t) {
29
- if (e.charCodeAt(1) !== t) return 1;
30
- const s = e.indexOf(47 === t ? "/" : "\\", 2);
31
- return s < 0 ? e.length : s + 1;
32
- }
33
- if (isVolumeCharacter(t) && 58 === e.charCodeAt(1)) {
34
- const t = e.charCodeAt(2);
35
- if (47 === t || 92 === t) return 3;
36
- if (2 === e.length) return 2;
37
- }
38
- const s = e.indexOf("://");
39
- if (-1 !== s) {
40
- const t = s + "://".length, n = e.indexOf("/", t);
41
- if (-1 !== n) {
42
- const r = e.slice(0, s), o = e.slice(t, n);
43
- if ("file" === r && ("" === o || "localhost" === o) && isVolumeCharacter(e.charCodeAt(n + 1))) {
44
- const t = getFileUrlVolumeSeparatorEnd(e, n + 2);
45
- if (-1 !== t) {
46
- if (47 === e.charCodeAt(t)) return ~(t + 1);
47
- if (t === e.length) return ~t;
48
- }
49
- }
50
- return ~(n + 1);
51
- }
52
- return ~e.length;
53
- }
54
- return 0;
55
- }, isVolumeCharacter = e => e >= 97 && e <= 122 || e >= 65 && e <= 90, getFileUrlVolumeSeparatorEnd = (e, t) => {
56
- const s = e.charCodeAt(t);
57
- if (58 === s) return t + 1;
58
- if (37 === s && 51 === e.charCodeAt(t + 1)) {
59
- const s = e.charCodeAt(t + 2);
60
- if (97 === s || 65 === s) return t + 3;
61
- }
62
- return -1;
63
- }, pathComponents = (e, t) => {
64
- const s = e.substring(0, t), n = e.substring(t).split("/"), r = n.length;
65
- return r > 0 && !n[r - 1] && n.pop(), [ s, ...n ];
66
- }, parseFlags = (e, t) => {
67
- const s = {
68
- task: null,
69
- args: [],
70
- knownArgs: [],
71
- unknownArgs: null
72
- };
73
- if (s.args = e.slice(), s.args.length > 0 && s.args[0] && !s.args[0].startsWith("-") && (s.task = s.args[0]),
74
- parseArgs(s, s.args, s.knownArgs), t && "node" === t.name) {
75
- const e = getNpmConfigEnvArgs(t);
76
- parseArgs(s, e, s.knownArgs), e.forEach(e => {
77
- s.args.includes(e) || s.args.push(e);
78
- });
79
- }
80
- if (null != s.task) {
81
- const e = s.args.indexOf(s.task);
82
- e > -1 && s.args.splice(e, 1);
83
- }
84
- return s.unknownArgs = s.args.filter(e => !s.knownArgs.includes(e)), s;
85
- }, parseArgs = (e, t, s) => {
86
- ARG_OPTS.boolean.forEach(n => {
87
- const r = ARG_OPTS.alias[n], o = configCase(n);
88
- "boolean" != typeof e[o] && (e[o] = null), t.forEach(t => {
89
- t === "--" + n || t === "--" + o ? (e[o] = !0, s.push(t)) : t === "--no-" + n || t === "--no" + dashToPascalCase(n) ? (e[o] = !1,
90
- s.push(t)) : r && t === "-" + r && (e[o] = !0, s.push(t));
91
- });
92
- }), ARG_OPTS.string.forEach(n => {
93
- const r = ARG_OPTS.alias[n], o = configCase(n);
94
- "string" != typeof e[o] && (e[o] = null);
95
- for (let i = 0; i < t.length; i++) {
96
- const a = t[i];
97
- if (a.startsWith(`--${n}=`)) {
98
- const t = a.split("=");
99
- t.shift(), e[o] = t.join("="), s.push(a);
100
- } else if (a === "--" + n) e[o] = t[i + 1], s.push(a), s.push(t[i + 1]); else if (a === "--" + o) e[o] = t[i + 1],
101
- s.push(a), s.push(t[i + 1]); else if (a.startsWith(`--${o}=`)) {
102
- const t = a.split("=");
103
- t.shift(), e[o] = t.join("="), s.push(a);
104
- } else if (r) if (a.startsWith(`-${r}=`)) {
105
- const t = a.split("=");
106
- t.shift(), e[o] = t.join("="), s.push(a);
107
- } else a === "-" + r && (e[o] = t[i + 1], s.push(t[i + 1]));
108
- }
109
- }), ARG_OPTS.number.forEach(n => {
110
- const r = ARG_OPTS.alias[n], o = configCase(n);
111
- "number" != typeof e[o] && (e[o] = null);
112
- for (let i = 0; i < t.length; i++) {
113
- const a = t[i];
114
- if (a.startsWith(`--${n}=`)) {
115
- const t = a.split("=");
116
- t.shift(), e[o] = parseInt(t.join(""), 10), s.push(a);
117
- } else if (a === "--" + n) e[o] = parseInt(t[i + 1], 10), s.push(t[i + 1]); else if (a.startsWith(`--${o}=`)) {
118
- const t = a.split("=");
119
- t.shift(), e[o] = parseInt(t.join(""), 10), s.push(a);
120
- } else if (a === "--" + o) e[o] = parseInt(t[i + 1], 10), s.push(t[i + 1]); else if (r) if (a.startsWith(`-${r}=`)) {
121
- const t = a.split("=");
122
- t.shift(), e[o] = parseInt(t.join(""), 10), s.push(a);
123
- } else a === "-" + r && (e[o] = parseInt(t[i + 1], 10), s.push(t[i + 1]));
1
+ /*!
2
+ Rindo CLI v2.5.2 | MIT Licensed | https://rindojs.web.app
3
+ */
4
+ const toLowerCase = (str) => str.toLowerCase();
5
+ const dashToPascalCase = (str) => toLowerCase(str)
6
+ .split('-')
7
+ .map(segment => segment.charAt(0).toUpperCase() + segment.slice(1))
8
+ .join('');
9
+ const isFunction = (v) => typeof v === 'function';
10
+ const isString = (v) => typeof v === 'string';
11
+
12
+ const buildError = (diagnostics) => {
13
+ const diagnostic = {
14
+ level: 'error',
15
+ type: 'build',
16
+ header: 'Build Error',
17
+ messageText: 'build error',
18
+ relFilePath: null,
19
+ absFilePath: null,
20
+ lines: [],
21
+ };
22
+ if (diagnostics) {
23
+ diagnostics.push(diagnostic);
24
+ }
25
+ return diagnostic;
26
+ };
27
+ const catchError = (diagnostics, err, msg) => {
28
+ const diagnostic = {
29
+ level: 'error',
30
+ type: 'build',
31
+ header: 'Build Error',
32
+ messageText: 'build error',
33
+ relFilePath: null,
34
+ absFilePath: null,
35
+ lines: [],
36
+ };
37
+ if (isString(msg)) {
38
+ diagnostic.messageText = msg;
39
+ }
40
+ else if (err != null) {
41
+ if (err.stack != null) {
42
+ diagnostic.messageText = err.stack.toString();
43
+ }
44
+ else {
45
+ if (err.message != null) {
46
+ diagnostic.messageText = err.message.toString();
47
+ }
48
+ else {
49
+ diagnostic.messageText = err.toString();
50
+ }
51
+ }
52
+ }
53
+ if (diagnostics != null && !shouldIgnoreError(diagnostic.messageText)) {
54
+ diagnostics.push(diagnostic);
55
+ }
56
+ return diagnostic;
57
+ };
58
+ const hasError = (diagnostics) => {
59
+ if (diagnostics == null || diagnostics.length === 0) {
60
+ return false;
61
+ }
62
+ return diagnostics.some(d => d.level === 'error' && d.type !== 'runtime');
63
+ };
64
+ const shouldIgnoreError = (msg) => {
65
+ return msg === TASK_CANCELED_MSG;
66
+ };
67
+ const TASK_CANCELED_MSG = `task canceled`;
68
+
69
+ /**
70
+ * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
71
+ * Forward-slash paths can be used in Windows as long as they're not
72
+ * extended-length paths and don't contain any non-ascii characters.
73
+ * This was created since the path methods in Node.js outputs \\ paths on Windows.
74
+ */
75
+ const normalizePath = (path) => {
76
+ if (typeof path !== 'string') {
77
+ throw new Error(`invalid path to normalize`);
78
+ }
79
+ path = normalizeSlashes(path.trim());
80
+ const components = pathComponents(path, getRootLength(path));
81
+ const reducedComponents = reducePathComponents(components);
82
+ const rootPart = reducedComponents[0];
83
+ const secondPart = reducedComponents[1];
84
+ const normalized = rootPart + reducedComponents.slice(1).join('/');
85
+ if (normalized === '') {
86
+ return '.';
87
+ }
88
+ if (rootPart === '' &&
89
+ secondPart &&
90
+ path.includes('/') &&
91
+ !secondPart.startsWith('.') &&
92
+ !secondPart.startsWith('@')) {
93
+ return './' + normalized;
94
+ }
95
+ return normalized;
96
+ };
97
+ const normalizeSlashes = (path) => path.replace(backslashRegExp, '/');
98
+ const altDirectorySeparator = '\\';
99
+ const urlSchemeSeparator = '://';
100
+ const backslashRegExp = /\\/g;
101
+ const reducePathComponents = (components) => {
102
+ if (!Array.isArray(components) || components.length === 0) {
103
+ return [];
104
+ }
105
+ const reduced = [components[0]];
106
+ for (let i = 1; i < components.length; i++) {
107
+ const component = components[i];
108
+ if (!component)
109
+ continue;
110
+ if (component === '.')
111
+ continue;
112
+ if (component === '..') {
113
+ if (reduced.length > 1) {
114
+ if (reduced[reduced.length - 1] !== '..') {
115
+ reduced.pop();
116
+ continue;
117
+ }
118
+ }
119
+ else if (reduced[0])
120
+ continue;
121
+ }
122
+ reduced.push(component);
123
+ }
124
+ return reduced;
125
+ };
126
+ const getRootLength = (path) => {
127
+ const rootLength = getEncodedRootLength(path);
128
+ return rootLength < 0 ? ~rootLength : rootLength;
129
+ };
130
+ const getEncodedRootLength = (path) => {
131
+ if (!path)
132
+ return 0;
133
+ const ch0 = path.charCodeAt(0);
134
+ // POSIX or UNC
135
+ if (ch0 === 47 /* slash */ || ch0 === 92 /* backslash */) {
136
+ if (path.charCodeAt(1) !== ch0)
137
+ return 1; // POSIX: "/" (or non-normalized "\")
138
+ const p1 = path.indexOf(ch0 === 47 /* slash */ ? '/' : altDirectorySeparator, 2);
139
+ if (p1 < 0)
140
+ return path.length; // UNC: "//server" or "\\server"
141
+ return p1 + 1; // UNC: "//server/" or "\\server\"
142
+ }
143
+ // DOS
144
+ if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* colon */) {
145
+ const ch2 = path.charCodeAt(2);
146
+ if (ch2 === 47 /* slash */ || ch2 === 92 /* backslash */)
147
+ return 3; // DOS: "c:/" or "c:\"
148
+ if (path.length === 2)
149
+ return 2; // DOS: "c:" (but not "c:d")
150
+ }
151
+ // URL
152
+ const schemeEnd = path.indexOf(urlSchemeSeparator);
153
+ if (schemeEnd !== -1) {
154
+ const authorityStart = schemeEnd + urlSchemeSeparator.length;
155
+ const authorityEnd = path.indexOf('/', authorityStart);
156
+ if (authorityEnd !== -1) {
157
+ // URL: "file:///", "file://server/", "file://server/path"
158
+ // For local "file" URLs, include the leading DOS volume (if present).
159
+ // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
160
+ // special case interpreted as "the machine from which the URL is being interpreted".
161
+ const scheme = path.slice(0, schemeEnd);
162
+ const authority = path.slice(authorityStart, authorityEnd);
163
+ if (scheme === 'file' &&
164
+ (authority === '' || authority === 'localhost') &&
165
+ isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
166
+ const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
167
+ if (volumeSeparatorEnd !== -1) {
168
+ if (path.charCodeAt(volumeSeparatorEnd) === 47 /* slash */) {
169
+ // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
170
+ return ~(volumeSeparatorEnd + 1);
171
+ }
172
+ if (volumeSeparatorEnd === path.length) {
173
+ // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
174
+ // but not "file:///c:d" or "file:///c%3ad"
175
+ return ~volumeSeparatorEnd;
176
+ }
177
+ }
178
+ }
179
+ return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
180
+ }
181
+ return ~path.length; // URL: "file://server", "http://server"
182
+ }
183
+ // relative
184
+ return 0;
185
+ };
186
+ const isVolumeCharacter = (charCode) => (charCode >= 97 /* a */ && charCode <= 122 /* z */) ||
187
+ (charCode >= 65 /* A */ && charCode <= 90 /* Z */);
188
+ const getFileUrlVolumeSeparatorEnd = (url, start) => {
189
+ const ch0 = url.charCodeAt(start);
190
+ if (ch0 === 58 /* colon */)
191
+ return start + 1;
192
+ if (ch0 === 37 /* percent */ && url.charCodeAt(start + 1) === 51 /* _3 */) {
193
+ const ch2 = url.charCodeAt(start + 2);
194
+ if (ch2 === 97 /* a */ || ch2 === 65 /* A */)
195
+ return start + 3;
196
+ }
197
+ return -1;
198
+ };
199
+ const pathComponents = (path, rootLength) => {
200
+ const root = path.substring(0, rootLength);
201
+ const rest = path.substring(rootLength).split('/');
202
+ const restLen = rest.length;
203
+ if (restLen > 0 && !rest[restLen - 1]) {
204
+ rest.pop();
205
+ }
206
+ return [root, ...rest];
207
+ };
208
+
209
+ const validateComponentTag = (tag) => {
210
+ if (tag !== tag.trim()) {
211
+ return `Tag can not contain white spaces`;
212
+ }
213
+ if (tag !== tag.toLowerCase()) {
214
+ return `Tag can not contain upper case characters`;
215
+ }
216
+ if (typeof tag !== 'string') {
217
+ return `Tag "${tag}" must be a string type`;
218
+ }
219
+ if (tag.length === 0) {
220
+ return `Received empty tag value`;
221
+ }
222
+ if (tag.indexOf(' ') > -1) {
223
+ return `"${tag}" tag cannot contain a space`;
224
+ }
225
+ if (tag.indexOf(',') > -1) {
226
+ return `"${tag}" tag cannot be used for multiple tags`;
227
+ }
228
+ const invalidChars = tag.replace(/\w|-/g, '');
229
+ if (invalidChars !== '') {
230
+ return `"${tag}" tag contains invalid characters: ${invalidChars}`;
231
+ }
232
+ if (tag.indexOf('-') === -1) {
233
+ return `"${tag}" tag must contain a dash (-) to work as a valid web component`;
234
+ }
235
+ if (tag.indexOf('--') > -1) {
236
+ return `"${tag}" tag cannot contain multiple dashes (--) next to each other`;
237
+ }
238
+ if (tag.indexOf('-') === 0) {
239
+ return `"${tag}" tag cannot start with a dash (-)`;
240
+ }
241
+ if (tag.lastIndexOf('-') === tag.length - 1) {
242
+ return `"${tag}" tag cannot end with a dash (-)`;
243
+ }
244
+ return undefined;
245
+ };
246
+
247
+ const parseFlags = (args, sys) => {
248
+ const flags = {
249
+ task: null,
250
+ args: [],
251
+ knownArgs: [],
252
+ unknownArgs: null,
253
+ };
254
+ // cmd line has more priority over npm scripts cmd
255
+ flags.args = args.slice();
256
+ if (flags.args.length > 0 && flags.args[0] && !flags.args[0].startsWith('-')) {
257
+ flags.task = flags.args[0];
258
+ }
259
+ parseArgs(flags, flags.args, flags.knownArgs);
260
+ if (sys && sys.name === 'node') {
261
+ const envArgs = getNpmConfigEnvArgs(sys);
262
+ parseArgs(flags, envArgs, flags.knownArgs);
263
+ envArgs.forEach(envArg => {
264
+ if (!flags.args.includes(envArg)) {
265
+ flags.args.push(envArg);
266
+ }
267
+ });
268
+ }
269
+ if (flags.task != null) {
270
+ const i = flags.args.indexOf(flags.task);
271
+ if (i > -1) {
272
+ flags.args.splice(i, 1);
273
+ }
274
+ }
275
+ flags.unknownArgs = flags.args.filter((arg) => {
276
+ return !flags.knownArgs.includes(arg);
277
+ });
278
+ return flags;
279
+ };
280
+ const parseArgs = (flags, args, knownArgs) => {
281
+ ARG_OPTS.boolean.forEach(booleanName => {
282
+ const alias = ARG_OPTS.alias[booleanName];
283
+ const flagKey = configCase(booleanName);
284
+ if (typeof flags[flagKey] !== 'boolean') {
285
+ flags[flagKey] = null;
286
+ }
287
+ args.forEach(cmdArg => {
288
+ if (cmdArg === `--${booleanName}`) {
289
+ flags[flagKey] = true;
290
+ knownArgs.push(cmdArg);
291
+ }
292
+ else if (cmdArg === `--${flagKey}`) {
293
+ flags[flagKey] = true;
294
+ knownArgs.push(cmdArg);
295
+ }
296
+ else if (cmdArg === `--no-${booleanName}`) {
297
+ flags[flagKey] = false;
298
+ knownArgs.push(cmdArg);
299
+ }
300
+ else if (cmdArg === `--no${dashToPascalCase(booleanName)}`) {
301
+ flags[flagKey] = false;
302
+ knownArgs.push(cmdArg);
303
+ }
304
+ else if (alias && cmdArg === `-${alias}`) {
305
+ flags[flagKey] = true;
306
+ knownArgs.push(cmdArg);
307
+ }
308
+ });
309
+ });
310
+ ARG_OPTS.string.forEach(stringName => {
311
+ const alias = ARG_OPTS.alias[stringName];
312
+ const flagKey = configCase(stringName);
313
+ if (typeof flags[flagKey] !== 'string') {
314
+ flags[flagKey] = null;
315
+ }
316
+ for (let i = 0; i < args.length; i++) {
317
+ const cmdArg = args[i];
318
+ if (cmdArg.startsWith(`--${stringName}=`)) {
319
+ const values = cmdArg.split('=');
320
+ values.shift();
321
+ flags[flagKey] = values.join('=');
322
+ knownArgs.push(cmdArg);
323
+ }
324
+ else if (cmdArg === `--${stringName}`) {
325
+ flags[flagKey] = args[i + 1];
326
+ knownArgs.push(cmdArg);
327
+ knownArgs.push(args[i + 1]);
328
+ }
329
+ else if (cmdArg === `--${flagKey}`) {
330
+ flags[flagKey] = args[i + 1];
331
+ knownArgs.push(cmdArg);
332
+ knownArgs.push(args[i + 1]);
333
+ }
334
+ else if (cmdArg.startsWith(`--${flagKey}=`)) {
335
+ const values = cmdArg.split('=');
336
+ values.shift();
337
+ flags[flagKey] = values.join('=');
338
+ knownArgs.push(cmdArg);
339
+ }
340
+ else if (alias) {
341
+ if (cmdArg.startsWith(`-${alias}=`)) {
342
+ const values = cmdArg.split('=');
343
+ values.shift();
344
+ flags[flagKey] = values.join('=');
345
+ knownArgs.push(cmdArg);
346
+ }
347
+ else if (cmdArg === `-${alias}`) {
348
+ flags[flagKey] = args[i + 1];
349
+ knownArgs.push(args[i + 1]);
350
+ }
351
+ }
352
+ }
353
+ });
354
+ ARG_OPTS.number.forEach(numberName => {
355
+ const alias = ARG_OPTS.alias[numberName];
356
+ const flagKey = configCase(numberName);
357
+ if (typeof flags[flagKey] !== 'number') {
358
+ flags[flagKey] = null;
359
+ }
360
+ for (let i = 0; i < args.length; i++) {
361
+ const cmdArg = args[i];
362
+ if (cmdArg.startsWith(`--${numberName}=`)) {
363
+ const values = cmdArg.split('=');
364
+ values.shift();
365
+ flags[flagKey] = parseInt(values.join(''), 10);
366
+ knownArgs.push(cmdArg);
367
+ }
368
+ else if (cmdArg === `--${numberName}`) {
369
+ flags[flagKey] = parseInt(args[i + 1], 10);
370
+ knownArgs.push(args[i + 1]);
371
+ }
372
+ else if (cmdArg.startsWith(`--${flagKey}=`)) {
373
+ const values = cmdArg.split('=');
374
+ values.shift();
375
+ flags[flagKey] = parseInt(values.join(''), 10);
376
+ knownArgs.push(cmdArg);
377
+ }
378
+ else if (cmdArg === `--${flagKey}`) {
379
+ flags[flagKey] = parseInt(args[i + 1], 10);
380
+ knownArgs.push(args[i + 1]);
381
+ }
382
+ else if (alias) {
383
+ if (cmdArg.startsWith(`-${alias}=`)) {
384
+ const values = cmdArg.split('=');
385
+ values.shift();
386
+ flags[flagKey] = parseInt(values.join(''), 10);
387
+ knownArgs.push(cmdArg);
388
+ }
389
+ else if (cmdArg === `-${alias}`) {
390
+ flags[flagKey] = parseInt(args[i + 1], 10);
391
+ knownArgs.push(args[i + 1]);
392
+ }
393
+ }
394
+ }
395
+ });
396
+ };
397
+ const configCase = (prop) => {
398
+ prop = dashToPascalCase(prop);
399
+ return prop.charAt(0).toLowerCase() + prop.substr(1);
400
+ };
401
+ const ARG_OPTS = {
402
+ boolean: [
403
+ 'build',
404
+ 'cache',
405
+ 'check-version',
406
+ 'ci',
407
+ 'compare',
408
+ 'debug',
409
+ 'dev',
410
+ 'devtools',
411
+ 'docs',
412
+ 'e2e',
413
+ 'es5',
414
+ 'esm',
415
+ 'headless',
416
+ 'help',
417
+ 'log',
418
+ 'open',
419
+ 'prerender',
420
+ 'prerender-external',
421
+ 'prod',
422
+ 'profile',
423
+ 'service-worker',
424
+ 'screenshot',
425
+ 'serve',
426
+ 'skip-node-check',
427
+ 'spec',
428
+ 'ssr',
429
+ 'stats',
430
+ 'update-screenshot',
431
+ 'verbose',
432
+ 'version',
433
+ 'watch',
434
+ ],
435
+ number: ['max-workers', 'port'],
436
+ string: ['address', 'config', 'docs-json', 'emulate', 'log-level', 'root', 'screenshot-connector'],
437
+ alias: {
438
+ config: 'c',
439
+ help: 'h',
440
+ port: 'p',
441
+ version: 'v',
442
+ },
443
+ };
444
+ const getNpmConfigEnvArgs = (sys) => {
445
+ // process.env.npm_config_argv
446
+ // {"remain":["4444"],"cooked":["run","serve","--port","4444"],"original":["run","serve","--port","4444"]}
447
+ let args = [];
448
+ try {
449
+ const npmConfigArgs = sys.getEnvironmentVar('npm_config_argv');
450
+ if (npmConfigArgs) {
451
+ args = JSON.parse(npmConfigArgs).original;
452
+ if (args[0] === 'run') {
453
+ args = args.slice(2);
454
+ }
455
+ }
456
+ }
457
+ catch (e) { }
458
+ return args;
459
+ };
460
+
461
+ const dependencies = [
462
+ {
463
+ name: "@rindo/core",
464
+ version: "2.5.2",
465
+ main: "compiler/rindo.js",
466
+ resources: [
467
+ "package.json",
468
+ "compiler/lib.d.ts",
469
+ "compiler/lib.dom.d.ts",
470
+ "compiler/lib.dom.iterable.d.ts",
471
+ "compiler/lib.es2015.collection.d.ts",
472
+ "compiler/lib.es2015.core.d.ts",
473
+ "compiler/lib.es2015.d.ts",
474
+ "compiler/lib.es2015.generator.d.ts",
475
+ "compiler/lib.es2015.iterable.d.ts",
476
+ "compiler/lib.es2015.promise.d.ts",
477
+ "compiler/lib.es2015.proxy.d.ts",
478
+ "compiler/lib.es2015.reflect.d.ts",
479
+ "compiler/lib.es2015.symbol.d.ts",
480
+ "compiler/lib.es2015.symbol.wellknown.d.ts",
481
+ "compiler/lib.es2016.array.include.d.ts",
482
+ "compiler/lib.es2016.d.ts",
483
+ "compiler/lib.es2016.full.d.ts",
484
+ "compiler/lib.es2017.d.ts",
485
+ "compiler/lib.es2017.full.d.ts",
486
+ "compiler/lib.es2017.intl.d.ts",
487
+ "compiler/lib.es2017.object.d.ts",
488
+ "compiler/lib.es2017.sharedmemory.d.ts",
489
+ "compiler/lib.es2017.string.d.ts",
490
+ "compiler/lib.es2017.typedarrays.d.ts",
491
+ "compiler/lib.es2018.asyncgenerator.d.ts",
492
+ "compiler/lib.es2018.asynciterable.d.ts",
493
+ "compiler/lib.es2018.d.ts",
494
+ "compiler/lib.es2018.full.d.ts",
495
+ "compiler/lib.es2018.intl.d.ts",
496
+ "compiler/lib.es2018.promise.d.ts",
497
+ "compiler/lib.es2018.regexp.d.ts",
498
+ "compiler/lib.es2019.array.d.ts",
499
+ "compiler/lib.es2019.d.ts",
500
+ "compiler/lib.es2019.full.d.ts",
501
+ "compiler/lib.es2019.object.d.ts",
502
+ "compiler/lib.es2019.string.d.ts",
503
+ "compiler/lib.es2019.symbol.d.ts",
504
+ "compiler/lib.es2020.bigint.d.ts",
505
+ "compiler/lib.es2020.d.ts",
506
+ "compiler/lib.es2020.full.d.ts",
507
+ "compiler/lib.es2020.intl.d.ts",
508
+ "compiler/lib.es2020.promise.d.ts",
509
+ "compiler/lib.es2020.sharedmemory.d.ts",
510
+ "compiler/lib.es2020.string.d.ts",
511
+ "compiler/lib.es2020.symbol.wellknown.d.ts",
512
+ "compiler/lib.es5.d.ts",
513
+ "compiler/lib.es6.d.ts",
514
+ "compiler/lib.esnext.d.ts",
515
+ "compiler/lib.esnext.full.d.ts",
516
+ "compiler/lib.esnext.intl.d.ts",
517
+ "compiler/lib.esnext.promise.d.ts",
518
+ "compiler/lib.esnext.string.d.ts",
519
+ "compiler/lib.esnext.weakref.d.ts",
520
+ "compiler/lib.scripthost.d.ts",
521
+ "compiler/lib.webworker.d.ts",
522
+ "compiler/lib.webworker.importscripts.d.ts",
523
+ "compiler/lib.webworker.iterable.d.ts",
524
+ "internal/index.d.ts",
525
+ "internal/index.js",
526
+ "internal/package.json",
527
+ "internal/rindo-ext-modules.d.ts",
528
+ "internal/rindo-private.d.ts",
529
+ "internal/rindo-public-compiler.d.ts",
530
+ "internal/rindo-public-docs.d.ts",
531
+ "internal/rindo-public-runtime.d.ts",
532
+ "mock-doc/index.js",
533
+ "mock-doc/package.json",
534
+ "internal/client/css-shim.js",
535
+ "internal/client/dom.js",
536
+ "internal/client/index.js",
537
+ "internal/client/package.json",
538
+ "internal/client/patch-browser.js",
539
+ "internal/client/patch-esm.js",
540
+ "internal/client/shadow-css.js",
541
+ "internal/hydrate/index.js",
542
+ "internal/hydrate/package.json",
543
+ "internal/hydrate/runner.js",
544
+ "internal/hydrate/shadow-css.js",
545
+ "internal/rindo-core/index.d.ts",
546
+ "internal/rindo-core/index.js"
547
+ ]
548
+ },
549
+ {
550
+ name: "rollup",
551
+ version: "2.42.3",
552
+ main: "dist/es/rollup.browser.js"
553
+ },
554
+ {
555
+ name: "terser",
556
+ version: "5.6.1",
557
+ main: "dist/bundle.min.js"
558
+ },
559
+ {
560
+ name: "typescript",
561
+ version: "4.2.3",
562
+ main: "lib/typescript.js"
563
+ }
564
+ ];
565
+
566
+ const findConfig = async (opts) => {
567
+ const sys = opts.sys;
568
+ const cwd = sys.getCurrentDirectory();
569
+ const results = {
570
+ configPath: null,
571
+ rootDir: normalizePath(cwd),
572
+ diagnostics: [],
573
+ };
574
+ let configPath = opts.configPath;
575
+ if (isString(configPath)) {
576
+ if (!sys.platformPath.isAbsolute(configPath)) {
577
+ // passed in a custom rindo config location
578
+ // but it's relative, so prefix the cwd
579
+ configPath = normalizePath(sys.platformPath.join(cwd, configPath));
580
+ }
581
+ else {
582
+ // config path already an absolute path, we're good here
583
+ configPath = normalizePath(opts.configPath);
584
+ }
585
+ }
586
+ else {
587
+ // nothing was passed in, use the current working directory
588
+ configPath = results.rootDir;
589
+ }
590
+ const stat = await sys.stat(configPath);
591
+ if (stat.error) {
592
+ const diagnostic = buildError(results.diagnostics);
593
+ diagnostic.absFilePath = configPath;
594
+ diagnostic.header = `Invalid config path`;
595
+ diagnostic.messageText = `Config path "${configPath}" not found`;
596
+ return results;
597
+ }
598
+ if (stat.isFile) {
599
+ results.configPath = configPath;
600
+ results.rootDir = sys.platformPath.dirname(configPath);
601
+ }
602
+ else if (stat.isDirectory) {
603
+ // this is only a directory, so let's make some assumptions
604
+ for (const configName of ['rindo.config.ts', 'rindo.config.js']) {
605
+ const testConfigFilePath = sys.platformPath.join(configPath, configName);
606
+ const stat = await sys.stat(testConfigFilePath);
607
+ if (stat.isFile) {
608
+ results.configPath = testConfigFilePath;
609
+ results.rootDir = sys.platformPath.dirname(testConfigFilePath);
610
+ break;
611
+ }
612
+ }
613
+ }
614
+ return results;
615
+ };
616
+
617
+ const loadCoreCompiler = async (sys) => {
618
+ await sys.dynamicImport(sys.getCompilerExecutingPath());
619
+ return globalThis.rindo;
620
+ };
621
+
622
+ const startupLog = (logger, task) => {
623
+ if (task === 'info' || task === 'serve' || task === 'version') {
624
+ return;
625
+ }
626
+ logger.info(logger.cyan(`@rindo/core`));
627
+ };
628
+ const startupLogVersion = (logger, task, coreCompiler) => {
629
+ if (task === 'info' || task === 'serve' || task === 'version') {
630
+ return;
631
+ }
632
+ const isDevBuild = coreCompiler.version.includes('-dev.');
633
+ let startupMsg;
634
+ if (isDevBuild) {
635
+ startupMsg = logger.yellow('[LOCAL DEV]');
636
+ }
637
+ else {
638
+ startupMsg = logger.cyan(`v${coreCompiler.version}`);
639
+ }
640
+ startupMsg += logger.emoji(' ' + coreCompiler.vermoji);
641
+ logger.info(startupMsg);
642
+ };
643
+ const loadedCompilerLog = (sys, logger, flags, coreCompiler) => {
644
+ const sysDetails = sys.details;
645
+ const runtimeInfo = `${sys.name} ${sys.version}`;
646
+ const platformInfo = `${sysDetails.platform}, ${sysDetails.cpuModel}`;
647
+ const statsInfo = `cpus: ${sys.hardwareConcurrency}, freemem: ${Math.round(sysDetails.freemem() / 1000000)}MB, totalmem: ${Math.round(sysDetails.totalmem / 1000000)}MB`;
648
+ if (logger.getLevel() === 'debug') {
649
+ logger.debug(runtimeInfo);
650
+ logger.debug(platformInfo);
651
+ logger.debug(statsInfo);
652
+ logger.debug(`compiler: ${sys.getCompilerExecutingPath()}`);
653
+ logger.debug(`build: ${coreCompiler.buildId}`);
654
+ }
655
+ else if (flags.ci) {
656
+ logger.info(runtimeInfo);
657
+ logger.info(platformInfo);
658
+ logger.info(statsInfo);
659
+ }
660
+ };
661
+ const startupCompilerLog = (coreCompiler, config) => {
662
+ if (config.suppressLogs === true) {
663
+ return;
664
+ }
665
+ const { logger } = config;
666
+ const isDebug = logger.getLevel() === 'debug';
667
+ const isPrerelease = coreCompiler.version.includes('-');
668
+ const isDevBuild = coreCompiler.version.includes('-dev.');
669
+ if (isPrerelease && !isDevBuild) {
670
+ logger.warn(logger.yellow(`This is a prerelease build, undocumented changes might happen at any time. Technical support is not available for prereleases, but any assistance testing is appreciated.`));
671
+ }
672
+ if (config.devMode && !isDebug) {
673
+ if (config.buildEs5) {
674
+ logger.warn(`Generating ES5 during development is a very task expensive, initial and incremental builds will be much slower. Drop the '--es5' flag and use a modern browser for development.`);
675
+ }
676
+ if (!config.enableCache) {
677
+ logger.warn(`Disabling cache during development will slow down incremental builds.`);
678
+ }
679
+ }
680
+ };
681
+
682
+ const taskPrerender = async (coreCompiler, config) => {
683
+ startupCompilerLog(coreCompiler, config);
684
+ const hydrateAppFilePath = config.flags.unknownArgs[0];
685
+ if (typeof hydrateAppFilePath !== 'string') {
686
+ config.logger.error(`Missing hydrate app script path`);
687
+ return config.sys.exit(1);
688
+ }
689
+ const srcIndexHtmlPath = config.srcIndexHtml;
690
+ const diagnostics = await runPrerenderTask(coreCompiler, config, hydrateAppFilePath, null, srcIndexHtmlPath);
691
+ config.logger.printDiagnostics(diagnostics);
692
+ if (diagnostics.some(d => d.level === 'error')) {
693
+ return config.sys.exit(1);
694
+ }
695
+ };
696
+ const runPrerenderTask = async (coreCompiler, config, hydrateAppFilePath, componentGraph, srcIndexHtmlPath) => {
697
+ const diagnostics = [];
698
+ try {
699
+ const prerenderer = await coreCompiler.createPrerenderer(config);
700
+ const results = await prerenderer.start({
701
+ hydrateAppFilePath,
702
+ componentGraph,
703
+ srcIndexHtmlPath,
704
+ });
705
+ diagnostics.push(...results.diagnostics);
706
+ }
707
+ catch (e) {
708
+ catchError(diagnostics, e);
709
+ }
710
+ return diagnostics;
711
+ };
712
+
713
+ const startCheckVersion = async (config, currentVersion) => {
714
+ if (config.devMode && !config.flags.ci && !currentVersion.includes('-dev.') && isFunction(config.sys.checkVersion)) {
715
+ return config.sys.checkVersion(config.logger, currentVersion);
716
+ }
717
+ return null;
718
+ };
719
+ const printCheckVersionResults = async (versionChecker) => {
720
+ if (versionChecker) {
721
+ const checkVersionResults = await versionChecker;
722
+ if (isFunction(checkVersionResults)) {
723
+ checkVersionResults();
724
+ }
725
+ }
726
+ };
727
+
728
+ const taskWatch = async (coreCompiler, config) => {
729
+ let devServer = null;
730
+ let exitCode = 0;
731
+ try {
732
+ startupCompilerLog(coreCompiler, config);
733
+ const versionChecker = startCheckVersion(config, coreCompiler.version);
734
+ const compiler = await coreCompiler.createCompiler(config);
735
+ const watcher = await compiler.createWatcher();
736
+ if (config.flags.serve) {
737
+ const devServerPath = config.sys.getDevServerExecutingPath();
738
+ const { start } = await config.sys.dynamicImport(devServerPath);
739
+ devServer = await start(config.devServer, config.logger, watcher);
740
+ }
741
+ config.sys.onProcessInterrupt(() => {
742
+ config.logger.debug(`close watch`);
743
+ compiler && compiler.destroy();
744
+ });
745
+ const rmVersionCheckerLog = watcher.on('buildFinish', async () => {
746
+ // log the version check one time
747
+ rmVersionCheckerLog();
748
+ printCheckVersionResults(versionChecker);
749
+ });
750
+ if (devServer) {
751
+ const rmDevServerLog = watcher.on('buildFinish', () => {
752
+ // log the dev server url one time
753
+ rmDevServerLog();
754
+ config.logger.info(`${config.logger.cyan(devServer.browserUrl)}\n`);
755
+ });
756
+ }
757
+ const closeResults = await watcher.start();
758
+ if (closeResults.exitCode > 0) {
759
+ exitCode = closeResults.exitCode;
760
+ }
761
+ }
762
+ catch (e) {
763
+ exitCode = 1;
764
+ config.logger.error(e);
765
+ }
766
+ if (devServer) {
767
+ await devServer.close();
768
+ }
769
+ if (exitCode > 0) {
770
+ return config.sys.exit(exitCode);
771
+ }
772
+ };
773
+
774
+ const taskBuild = async (coreCompiler, config) => {
775
+ if (config.flags.watch) {
776
+ // watch build
777
+ await taskWatch(coreCompiler, config);
778
+ return;
779
+ }
780
+ // one-time build
781
+ let exitCode = 0;
782
+ try {
783
+ startupCompilerLog(coreCompiler, config);
784
+ const versionChecker = startCheckVersion(config, coreCompiler.version);
785
+ const compiler = await coreCompiler.createCompiler(config);
786
+ const results = await compiler.build();
787
+ await compiler.destroy();
788
+ if (results.hasError) {
789
+ exitCode = 1;
790
+ }
791
+ else if (config.flags.prerender) {
792
+ const prerenderDiagnostics = await runPrerenderTask(coreCompiler, config, results.hydrateAppFilePath, results.componentGraph, null);
793
+ config.logger.printDiagnostics(prerenderDiagnostics);
794
+ if (prerenderDiagnostics.some(d => d.level === 'error')) {
795
+ exitCode = 1;
796
+ }
797
+ }
798
+ await printCheckVersionResults(versionChecker);
799
+ }
800
+ catch (e) {
801
+ exitCode = 1;
802
+ config.logger.error(e);
803
+ }
804
+ if (exitCode > 0) {
805
+ return config.sys.exit(exitCode);
806
+ }
807
+ };
808
+
809
+ const isOutputTargetDocs = (o) => o.type === DOCS_README || o.type === DOCS_JSON || o.type === DOCS_CUSTOM || o.type === DOCS_VSCODE;
810
+ const DOCS_CUSTOM = 'docs-custom';
811
+ const DOCS_JSON = `docs-json`;
812
+ const DOCS_README = `docs-readme`;
813
+ const DOCS_VSCODE = `docs-vscode`;
814
+
815
+ const taskDocs = async (coreCompiler, config) => {
816
+ config.devServer = null;
817
+ config.outputTargets = config.outputTargets.filter(isOutputTargetDocs);
818
+ config.devMode = true;
819
+ startupCompilerLog(coreCompiler, config);
820
+ const compiler = await coreCompiler.createCompiler(config);
821
+ await compiler.build();
822
+ await compiler.destroy();
823
+ };
824
+
825
+ const IS_DENO_ENV = typeof Deno !== 'undefined';
826
+ const IS_NODE_ENV = !IS_DENO_ENV &&
827
+ typeof global !== 'undefined' &&
828
+ typeof require === 'function' &&
829
+ !!global.process &&
830
+ typeof __filename === 'string' &&
831
+ (!global.origin || typeof global.origin !== 'string');
832
+
833
+ /**
834
+ * Task to generate component boilerplate.
835
+ */
836
+ const taskGenerate = async (coreCompiler, config) => {
837
+ if (!IS_NODE_ENV) {
838
+ config.logger.error(`"generate" command is currently only implemented for a NodeJS environment`);
839
+ return config.sys.exit(1);
840
+ }
841
+ const path = coreCompiler.path;
842
+ if (!config.configPath) {
843
+ config.logger.error('Please run this command in your root directory (i. e. the one containing rindo.config.ts).');
844
+ return config.sys.exit(1);
845
+ }
846
+ const absoluteSrcDir = config.srcDir;
847
+ if (!absoluteSrcDir) {
848
+ config.logger.error(`Rindo's srcDir was not specified.`);
849
+ return config.sys.exit(1);
850
+ }
851
+ const { prompt } = await import('../sys/node/prompts.js');
852
+ const input = config.flags.unknownArgs.find(arg => !arg.startsWith('-')) ||
853
+ (await prompt({ name: 'tagName', type: 'text', message: 'Component tag name (dash-case):' })).tagName;
854
+ const { dir, base: componentName } = path.parse(input);
855
+ const tagError = validateComponentTag(componentName);
856
+ if (tagError) {
857
+ config.logger.error(tagError);
858
+ return config.sys.exit(1);
859
+ }
860
+ const extensionsToGenerate = ['tsx', ...(await chooseFilesToGenerate())];
861
+ const testFolder = extensionsToGenerate.some(isTest) ? 'test' : '';
862
+ const outDir = path.join(absoluteSrcDir, 'components', dir, componentName);
863
+ await config.sys.createDir(path.join(outDir, testFolder), { recursive: true });
864
+ const writtenFiles = await Promise.all(extensionsToGenerate.map(extension => writeFileByExtension(coreCompiler, config, outDir, componentName, extension, extensionsToGenerate.includes('css')))).catch(error => config.logger.error(error));
865
+ if (!writtenFiles) {
866
+ return config.sys.exit(1);
867
+ }
868
+ console.log();
869
+ console.log(`${config.logger.gray('$')} rindo generate ${input}`);
870
+ console.log();
871
+ console.log(config.logger.bold('The following files have been generated:'));
872
+ const absoluteRootDir = config.rootDir;
873
+ writtenFiles.map(file => console.log(` - ${path.relative(absoluteRootDir, file)}`));
874
+ };
875
+ /**
876
+ * Show a checkbox prompt to select the files to be generated.
877
+ */
878
+ const chooseFilesToGenerate = async () => {
879
+ const { prompt } = await import('../sys/node/prompts.js');
880
+ return (await prompt({
881
+ name: 'filesToGenerate',
882
+ type: 'multiselect',
883
+ message: 'Which additional files do you want to generate?',
884
+ choices: [
885
+ { value: 'css', title: 'Stylesheet (.css)', selected: true },
886
+ { value: 'spec.tsx', title: 'Spec Test (.spec.tsx)', selected: true },
887
+ { value: 'e2e.ts', title: 'E2E Test (.e2e.ts)', selected: true },
888
+ ],
889
+ })).filesToGenerate;
890
+ };
891
+ /**
892
+ * Get a file's boilerplate by its extension and write it to disk.
893
+ */
894
+ const writeFileByExtension = async (coreCompiler, config, path, name, extension, withCss) => {
895
+ if (isTest(extension)) {
896
+ path = coreCompiler.path.join(path, 'test');
897
+ }
898
+ const outFile = coreCompiler.path.join(path, `${name}.${extension}`);
899
+ const boilerplate = getBoilerplateByExtension(name, extension, withCss);
900
+ await config.sys.writeFile(outFile, boilerplate);
901
+ return outFile;
902
+ };
903
+ const isTest = (extension) => {
904
+ return extension === 'e2e.ts' || extension === 'spec.tsx';
905
+ };
906
+ /**
907
+ * Get the boilerplate for a file by its extension.
908
+ */
909
+ const getBoilerplateByExtension = (tagName, extension, withCss) => {
910
+ switch (extension) {
911
+ case 'tsx':
912
+ return getComponentBoilerplate(tagName, withCss);
913
+ case 'css':
914
+ return getStyleUrlBoilerplate();
915
+ case 'spec.tsx':
916
+ return getSpecTestBoilerplate(tagName);
917
+ case 'e2e.ts':
918
+ return getE2eTestBoilerplate(tagName);
919
+ default:
920
+ throw new Error(`Unkown extension "${extension}".`);
921
+ }
922
+ };
923
+ /**
924
+ * Get the boilerplate for a component.
925
+ */
926
+ const getComponentBoilerplate = (tagName, hasStyle) => {
927
+ const decorator = [`{`];
928
+ decorator.push(` tag: '${tagName}',`);
929
+ if (hasStyle) {
930
+ decorator.push(` styleUrl: '${tagName}.css',`);
931
+ }
932
+ decorator.push(` shadow: true,`);
933
+ decorator.push(`}`);
934
+ return `import { Component, Host, h } from '@rindo/core';
935
+
936
+ @Component(${decorator.join('\n')})
937
+ export class ${toPascalCase(tagName)} {
938
+
939
+ render() {
940
+ return (
941
+ <Host>
942
+ <slot></slot>
943
+ </Host>
944
+ );
124
945
  }
125
- });
126
- }, configCase = e => (e = dashToPascalCase(e)).charAt(0).toLowerCase() + e.substr(1), ARG_OPTS = {
127
- boolean: [ "build", "cache", "check-version", "ci", "compare", "debug", "dev", "devtools", "docs", "e2e", "es5", "esm", "headless", "help", "log", "open", "prerender", "prerender-external", "prod", "profile", "service-worker", "screenshot", "serve", "skip-node-check", "spec", "stats", "update-screenshot", "verbose", "version", "watch" ],
128
- number: [ "max-workers", "port" ],
129
- string: [ "address", "config", "docs-json", "emulate", "log-level", "root", "screenshot-connector" ],
130
- alias: {
131
- config: "c",
132
- help: "h",
133
- port: "p",
134
- version: "v"
135
- }
136
- }, getNpmConfigEnvArgs = e => {
137
- let t = [];
138
- try {
139
- const s = e.getEnvironmentVar("npm_config_argv");
140
- s && (t = JSON.parse(s).original, "run" === t[0] && (t = t.slice(2)));
141
- } catch (e) {}
142
- return t;
143
- }, dependencies = [ {
144
- name: "@rindo/core",
145
- version: "0.0.0-dev.20221104122636",
146
- main: "compiler/rindo.js",
147
- resources: [ "internal/index.js", "internal/index.d.ts", "internal/package.json", "internal/rindo-core/index.js", "internal/rindo-core/index.d.ts", "internal/rindo-ext-modules.d.ts", "internal/rindo-private.d.ts", "internal/rindo-public-compiler.d.ts", "internal/rindo-public-docs.d.ts", "internal/rindo-public-runtime.d.ts", "internal/client/css-shim.js", "internal/client/dom.js", "internal/client/index.js", "internal/client/patch.js", "internal/client/shadow-css.js", "internal/client/package.json", "internal/hydrate/index.js", "internal/hydrate/runner.js", "internal/hydrate/shadow-css.js", "internal/hydrate/package.json", "mock-doc/index.js", "mock-doc/package.json", "package.json" ]
148
- }, {
149
- name: "typescript",
150
- version: "3.9.7",
151
- main: "lib/typescript.js",
152
- resources: [ "lib/lib.dom.d.ts", "lib/lib.es2015.d.ts", "lib/lib.es5.d.ts", "lib/lib.es2015.core.d.ts", "lib/lib.es2015.collection.d.ts", "lib/lib.es2015.generator.d.ts", "lib/lib.es2015.iterable.d.ts", "lib/lib.es2015.symbol.d.ts", "lib/lib.es2015.promise.d.ts", "lib/lib.es2015.proxy.d.ts", "lib/lib.es2015.reflect.d.ts", "lib/lib.es2015.symbol.wellknown.d.ts", "lib/lib.es2016.d.ts", "lib/lib.es2016.array.include.d.ts", "lib/lib.es2017.d.ts", "lib/lib.es2017.typedarrays.d.ts", "lib/lib.es2017.intl.d.ts", "lib/lib.es2017.object.d.ts", "lib/lib.es2017.sharedmemory.d.ts", "lib/lib.es2017.string.d.ts", "lib/lib.es2018.d.ts", "lib/lib.es2018.asyncgenerator.d.ts", "lib/lib.es2018.asynciterable.d.ts", "lib/lib.es2018.promise.d.ts", "lib/lib.es2018.regexp.d.ts", "lib/lib.es2018.intl.d.ts", "lib/lib.esnext.intl.d.ts", "lib/lib.es2020.bigint.d.ts", "package.json" ]
153
- }, {
154
- name: "rollup",
155
- version: "2.23.0",
156
- main: "dist/rollup.browser.es.js"
157
- }, {
158
- name: "terser",
159
- version: "4.8.0",
160
- main: "dist/bundle.min.js"
161
- } ], startupCompilerLog = (e, t) => {
162
- if (!0 === t.suppressLogs) return;
163
- const {logger: s} = t, n = "debug" === s.getLevel(), r = e.version.includes("-"), o = e.version.includes("-dev.");
164
- r && !o && s.warn(s.yellow("This is a prerelease build, undocumented changes might happen at any time. Technical support is not available for prereleases, but any assistance testing is appreciated.")),
165
- t.devMode && !n && (t.buildEs5 && s.warn("Generating ES5 during development is a very task expensive, initial and incremental builds will be much slower. Drop the '--es5' flag and use a modern browser for development."),
166
- t.enableCache || s.warn("Disabling cache during development will slow down incremental builds."));
167
- }, runPrerenderTask = async (e, t, s, n, r) => {
168
- const o = [];
169
- try {
170
- const i = await e.createPrerenderer(t), a = await i.start({
171
- hydrateAppFilePath: s,
172
- componentGraph: n,
173
- srcIndexHtmlPath: r
174
- });
175
- o.push(...a.diagnostics);
176
- } catch (e) {
177
- ((e, t, s) => {
178
- const n = {
179
- level: "error",
180
- type: "build",
181
- header: "Build Error",
182
- messageText: "build error",
183
- relFilePath: null,
184
- absFilePath: null,
185
- lines: []
186
- };
187
- isString(void 0) ? n.messageText = void 0 : null != t && (null != t.stack ? n.messageText = t.stack.toString() : null != t.message ? n.messageText = t.message.toString() : n.messageText = t.toString()),
188
- null == e || shouldIgnoreError(n.messageText) || e.push(n);
189
- })(o, e);
190
- }
191
- return o;
192
- }, startCheckVersion = async (e, t) => e.devMode && !e.flags.ci && !t.includes("-dev.") && isFunction(e.sys.checkVersion) ? e.sys.checkVersion(e.logger, t) : null, printCheckVersionResults = async e => {
193
- if (e) {
194
- const t = await e;
195
- isFunction(t) && t();
196
- }
197
- }, isOutputTargetDocs = e => e.type === DOCS || e.type === DOCS_README || e.type === DOCS_JSON || e.type === DOCS_CUSTOM || e.type === DOCS_VSCODE, DOCS = "docs", DOCS_CUSTOM = "docs-custom", DOCS_JSON = "docs-json", DOCS_README = "docs-readme", DOCS_VSCODE = "docs-vscode", chooseFilesToGenerate = async () => {
198
- const {prompt: e} = await import("../sys/node/prompts.js");
199
- return (await e({
200
- name: "filesToGenerate",
201
- type: "multiselect",
202
- message: "Which additional files do you want to generate?",
203
- choices: [ {
204
- value: "css",
205
- title: "Stylesheet (.css)",
206
- selected: !0
207
- }, {
208
- value: "spec.tsx",
209
- title: "Spec Test (.spec.tsx)",
210
- selected: !0
211
- }, {
212
- value: "e2e.ts",
213
- title: "E2E Test (.e2e.ts)",
214
- selected: !0
215
- } ]
216
- })).filesToGenerate;
217
- }, isTest = e => "e2e.ts" === e || "spec.tsx" === e, getBoilerplateByExtension = (e, t, s) => {
218
- switch (t) {
219
- case "tsx":
220
- return getComponentBoilerplate(e, s);
221
-
222
- case "css":
223
- return getStyleUrlBoilerplate();
224
-
225
- case "spec.tsx":
226
- return getSpecTestBoilerplate(e);
227
-
228
- case "e2e.ts":
229
- return getE2eTestBoilerplate(e);
230
-
231
- default:
232
- throw new Error(`Unkown extension "${t}".`);
233
- }
234
- }, getComponentBoilerplate = (e, t) => {
235
- const s = [ "{" ];
236
- return s.push(` tag: '${e}',`), t && s.push(` styleUrl: '${e}.css',`), s.push(" shadow: true,"),
237
- s.push("}"), `import { Component, Host, h } from '@rindo/core';\n\n@Component(${s.join("\n")})\nexport class ${toPascalCase(e)} {\n\n render() {\n return (\n <Host>\n <slot></slot>\n </Host>\n );\n }\n\n}\n`;
238
- }, getStyleUrlBoilerplate = () => ":host {\n display: block;\n}\n", getSpecTestBoilerplate = e => `import { newSpecPage } from '@rindo/core/testing';\nimport { ${toPascalCase(e)} } from '../${e}';\n\ndescribe('${e}', () => {\n it('renders', async () => {\n const page = await newSpecPage({\n components: [${toPascalCase(e)}],\n html: \`<${e}></${e}>\`,\n });\n expect(page.root).toEqualHtml(\`\n <${e}>\n <mock:shadow-root>\n <slot></slot>\n </mock:shadow-root>\n </${e}>\n \`);\n });\n});\n`, getE2eTestBoilerplate = e => `import { newE2EPage } from '@rindo/core/testing';\n\ndescribe('${e}', () => {\n it('renders', async () => {\n const page = await newE2EPage();\n await page.setContent('<${e}></${e}>');\n\n const element = await page.find('${e}');\n expect(element).toHaveClass('hydrated');\n });\n});\n`, toPascalCase = e => e.split("-").reduce((e, t) => e + t[0].toUpperCase() + t.substr(1), ""), taskHelp = (e, t) => {
239
- const s = t.dim("windows" === e.details.platform ? ">" : "$");
240
- console.log(`\n ${t.bold("Build:")} ${t.dim("Build components for development or production.")}\n\n ${s} ${t.green("rindo build [--dev] [--watch] [--prerender] [--debug]")}\n\n ${t.cyan("--dev")} ${t.dim(".............")} Development build\n ${t.cyan("--watch")} ${t.dim("...........")} Rebuild when files update\n ${t.cyan("--serve")} ${t.dim("...........")} Start the dev-server\n ${t.cyan("--prerender")} ${t.dim(".......")} Prerender the application\n ${t.cyan("--docs")} ${t.dim("............")} Generate component readme.md docs\n ${t.cyan("--config")} ${t.dim("..........")} Set rindo config file\n ${t.cyan("--stats")} ${t.dim("...........")} Write rindo-stats.json file\n ${t.cyan("--log")} ${t.dim(".............")} Write rindo-build.log file\n ${t.cyan("--debug")} ${t.dim("...........")} Set the log level to debug\n\n\n ${t.bold("Test:")} ${t.dim("Run unit and end-to-end tests.")}\n\n ${s} ${t.green("rindo test [--spec] [--e2e]")}\n\n ${t.cyan("--spec")} ${t.dim("............")} Run unit tests with Jest\n ${t.cyan("--e2e")} ${t.dim(".............")} Run e2e tests with Puppeteer\n\n\n ${t.bold("Generate:")} ${t.dim("Bootstrap components.")}\n\n ${s} ${t.green("rindo generate")} or ${t.green("rindo g")}\n\n\n ${t.bold("Examples:")}\n\n ${s} ${t.green("rindo build --dev --watch --serve")}\n ${s} ${t.green("rindo build --prerender")}\n ${s} ${t.green("rindo test --spec --e2e")}\n ${s} ${t.green("rindo generate")}\n ${s} ${t.green("rindo g my-component")}\n\n`);
241
- }, run = async e => {
242
- const {args: t, logger: s, sys: n} = e;
243
- try {
244
- const e = parseFlags(t, n), r = e.task;
245
- if ((e.debug || e.verbose) && s.setLevel("debug"), e.ci && s.enableColors(!1), isFunction(n.applyGlobalPatch) && n.applyGlobalPatch(n.getCurrentDirectory()),
246
- "help" === r || e.help) return void taskHelp(n, s);
247
- ((e, t) => {
248
- "info" !== t && "serve" !== t && "version" !== t && e.info(e.cyan("@rindo/core"));
249
- })(s, r);
250
- const o = await (async e => {
251
- const t = e.sys, s = t.getCurrentDirectory(), n = {
252
- configPath: null,
253
- rootDir: normalizePath(s),
254
- diagnostics: []
255
- };
256
- let r = e.configPath;
257
- r = isString(r) ? t.platformPath.isAbsolute(r) ? normalizePath(e.configPath) : normalizePath(t.platformPath.join(s, r)) : n.rootDir;
258
- const o = await t.stat(r);
259
- if (!o) {
260
- const e = (e => {
261
- const t = {
262
- level: "error",
263
- type: "build",
264
- header: "Build Error",
265
- messageText: "build error",
266
- relFilePath: null,
267
- absFilePath: null,
268
- lines: []
269
- };
270
- return e && e.push(t), t;
271
- })(n.diagnostics);
272
- return e.absFilePath = r, e.header = "Invalid config path", e.messageText = `Config path "${r}" not found`,
273
- n;
274
- }
275
- if (o.isFile()) n.configPath = r, n.rootDir = t.platformPath.dirname(r); else if (o.isDirectory()) for (const e of [ "rindo.config.ts", "rindo.config.js" ]) {
276
- const s = t.platformPath.join(r, e), o = await t.stat(s);
277
- if (o && o.isFile()) {
278
- n.configPath = s, n.rootDir = t.platformPath.dirname(s);
279
- break;
280
- }
281
- }
282
- return n;
283
- })({
284
- sys: n,
285
- configPath: e.config
286
- });
287
- hasError(o.diagnostics) && (s.printDiagnostics(o.diagnostics), n.exit(1));
288
- const i = await n.ensureDependencies({
289
- rootDir: o.rootDir,
290
- logger: s,
291
- dependencies
946
+
947
+ }
948
+ `;
949
+ };
950
+ /**
951
+ * Get the boilerplate for style.
952
+ */
953
+ const getStyleUrlBoilerplate = () => `:host {
954
+ display: block;
955
+ }
956
+ `;
957
+ /**
958
+ * Get the boilerplate for a spec test.
959
+ */
960
+ const getSpecTestBoilerplate = (tagName) => `import { newSpecPage } from '@rindo/core/testing';
961
+ import { ${toPascalCase(tagName)} } from '../${tagName}';
962
+
963
+ describe('${tagName}', () => {
964
+ it('renders', async () => {
965
+ const page = await newSpecPage({
966
+ components: [${toPascalCase(tagName)}],
967
+ html: \`<${tagName}></${tagName}>\`,
968
+ });
969
+ expect(page.root).toEqualHtml(\`
970
+ <${tagName}>
971
+ <mock:shadow-root>
972
+ <slot></slot>
973
+ </mock:shadow-root>
974
+ </${tagName}>
975
+ \`);
292
976
  });
293
- hasError(i.diagnostics) && (s.printDiagnostics(i.diagnostics), n.exit(1));
294
- const a = await (async e => (await e.dynamicImport(e.getCompilerExecutingPath()),
295
- globalThis.rindo))(n);
296
- if ("version" === r || e.version) return void console.log(a.version);
297
- if (((e, t, s) => {
298
- if ("info" === t || "serve" === t || "version" === t) return;
299
- let n;
300
- n = s.version.includes("-dev.") ? e.yellow("[LOCAL DEV]") : e.cyan("v" + s.version),
301
- n += e.emoji(" " + s.vermoji), e.info(n);
302
- })(s, r, a), ((e, t, s, n) => {
303
- const r = e.details, o = `${e.name} ${e.version}`, i = `${r.platform}, ${r.cpuModel}`, a = `cpus: ${e.hardwareConcurrency}, freemem: ${Math.round(r.freemem() / 1e6)}MB, totalmem: ${Math.round(r.totalmem / 1e6)}MB`;
304
- "debug" === t.getLevel() ? (t.debug(o), t.debug(i), t.debug(a), t.debug("compiler: " + e.getCompilerExecutingPath()),
305
- t.debug("build: " + n.buildId)) : s.ci && (t.info(o), t.info(i), t.info(a));
306
- })(n, s, e, a), "info" === r) return void ((e, t, s) => {
307
- const n = t.details, r = e.versions;
308
- console.log(""), console.log(`${s.cyan(" System:")} ${t.name} ${t.version}`),
309
- console.log(`${s.cyan(" Plaform:")} ${n.platform} (${n.release})`), console.log(`${s.cyan(" CPU Model:")} ${n.cpuModel} (${t.hardwareConcurrency} cpu${1 !== t.hardwareConcurrency ? "s" : ""})`),
310
- console.log(`${s.cyan(" Compiler:")} ${t.getCompilerExecutingPath()}`), console.log(`${s.cyan(" Build:")} ${e.buildId}`),
311
- console.log(`${s.cyan(" Rindo:")} ${e.version}${s.emoji(" " + e.vermoji)}`),
312
- console.log(`${s.cyan(" TypeScript:")} ${r.typescript}`), console.log(`${s.cyan(" Rollup:")} ${r.rollup}`),
313
- console.log(`${s.cyan(" Terser:")} ${r.terser}`), console.log("");
314
- })(a, n, s);
315
- const l = await a.loadConfig({
316
- config: {
317
- flags: e
318
- },
319
- configPath: o.configPath,
320
- logger: s,
321
- sys: n,
322
- typescriptPath: i.typescriptPath
977
+ });
978
+ `;
979
+ /**
980
+ * Get the boilerplate for an E2E test.
981
+ */
982
+ const getE2eTestBoilerplate = (name) => `import { newE2EPage } from '@rindo/core/testing';
983
+
984
+ describe('${name}', () => {
985
+ it('renders', async () => {
986
+ const page = await newE2EPage();
987
+ await page.setContent('<${name}></${name}>');
988
+
989
+ const element = await page.find('${name}');
990
+ expect(element).toHaveClass('hydrated');
323
991
  });
324
- l.diagnostics.length > 0 && (s.printDiagnostics(l.diagnostics), hasError(l.diagnostics) && n.exit(1)),
325
- isFunction(n.applyGlobalPatch) && n.applyGlobalPatch(l.config.rootDir), await n.ensureResources({
326
- rootDir: l.config.rootDir,
327
- logger: s,
328
- dependencies
329
- }), await runTask(a, l.config, r);
330
- } catch (e) {
331
- shouldIgnoreError(e) || (s.error(`uncaught cli error: ${e}${"debug" === s.getLevel() ? e.stack : ""}`),
332
- n.exit(1));
333
- }
334
- }, runTask = async (e, t, s) => {
335
- switch (t.flags = t.flags || {}, t.outputTargets = t.outputTargets || [], s) {
336
- case "build":
337
- await (async (e, t) => {
338
- if (t.flags.watch) return void await (async (e, t) => {
339
- let s = null, n = 0;
340
- try {
341
- startupCompilerLog(e, t);
342
- const r = startCheckVersion(t, e.version), o = await e.createCompiler(t), i = await o.createWatcher();
343
- if (t.flags.serve) {
344
- const e = t.sys.getDevServerExecutingPath(), {start: n} = await t.sys.dynamicImport(e);
345
- s = await n(t.devServer, t.logger, i);
346
- }
347
- t.sys.onProcessInterrupt(() => {
348
- t.logger.debug("close watch"), o && o.destroy();
349
- });
350
- const a = i.on("buildFinish", async () => {
351
- a(), printCheckVersionResults(r);
352
- });
353
- if (s) {
354
- const e = i.on("buildFinish", () => {
355
- e(), t.logger.info(t.logger.cyan(s.browserUrl) + "\n");
356
- });
357
- }
358
- t.flags.prerender && i.on("buildFinish", async s => {
359
- if (!s.hasError) {
360
- const n = await runPrerenderTask(e, t, s.hydrateAppFilePath, s.componentGraph, null);
361
- t.logger.printDiagnostics(n);
362
- }
363
- });
364
- const l = await i.start();
365
- l.exitCode > 0 && (n = l.exitCode);
366
- } catch (e) {
367
- n = 1, t.logger.error(e);
368
- }
369
- s && await s.close(), n > 0 && t.sys.exit(n);
370
- })(e, t);
371
- let s = 0;
372
- try {
373
- startupCompilerLog(e, t);
374
- const n = startCheckVersion(t, e.version), r = await e.createCompiler(t), o = await r.build();
375
- if (await r.destroy(), o.hasError) s = 1; else if (t.flags.prerender) {
376
- const n = await runPrerenderTask(e, t, o.hydrateAppFilePath, o.componentGraph, null);
377
- t.logger.printDiagnostics(n), n.some(e => "error" === e.level) && (s = 1);
378
- }
379
- await printCheckVersionResults(n);
380
- } catch (e) {
381
- s = 1, t.logger.error(e);
382
- }
383
- s > 0 && t.sys.exit(s);
384
- })(e, t);
385
- break;
386
-
387
- case "docs":
388
- await (async (e, t) => {
389
- t.devServer = null, t.outputTargets = t.outputTargets.filter(isOutputTargetDocs),
390
- t.devMode = !0, startupCompilerLog(e, t);
391
- const s = await e.createCompiler(t);
392
- await s.build(), await s.destroy();
393
- })(e, t);
394
- break;
395
-
396
- case "help":
397
- taskHelp(t.sys, t.logger);
398
- break;
399
-
400
- case "generate":
401
- case "g":
402
- await (async (e, t) => {
403
- IS_NODE_ENV || (t.logger.error('"generate" command is currently only implemented for a NodeJS environment'),
404
- t.sys.exit(1));
405
- const s = e.path;
406
- t.configPath || (t.logger.error("Please run this command in your root directory (i. e. the one containing rindo.config.ts)."),
407
- t.sys.exit(1));
408
- const n = t.srcDir;
409
- n || (t.logger.error("Rindo's srcDir was not specified."), t.sys.exit(1));
410
- const {prompt: r} = await import("../sys/node/prompts.js"), o = t.flags.unknownArgs.find(e => !e.startsWith("-")) || (await r({
411
- name: "tagName",
412
- type: "text",
413
- message: "Component tag name (dash-case):"
414
- })).tagName, {dir: i, base: a} = s.parse(o), l = (e => {
415
- if (e !== e.trim()) return "Tag can not contain white spaces";
416
- if (e !== e.toLowerCase()) return "Tag can not contain upper case characters";
417
- if ("string" != typeof e) return `Tag "${e}" must be a string type`;
418
- if (0 === e.length) return "Received empty tag value";
419
- if (e.indexOf(" ") > -1) return `"${e}" tag cannot contain a space`;
420
- if (e.indexOf(",") > -1) return `"${e}" tag cannot be used for multiple tags`;
421
- const t = e.replace(/\w|-/g, "");
422
- return "" !== t ? `"${e}" tag contains invalid characters: ${t}` : -1 === e.indexOf("-") ? `"${e}" tag must contain a dash (-) to work as a valid web component` : e.indexOf("--") > -1 ? `"${e}" tag cannot contain multiple dashes (--) next to each other` : 0 === e.indexOf("-") ? `"${e}" tag cannot start with a dash (-)` : e.lastIndexOf("-") === e.length - 1 ? `"${e}" tag cannot end with a dash (-)` : void 0;
423
- })(a);
424
- l && (t.logger.error(l), t.sys.exit(1));
425
- const c = [ "tsx", ...await chooseFilesToGenerate() ], d = c.some(isTest) ? "test" : "", g = s.join(n, "components", i, a);
426
- await t.sys.mkdir(s.join(g, d), {
427
- recursive: !0
428
- });
429
- const p = await Promise.all(c.map(s => (async (e, t, s, n, r, o) => {
430
- isTest(r) && (s = e.path.join(s, "test"));
431
- const i = e.path.join(s, `${n}.${r}`), a = getBoilerplateByExtension(n, r, o);
432
- return await t.sys.writeFile(i, a), i;
433
- })(e, t, g, a, s, c.includes("css")))).catch(e => t.logger.error(e));
434
- if (!p) return t.sys.exit(1);
435
- console.log(), console.log(`${t.logger.gray("$")} rindo generate ${o}`), console.log(),
436
- console.log(t.logger.bold("The following files have been generated:"));
437
- const u = t.rootDir;
438
- p.map(e => console.log(" - " + s.relative(u, e)));
439
- })(e, t);
440
- break;
441
-
442
- case "prerender":
443
- await (async (e, t) => {
444
- startupCompilerLog(e, t);
445
- const s = t.flags.unknownArgs[0];
446
- "string" != typeof s && (t.logger.error("Missing hydrate app script path"), t.sys.exit(1));
447
- const n = t.srcIndexHtml, r = await runPrerenderTask(e, t, s, null, n);
448
- t.logger.printDiagnostics(r), r.some(e => "error" === e.level) && t.sys.exit(1);
449
- })(e, t);
450
- break;
451
-
452
- case "serve":
453
- await (async e => {
454
- e.suppressLogs = !0, e.flags.serve = !0, e.devServer.openBrowser = e.flags.open,
455
- e.devServer.reloadStrategy = null, e.devServer.initialLoadUrl = "/", e.devServer.websocket = !1,
456
- e.maxConcurrentWorkers = 1, e.devServer.root = isString(e.flags.root) ? e.flags.root : e.sys.getCurrentDirectory();
457
- const t = e.sys.getDevServerExecutingPath(), {start: s} = await e.sys.dynamicImport(t), n = await s(e.devServer, e.logger);
458
- console.log(`${e.logger.cyan(" Root:")} ${n.root}`), console.log(`${e.logger.cyan(" Address:")} ${n.address}`),
459
- console.log(`${e.logger.cyan(" Port:")} ${n.port}`), console.log(`${e.logger.cyan(" Server:")} ${n.browserUrl}`),
460
- console.log(""), e.sys.onProcessInterrupt(() => {
461
- n && (e.logger.debug("dev server close: " + n.browserUrl), n.close());
462
- });
463
- })(t);
464
- break;
465
-
466
- case "test":
467
- await (async e => {
468
- IS_NODE_ENV || (e.logger.error('"test" command is currently only implemented for a NodeJS environment'),
469
- e.sys.exit(1));
470
- try {
471
- const t = {
472
- e2e: !!e.flags.e2e,
473
- screenshot: !!e.flags.screenshot,
474
- spec: !!e.flags.spec,
475
- updateScreenshot: !!e.flags.updateScreenshot
476
- }, s = [ "@types/jest", "jest", "jest-cli" ];
477
- if (t.e2e) {
478
- const n = e.testing.browserExecutablePath ? "puppeteer-core" : "puppeteer";
479
- s.push("@types/puppeteer", n), t.screenshot && e.logger.warn(e.logger.yellow("EXPERIMENTAL: screenshot visual diff testing is currently under heavy development and has not reached a stable status. However, any assistance testing would be appreciated."));
480
- }
481
- await e.sys.lazyRequire.ensure(e.logger, e.rootDir, s);
482
- const {createTesting: n} = await import("../testing/index.js"), r = await n(e), o = await r.run(t);
483
- await r.destroy(), o || e.sys.exit(1);
484
- } catch (t) {
485
- e.logger.error(t), e.sys.exit(1);
486
- }
487
- })(t);
488
- break;
489
-
490
- case "version":
491
- console.log(e.version);
492
- break;
493
-
494
- default:
495
- t.logger.error(t.logger.emoji("❌ ") + "Invalid rindo command, please see the options below:"),
496
- taskHelp(t.sys, t.logger), t.sys.exit(1);
497
- }
992
+ });
993
+ `;
994
+ /**
995
+ * Convert a dash case string to pascal case.
996
+ */
997
+ const toPascalCase = (str) => str.split('-').reduce((res, part) => res + part[0].toUpperCase() + part.substr(1), '');
998
+
999
+ const taskHelp = (sys, logger) => {
1000
+ const p = logger.dim(sys.details.platform === 'windows' ? '>' : '$');
1001
+ console.log(`
1002
+ ${logger.bold('Build:')} ${logger.dim('Build components for development or production.')}
1003
+
1004
+ ${p} ${logger.green('rindo build [--dev] [--watch] [--prerender] [--debug]')}
1005
+
1006
+ ${logger.cyan('--dev')} ${logger.dim('.............')} Development build
1007
+ ${logger.cyan('--watch')} ${logger.dim('...........')} Rebuild when files update
1008
+ ${logger.cyan('--serve')} ${logger.dim('...........')} Start the dev-server
1009
+ ${logger.cyan('--prerender')} ${logger.dim('.......')} Prerender the application
1010
+ ${logger.cyan('--docs')} ${logger.dim('............')} Generate component readme.md docs
1011
+ ${logger.cyan('--config')} ${logger.dim('..........')} Set rindo config file
1012
+ ${logger.cyan('--stats')} ${logger.dim('...........')} Write rindo-stats.json file
1013
+ ${logger.cyan('--log')} ${logger.dim('.............')} Write rindo-build.log file
1014
+ ${logger.cyan('--debug')} ${logger.dim('...........')} Set the log level to debug
1015
+
1016
+
1017
+ ${logger.bold('Test:')} ${logger.dim('Run unit and end-to-end tests.')}
1018
+
1019
+ ${p} ${logger.green('rindo test [--spec] [--e2e]')}
1020
+
1021
+ ${logger.cyan('--spec')} ${logger.dim('............')} Run unit tests with Jest
1022
+ ${logger.cyan('--e2e')} ${logger.dim('.............')} Run e2e tests with Puppeteer
1023
+
1024
+
1025
+ ${logger.bold('Generate:')} ${logger.dim('Bootstrap components.')}
1026
+
1027
+ ${p} ${logger.green('rindo generate')} or ${logger.green('rindo g')}
1028
+
1029
+
1030
+ ${logger.bold('Examples:')}
1031
+
1032
+ ${p} ${logger.green('rindo build --dev --watch --serve')}
1033
+ ${p} ${logger.green('rindo build --prerender')}
1034
+ ${p} ${logger.green('rindo test --spec --e2e')}
1035
+ ${p} ${logger.green('rindo generate')}
1036
+ ${p} ${logger.green('rindo g my-component')}
1037
+
1038
+ `);
1039
+ };
1040
+
1041
+ const taskInfo = (coreCompiler, sys, logger) => {
1042
+ const details = sys.details;
1043
+ const versions = coreCompiler.versions;
1044
+ console.log(``);
1045
+ console.log(`${logger.cyan(' System:')} ${sys.name} ${sys.version}`);
1046
+ console.log(`${logger.cyan(' Plaform:')} ${details.platform} (${details.release})`);
1047
+ console.log(`${logger.cyan(' CPU Model:')} ${details.cpuModel} (${sys.hardwareConcurrency} cpu${sys.hardwareConcurrency !== 1 ? 's' : ''})`);
1048
+ console.log(`${logger.cyan(' Compiler:')} ${sys.getCompilerExecutingPath()}`);
1049
+ console.log(`${logger.cyan(' Build:')} ${coreCompiler.buildId}`);
1050
+ console.log(`${logger.cyan(' Rindo:')} ${coreCompiler.version}${logger.emoji(' ' + coreCompiler.vermoji)}`);
1051
+ console.log(`${logger.cyan(' TypeScript:')} ${versions.typescript}`);
1052
+ console.log(`${logger.cyan(' Rollup:')} ${versions.rollup}`);
1053
+ console.log(`${logger.cyan(' Parse5:')} ${versions.parse5}`);
1054
+ console.log(`${logger.cyan(' Sizzle:')} ${versions.sizzle}`);
1055
+ console.log(`${logger.cyan(' Terser:')} ${versions.terser}`);
1056
+ console.log(``);
1057
+ };
1058
+
1059
+ const taskServe = async (config) => {
1060
+ config.suppressLogs = true;
1061
+ config.flags.serve = true;
1062
+ config.devServer.openBrowser = config.flags.open;
1063
+ config.devServer.reloadStrategy = null;
1064
+ config.devServer.initialLoadUrl = '/';
1065
+ config.devServer.websocket = false;
1066
+ config.maxConcurrentWorkers = 1;
1067
+ config.devServer.root = isString(config.flags.root) ? config.flags.root : config.sys.getCurrentDirectory();
1068
+ const devServerPath = config.sys.getDevServerExecutingPath();
1069
+ const { start } = await config.sys.dynamicImport(devServerPath);
1070
+ const devServer = await start(config.devServer, config.logger);
1071
+ console.log(`${config.logger.cyan(' Root:')} ${devServer.root}`);
1072
+ console.log(`${config.logger.cyan(' Address:')} ${devServer.address}`);
1073
+ console.log(`${config.logger.cyan(' Port:')} ${devServer.port}`);
1074
+ console.log(`${config.logger.cyan(' Server:')} ${devServer.browserUrl}`);
1075
+ console.log(``);
1076
+ config.sys.onProcessInterrupt(() => {
1077
+ if (devServer) {
1078
+ config.logger.debug(`dev server close: ${devServer.browserUrl}`);
1079
+ devServer.close();
1080
+ }
1081
+ });
1082
+ };
1083
+
1084
+ const taskTest = async (config) => {
1085
+ if (!IS_NODE_ENV) {
1086
+ config.logger.error(`"test" command is currently only implemented for a NodeJS environment`);
1087
+ return config.sys.exit(1);
1088
+ }
1089
+ try {
1090
+ config.buildDocs = false;
1091
+ const testingRunOpts = {
1092
+ e2e: !!config.flags.e2e,
1093
+ screenshot: !!config.flags.screenshot,
1094
+ spec: !!config.flags.spec,
1095
+ updateScreenshot: !!config.flags.updateScreenshot,
1096
+ };
1097
+ // always ensure we have jest modules installed
1098
+ const ensureModuleIds = ['@types/jest', 'jest', 'jest-cli'];
1099
+ if (testingRunOpts.e2e) {
1100
+ // if it's an e2e test, also make sure we're got
1101
+ // puppeteer modules installed and if browserExecutablePath is provided don't download Chromium use only puppeteer-core instead
1102
+ const puppeteer = config.testing.browserExecutablePath ? 'puppeteer-core' : 'puppeteer';
1103
+ ensureModuleIds.push('@types/puppeteer', puppeteer);
1104
+ if (testingRunOpts.screenshot) {
1105
+ // ensure we've got pixelmatch for screenshots
1106
+ config.logger.warn(config.logger.yellow(`EXPERIMENTAL: screenshot visual diff testing is currently under heavy development and has not reached a stable status. However, any assistance testing would be appreciated.`));
1107
+ }
1108
+ }
1109
+ // ensure we've got the required modules installed
1110
+ const diagnostics = await config.sys.lazyRequire.ensure(config.rootDir, ensureModuleIds);
1111
+ if (diagnostics.length > 0) {
1112
+ config.logger.printDiagnostics(diagnostics);
1113
+ return config.sys.exit(1);
1114
+ }
1115
+ // let's test!
1116
+ const { createTesting } = await import('../testing/index.js');
1117
+ const testing = await createTesting(config);
1118
+ const passed = await testing.run(testingRunOpts);
1119
+ await testing.destroy();
1120
+ if (!passed) {
1121
+ return config.sys.exit(1);
1122
+ }
1123
+ }
1124
+ catch (e) {
1125
+ config.logger.error(e);
1126
+ return config.sys.exit(1);
1127
+ }
1128
+ };
1129
+
1130
+ const run = async (init) => {
1131
+ const { args, logger, sys } = init;
1132
+ try {
1133
+ const flags = parseFlags(args, sys);
1134
+ const task = flags.task;
1135
+ if (flags.debug || flags.verbose) {
1136
+ logger.setLevel('debug');
1137
+ }
1138
+ if (flags.ci) {
1139
+ logger.enableColors(false);
1140
+ }
1141
+ if (isFunction(sys.applyGlobalPatch)) {
1142
+ sys.applyGlobalPatch(sys.getCurrentDirectory());
1143
+ }
1144
+ if (task === 'help' || flags.help) {
1145
+ taskHelp(sys, logger);
1146
+ return;
1147
+ }
1148
+ startupLog(logger, task);
1149
+ const findConfigResults = await findConfig({ sys, configPath: flags.config });
1150
+ if (hasError(findConfigResults.diagnostics)) {
1151
+ logger.printDiagnostics(findConfigResults.diagnostics);
1152
+ return sys.exit(1);
1153
+ }
1154
+ const ensureDepsResults = await sys.ensureDependencies({
1155
+ rootDir: findConfigResults.rootDir,
1156
+ logger,
1157
+ dependencies: dependencies,
1158
+ });
1159
+ if (hasError(ensureDepsResults.diagnostics)) {
1160
+ logger.printDiagnostics(ensureDepsResults.diagnostics);
1161
+ return sys.exit(1);
1162
+ }
1163
+ const coreCompiler = await loadCoreCompiler(sys);
1164
+ if (task === 'version' || flags.version) {
1165
+ console.log(coreCompiler.version);
1166
+ return;
1167
+ }
1168
+ startupLogVersion(logger, task, coreCompiler);
1169
+ loadedCompilerLog(sys, logger, flags, coreCompiler);
1170
+ if (task === 'info') {
1171
+ taskInfo(coreCompiler, sys, logger);
1172
+ return;
1173
+ }
1174
+ const validated = await coreCompiler.loadConfig({
1175
+ config: {
1176
+ flags,
1177
+ },
1178
+ configPath: findConfigResults.configPath,
1179
+ logger,
1180
+ sys,
1181
+ });
1182
+ if (validated.diagnostics.length > 0) {
1183
+ logger.printDiagnostics(validated.diagnostics);
1184
+ if (hasError(validated.diagnostics)) {
1185
+ return sys.exit(1);
1186
+ }
1187
+ }
1188
+ if (isFunction(sys.applyGlobalPatch)) {
1189
+ sys.applyGlobalPatch(validated.config.rootDir);
1190
+ }
1191
+ await sys.ensureResources({ rootDir: validated.config.rootDir, logger, dependencies: dependencies });
1192
+ await runTask(coreCompiler, validated.config, task);
1193
+ }
1194
+ catch (e) {
1195
+ if (!shouldIgnoreError(e)) {
1196
+ logger.error(`uncaught cli error: ${e}${logger.getLevel() === 'debug' ? e.stack : ''}`);
1197
+ return sys.exit(1);
1198
+ }
1199
+ }
1200
+ };
1201
+ const runTask = async (coreCompiler, config, task) => {
1202
+ config.flags = config.flags || {};
1203
+ config.outputTargets = config.outputTargets || [];
1204
+ switch (task) {
1205
+ case 'build':
1206
+ await taskBuild(coreCompiler, config);
1207
+ break;
1208
+ case 'docs':
1209
+ await taskDocs(coreCompiler, config);
1210
+ break;
1211
+ case 'help':
1212
+ taskHelp(config.sys, config.logger);
1213
+ break;
1214
+ case 'generate':
1215
+ case 'g':
1216
+ await taskGenerate(coreCompiler, config);
1217
+ break;
1218
+ case 'prerender':
1219
+ await taskPrerender(coreCompiler, config);
1220
+ break;
1221
+ case 'serve':
1222
+ await taskServe(config);
1223
+ break;
1224
+ case 'test':
1225
+ await taskTest(config);
1226
+ break;
1227
+ case 'version':
1228
+ console.log(coreCompiler.version);
1229
+ break;
1230
+ default:
1231
+ config.logger.error(`${config.logger.emoji('❌ ')}Invalid rindo command, please see the options below:`);
1232
+ taskHelp(config.sys, config.logger);
1233
+ return config.sys.exit(1);
1234
+ }
498
1235
  };
499
1236
 
500
- export { parseFlags, run, runTask };
1237
+ export { parseFlags, run, runTask };