marko 5.36.4 → 5.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/dist/compiler/index.js +11 -11
  2. package/dist/core-tags/components/init-components-tag.js +4 -4
  3. package/dist/core-tags/components/preferred-script-location-tag.js +2 -2
  4. package/dist/core-tags/core/__flush_here_and_after__.js +1 -1
  5. package/dist/core-tags/core/await/AsyncValue.js +21 -21
  6. package/dist/core-tags/core/await/renderer.js +24 -24
  7. package/dist/core-tags/core/await/reorderer-renderer.js +6 -6
  8. package/dist/node-require/browser-refresh.js +18 -1
  9. package/dist/node-require/index.js +7 -7
  10. package/dist/node_modules/@internal/components-beginComponent/index-browser.js +5 -5
  11. package/dist/node_modules/@internal/components-beginComponent/index.js +12 -12
  12. package/dist/node_modules/@internal/components-define-widget-legacy/index-browser.js +99 -99
  13. package/dist/node_modules/@internal/components-define-widget-legacy/index.js +3 -3
  14. package/dist/node_modules/@internal/components-endComponent/index.js +3 -3
  15. package/dist/node_modules/@internal/components-entry/index-browser.js +2 -2
  16. package/dist/node_modules/@internal/components-entry/index.js +29 -29
  17. package/dist/node_modules/@internal/components-entry-legacy/index-browser.js +13 -13
  18. package/dist/node_modules/@internal/components-entry-legacy/index.js +1 -1
  19. package/dist/node_modules/@internal/components-registry/index-browser.js +102 -102
  20. package/dist/node_modules/@internal/components-registry/index.js +2 -2
  21. package/dist/node_modules/@internal/components-util/index-browser.js +20 -20
  22. package/dist/node_modules/@internal/components-util/index.js +24 -20
  23. package/dist/node_modules/@internal/create-readable/index-browser.js +1 -1
  24. package/dist/node_modules/@internal/create-readable/index.js +9 -9
  25. package/dist/node_modules/@internal/preserve-tag/index-browser.js +8 -8
  26. package/dist/node_modules/@internal/preserve-tag/index.js +6 -6
  27. package/dist/node_modules/@internal/set-immediate/index-browser.js +2 -2
  28. package/dist/node_modules/@internal/set-immediate/index-worker.js +3 -3
  29. package/dist/node_modules/@internal/set-immediate/index.js +3 -3
  30. package/dist/runtime/RenderResult.js +24 -24
  31. package/dist/runtime/components/Component.js +163 -163
  32. package/dist/runtime/components/ComponentDef.js +34 -34
  33. package/dist/runtime/components/ComponentsContext.js +20 -20
  34. package/dist/runtime/components/GlobalComponentsContext.js +4 -4
  35. package/dist/runtime/components/KeySequence.js +3 -3
  36. package/dist/runtime/components/ServerComponent.js +17 -17
  37. package/dist/runtime/components/State.js +28 -28
  38. package/dist/runtime/components/attach-detach.js +8 -8
  39. package/dist/runtime/components/defineComponent.js +5 -5
  40. package/dist/runtime/components/dom-data.js +6 -6
  41. package/dist/runtime/components/event-delegation.js +10 -10
  42. package/dist/runtime/components/legacy/defineComponent-legacy.js +1 -1
  43. package/dist/runtime/components/legacy/defineRenderer-legacy.js +25 -25
  44. package/dist/runtime/components/legacy/dependencies/index.js +10 -10
  45. package/dist/runtime/components/legacy/renderer-legacy.js +56 -56
  46. package/dist/runtime/components/renderer.js +45 -45
  47. package/dist/runtime/components/update-manager.js +4 -4
  48. package/dist/runtime/createOut.js +1 -1
  49. package/dist/runtime/dom-insert.js +5 -5
  50. package/dist/runtime/helpers/_change-case.js +2 -2
  51. package/dist/runtime/helpers/dynamic-tag.js +33 -33
  52. package/dist/runtime/helpers/render-tag.js +1 -1
  53. package/dist/runtime/helpers/serialize-noop.js +2 -2
  54. package/dist/runtime/helpers/style-value.js +1 -1
  55. package/dist/runtime/helpers/tags-compat/runtime-dom.js +35 -35
  56. package/dist/runtime/helpers/tags-compat/runtime-html.js +16 -16
  57. package/dist/runtime/html/AsyncStream.js +28 -28
  58. package/dist/runtime/html/BufferedWriter.js +2 -2
  59. package/dist/runtime/html/StringWriter.js +2 -2
  60. package/dist/runtime/html/helpers/_dynamic-attr.js +2 -2
  61. package/dist/runtime/html/helpers/attr.js +11 -11
  62. package/dist/runtime/html/helpers/attrs.js +6 -6
  63. package/dist/runtime/html/helpers/data-marko.js +6 -6
  64. package/dist/runtime/html/helpers/escape-quotes.js +2 -2
  65. package/dist/runtime/html/helpers/escape-xml.js +1 -1
  66. package/dist/runtime/html/helpers/merge-attrs.js +11 -11
  67. package/dist/runtime/html/helpers/props-script.js +1 -1
  68. package/dist/runtime/html/index.js +2 -2
  69. package/dist/runtime/renderable.js +5 -5
  70. package/dist/runtime/vdom/AsyncVDOMBuilder.js +100 -100
  71. package/dist/runtime/vdom/VComment.js +7 -7
  72. package/dist/runtime/vdom/VComponent.js +5 -5
  73. package/dist/runtime/vdom/VDocumentFragment.js +8 -8
  74. package/dist/runtime/vdom/VElement.js +52 -52
  75. package/dist/runtime/vdom/VFragment.js +9 -9
  76. package/dist/runtime/vdom/VNode.js +34 -34
  77. package/dist/runtime/vdom/VText.js +8 -8
  78. package/dist/runtime/vdom/helpers/attrs.js +6 -6
  79. package/dist/runtime/vdom/helpers/const-element.js +3 -3
  80. package/dist/runtime/vdom/hot-reload.js +20 -20
  81. package/dist/runtime/vdom/index.js +2 -2
  82. package/dist/runtime/vdom/morphdom/fragment.js +10 -10
  83. package/dist/runtime/vdom/morphdom/helpers.js +5 -5
  84. package/dist/runtime/vdom/morphdom/index.js +81 -81
  85. package/dist/runtime/vdom/vdom.js +15 -15
  86. package/dist/taglib/index.js +7 -7
  87. package/dist/translator/cdata/index.js +15 -0
  88. package/dist/translator/cdata/index[html].js +15 -0
  89. package/dist/translator/cdata/index[vdom].js +12 -0
  90. package/dist/translator/class.js +65 -0
  91. package/dist/translator/comment/index.js +15 -0
  92. package/dist/translator/comment/index[html].js +17 -0
  93. package/dist/translator/comment/index[vdom].js +3 -0
  94. package/dist/translator/declaration/index.js +15 -0
  95. package/dist/translator/declaration/index[html].js +12 -0
  96. package/dist/translator/declaration/index[vdom].js +3 -0
  97. package/dist/translator/document-type/index.js +15 -0
  98. package/dist/translator/document-type/index[html].js +12 -0
  99. package/dist/translator/document-type/index[vdom].js +3 -0
  100. package/dist/translator/index.js +551 -0
  101. package/dist/translator/placeholder/index.js +15 -0
  102. package/dist/translator/placeholder/index[html].js +93 -0
  103. package/dist/translator/placeholder/index[vdom].js +22 -0
  104. package/dist/translator/scriptlet.js +4 -0
  105. package/dist/translator/tag/attribute/directives/class.js +42 -0
  106. package/dist/translator/tag/attribute/directives/index.js +15 -0
  107. package/dist/translator/tag/attribute/directives/no-update-body-if.js +15 -0
  108. package/dist/translator/tag/attribute/directives/no-update-body.js +10 -0
  109. package/dist/translator/tag/attribute/directives/no-update-if.js +12 -0
  110. package/dist/translator/tag/attribute/directives/no-update.js +48 -0
  111. package/dist/translator/tag/attribute/directives/style.js +42 -0
  112. package/dist/translator/tag/attribute/index.js +150 -0
  113. package/dist/translator/tag/attribute/modifiers/index.js +7 -0
  114. package/dist/translator/tag/attribute/modifiers/no-update.js +14 -0
  115. package/dist/translator/tag/attribute/modifiers/scoped.js +23 -0
  116. package/dist/translator/tag/attribute-tag.js +149 -0
  117. package/dist/translator/tag/custom-tag.js +146 -0
  118. package/dist/translator/tag/dynamic-tag.js +74 -0
  119. package/dist/translator/tag/index.js +287 -0
  120. package/dist/translator/tag/macro-tag.js +7 -0
  121. package/dist/translator/tag/native-tag.js +27 -0
  122. package/dist/translator/tag/native-tag[html]/attributes.js +151 -0
  123. package/dist/translator/tag/native-tag[html]/index.js +221 -0
  124. package/dist/translator/tag/native-tag[vdom]/attributes.js +105 -0
  125. package/dist/translator/tag/native-tag[vdom]/index.js +189 -0
  126. package/dist/translator/tag/util.js +246 -0
  127. package/dist/translator/taglib/core/conditional/translate-else-if.js +20 -0
  128. package/dist/translator/taglib/core/conditional/translate-else.js +20 -0
  129. package/dist/translator/taglib/core/conditional/translate-if.js +8 -0
  130. package/dist/translator/taglib/core/conditional/util.js +41 -0
  131. package/dist/translator/taglib/core/index.js +474 -0
  132. package/dist/translator/taglib/core/macro/parse.js +17 -0
  133. package/dist/translator/taglib/core/macro/translate.js +48 -0
  134. package/dist/translator/taglib/core/parse-class.js +79 -0
  135. package/dist/translator/taglib/core/parse-export.js +14 -0
  136. package/dist/translator/taglib/core/parse-import.js +14 -0
  137. package/dist/translator/taglib/core/parse-module-code.js +18 -0
  138. package/dist/translator/taglib/core/parse-static.js +18 -0
  139. package/dist/translator/taglib/core/transform-style.js +66 -0
  140. package/dist/translator/taglib/core/translate-await.js +41 -0
  141. package/dist/translator/taglib/core/translate-body.js +17 -0
  142. package/dist/translator/taglib/core/translate-for.js +156 -0
  143. package/dist/translator/taglib/core/translate-html-comment.js +52 -0
  144. package/dist/translator/taglib/core/translate-include-content.js +53 -0
  145. package/dist/translator/taglib/core/translate-server-only.js +5 -0
  146. package/dist/translator/taglib/core/translate-while.js +32 -0
  147. package/dist/translator/taglib/index.js +6 -0
  148. package/dist/translator/taglib/migrate/all-templates.js +46 -0
  149. package/dist/translator/taglib/migrate/index.js +5 -0
  150. package/dist/translator/text/index.js +10 -0
  151. package/dist/translator/text/index[html].js +12 -0
  152. package/dist/translator/text/index[vdom].js +20 -0
  153. package/dist/translator/util/add-dependencies.js +329 -0
  154. package/dist/translator/util/escape-regexp.js +4 -0
  155. package/dist/translator/util/get-component-files.js +86 -0
  156. package/dist/translator/util/html-out-write.js +15 -0
  157. package/dist/translator/util/key-manager.js +176 -0
  158. package/dist/translator/util/optimize-html-writes.js +52 -0
  159. package/dist/translator/util/optimize-vdom-create.js +164 -0
  160. package/dist/translator/util/plugin-hooks.js +22 -0
  161. package/dist/translator/util/runtime-flags.js +3 -0
  162. package/dist/translator/util/vdom-out-write.js +10 -0
  163. package/dist/translator/util/with-previous-location.js +6 -0
  164. package/package.json +7 -4
  165. package/src/taglib/index.js +2 -2
  166. package/src/translator/cdata/index.js +15 -0
  167. package/src/translator/cdata/index[html].js +15 -0
  168. package/src/translator/cdata/index[vdom].js +12 -0
  169. package/src/translator/class.js +65 -0
  170. package/src/translator/comment/index.js +15 -0
  171. package/src/translator/comment/index[html].js +17 -0
  172. package/src/translator/comment/index[vdom].js +3 -0
  173. package/src/translator/declaration/index.js +15 -0
  174. package/src/translator/declaration/index[html].js +12 -0
  175. package/src/translator/declaration/index[vdom].js +3 -0
  176. package/src/translator/document-type/index.js +15 -0
  177. package/src/translator/document-type/index[html].js +12 -0
  178. package/src/translator/document-type/index[vdom].js +3 -0
  179. package/src/translator/index.js +551 -0
  180. package/src/translator/placeholder/index.js +15 -0
  181. package/src/translator/placeholder/index[html].js +93 -0
  182. package/src/translator/placeholder/index[vdom].js +22 -0
  183. package/src/translator/scriptlet.js +4 -0
  184. package/src/translator/tag/attribute/directives/class.js +42 -0
  185. package/src/translator/tag/attribute/directives/index.js +15 -0
  186. package/src/translator/tag/attribute/directives/no-update-body-if.js +15 -0
  187. package/src/translator/tag/attribute/directives/no-update-body.js +10 -0
  188. package/src/translator/tag/attribute/directives/no-update-if.js +12 -0
  189. package/src/translator/tag/attribute/directives/no-update.js +48 -0
  190. package/src/translator/tag/attribute/directives/style.js +42 -0
  191. package/src/translator/tag/attribute/index.js +150 -0
  192. package/src/translator/tag/attribute/modifiers/index.js +7 -0
  193. package/src/translator/tag/attribute/modifiers/no-update.js +14 -0
  194. package/src/translator/tag/attribute/modifiers/scoped.js +23 -0
  195. package/src/translator/tag/attribute-tag.js +149 -0
  196. package/src/translator/tag/custom-tag.js +146 -0
  197. package/src/translator/tag/dynamic-tag.js +74 -0
  198. package/src/translator/tag/index.js +287 -0
  199. package/src/translator/tag/macro-tag.js +7 -0
  200. package/src/translator/tag/native-tag.js +27 -0
  201. package/src/translator/tag/native-tag[html]/attributes.js +151 -0
  202. package/src/translator/tag/native-tag[html]/index.js +221 -0
  203. package/src/translator/tag/native-tag[vdom]/attributes.js +105 -0
  204. package/src/translator/tag/native-tag[vdom]/index.js +189 -0
  205. package/src/translator/tag/util.js +246 -0
  206. package/src/translator/taglib/core/conditional/translate-else-if.js +20 -0
  207. package/src/translator/taglib/core/conditional/translate-else.js +20 -0
  208. package/src/translator/taglib/core/conditional/translate-if.js +8 -0
  209. package/src/translator/taglib/core/conditional/util.js +41 -0
  210. package/src/translator/taglib/core/index.js +474 -0
  211. package/src/translator/taglib/core/macro/parse.js +17 -0
  212. package/src/translator/taglib/core/macro/translate.js +48 -0
  213. package/src/translator/taglib/core/parse-class.js +79 -0
  214. package/src/translator/taglib/core/parse-export.js +14 -0
  215. package/src/translator/taglib/core/parse-import.js +14 -0
  216. package/src/translator/taglib/core/parse-module-code.js +18 -0
  217. package/src/translator/taglib/core/parse-static.js +18 -0
  218. package/src/translator/taglib/core/transform-style.js +66 -0
  219. package/src/translator/taglib/core/translate-await.js +41 -0
  220. package/src/translator/taglib/core/translate-body.js +17 -0
  221. package/src/translator/taglib/core/translate-for.js +156 -0
  222. package/src/translator/taglib/core/translate-html-comment.js +52 -0
  223. package/src/translator/taglib/core/translate-include-content.js +53 -0
  224. package/src/translator/taglib/core/translate-server-only.js +5 -0
  225. package/src/translator/taglib/core/translate-while.js +32 -0
  226. package/src/translator/taglib/index.js +7 -0
  227. package/src/translator/taglib/migrate/all-templates.js +46 -0
  228. package/src/translator/taglib/migrate/index.js +5 -0
  229. package/src/translator/text/index.js +10 -0
  230. package/src/translator/text/index[html].js +12 -0
  231. package/src/translator/text/index[vdom].js +20 -0
  232. package/src/translator/util/add-dependencies.js +329 -0
  233. package/src/translator/util/escape-regexp.js +4 -0
  234. package/src/translator/util/get-component-files.js +86 -0
  235. package/src/translator/util/html-out-write.js +15 -0
  236. package/src/translator/util/key-manager.js +176 -0
  237. package/src/translator/util/optimize-html-writes.js +52 -0
  238. package/src/translator/util/optimize-vdom-create.js +164 -0
  239. package/src/translator/util/plugin-hooks.js +22 -0
  240. package/src/translator/util/runtime-flags.js +3 -0
  241. package/src/translator/util/vdom-out-write.js +10 -0
  242. package/src/translator/util/with-previous-location.js +6 -0
  243. package/translator/index.d.ts +7 -0
  244. package/translator/package.json +5 -0
@@ -0,0 +1,329 @@
1
+ import { types as t } from "@marko/compiler";
2
+ import {
3
+ loadFileForImport,
4
+ parseStatements,
5
+ resolveRelativePath,
6
+ } from "@marko/compiler/babel-utils";
7
+ import MagicString from "magic-string";
8
+ import path from "path";
9
+ import resolveFrom from "resolve-from";
10
+ const kEntryState = Symbol();
11
+ const lassoDepPrefix = "package: ";
12
+
13
+ export default (entryFile, isHydrate) => {
14
+ const program = entryFile.path;
15
+ const programNode = program.node;
16
+
17
+ if (!isHydrate) {
18
+ const body = [];
19
+ addBrowserImports(new Set(), undefined, body, entryFile, entryFile);
20
+ if (body.length) {
21
+ programNode.body = body.concat(programNode.body);
22
+ }
23
+ return;
24
+ }
25
+
26
+ const visitedFiles = new Set([
27
+ resolveRelativePath(entryFile, entryFile.opts.filename),
28
+ ]);
29
+ entryBuilder.visit(entryFile, entryFile, function visitChild(resolved) {
30
+ if (!visitedFiles.has(resolved)) {
31
+ visitedFiles.add(resolved);
32
+ const file = loadFileForImport(entryFile, resolved);
33
+ if (file) {
34
+ entryBuilder.visit(file, entryFile, (id) =>
35
+ visitChild(resolveRelativeToEntry(entryFile, file, id)),
36
+ );
37
+ }
38
+ }
39
+ });
40
+
41
+ programNode.body = entryBuilder.build(entryFile);
42
+ program.skip();
43
+ };
44
+
45
+ export const entryBuilder = {
46
+ build(entryFile) {
47
+ const state = entryFile[kEntryState];
48
+ if (!state) {
49
+ throw entryFile.path.buildCodeFrameError(
50
+ "Unable to build hydrate code, no files were visited before finalizing the build",
51
+ );
52
+ }
53
+ const { markoOpts } = entryFile;
54
+ const entryMarkoMeta = entryFile.metadata.marko;
55
+ const { body } = state;
56
+ entryMarkoMeta.watchFiles = [...state.watchFiles];
57
+ entryMarkoMeta.deps = [...state.lassoDeps];
58
+
59
+ if (state.hasComponents) {
60
+ const initId = t.identifier("init");
61
+ const markoComponentsImport = importPath(
62
+ resolveRelativePath(entryFile, "marko/src/runtime/components/index.js"),
63
+ );
64
+ if (state.splitComponentIndex) {
65
+ markoComponentsImport.specifiers.push(
66
+ t.importSpecifier(t.identifier("register"), t.identifier("register")),
67
+ );
68
+ }
69
+
70
+ body.unshift(markoComponentsImport);
71
+
72
+ if (markoOpts.hydrateInit) {
73
+ markoComponentsImport.specifiers.push(
74
+ t.importSpecifier(initId, initId),
75
+ );
76
+ body.push(
77
+ t.expressionStatement(
78
+ t.callExpression(
79
+ initId,
80
+ markoOpts.runtimeId ? [t.stringLiteral(markoOpts.runtimeId)] : [],
81
+ ),
82
+ ),
83
+ );
84
+ }
85
+ }
86
+
87
+ return body;
88
+ },
89
+ visit(file, entryFile, visitChild) {
90
+ const fileMeta = file.metadata.marko;
91
+ const fileName = file.opts.filename;
92
+ const state = (entryFile[kEntryState] ||= {
93
+ shouldIncludeImport: toTestFn(file.markoOpts.hydrateIncludeImports),
94
+ watchFiles: new Set(),
95
+ imports: new Set(),
96
+ lassoDeps: new Set(),
97
+ hasComponents: false,
98
+ splitComponentIndex: 0,
99
+ body: [],
100
+ });
101
+
102
+ const { watchFiles, imports, lassoDeps, body } = state;
103
+
104
+ if (fileMeta.component) {
105
+ state.hasComponents = true;
106
+
107
+ if (path.basename(fileMeta.component) === path.basename(fileName)) {
108
+ // Stateful component.
109
+ addImport(imports, body, resolveRelativePath(entryFile, fileName));
110
+ return;
111
+ }
112
+ }
113
+
114
+ watchFiles.add(fileName);
115
+
116
+ for (const watchFile of fileMeta.watchFiles) {
117
+ watchFiles.add(watchFile);
118
+ }
119
+
120
+ addBrowserImports(imports, lassoDeps, body, file, entryFile);
121
+
122
+ for (const child of file.path.node.body) {
123
+ if (t.isImportDeclaration(child)) {
124
+ const { value } = child.source;
125
+ if (state.shouldIncludeImport(value)) {
126
+ addImport(
127
+ imports,
128
+ body,
129
+ resolveRelativeToEntry(entryFile, file, value),
130
+ );
131
+ }
132
+ }
133
+ }
134
+
135
+ for (const tag of fileMeta.tags) {
136
+ if (tag.endsWith(".marko")) {
137
+ visitChild(tag);
138
+ } else {
139
+ const importedTemplates = tryGetTemplateImports(file, tag);
140
+ if (importedTemplates) {
141
+ for (const templateFile of importedTemplates) {
142
+ visitChild(templateFile);
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ if (fileMeta.component) {
149
+ // Split component
150
+ const splitComponentId = t.identifier(
151
+ `component_${state.splitComponentIndex++}`,
152
+ );
153
+ const splitComponentImport = importPath(
154
+ resolveRelativeToEntry(entryFile, file, fileMeta.component),
155
+ );
156
+ splitComponentImport.specifiers.push(
157
+ t.importDefaultSpecifier(splitComponentId),
158
+ );
159
+ body.push(
160
+ splitComponentImport,
161
+ t.expressionStatement(
162
+ t.callExpression(t.identifier("register"), [
163
+ t.stringLiteral(fileMeta.id),
164
+ splitComponentId,
165
+ ]),
166
+ ),
167
+ );
168
+ }
169
+ },
170
+ };
171
+
172
+ function addBrowserImports(seenImports, lassoDeps, body, file, entryFile) {
173
+ const { filename, sourceMaps } = file.opts;
174
+ let s;
175
+
176
+ for (let dep of file.metadata.marko.deps) {
177
+ if (typeof dep !== "string") {
178
+ const { virtualPath } = dep;
179
+ let { code } = dep;
180
+ let map;
181
+
182
+ if (sourceMaps && dep.startPos !== undefined) {
183
+ s = s || new MagicString(file.code, { filename });
184
+ map = s.snip(dep.startPos, dep.endPos).generateMap({
185
+ source: filename,
186
+ includeContent: true,
187
+ });
188
+
189
+ if (sourceMaps === "inline" || sourceMaps === "both") {
190
+ code += dep.style
191
+ ? `\n/*# sourceMappingURL=${map.toUrl()}*/`
192
+ : `\n//# sourceMappingURL=${map.toUrl()}`;
193
+
194
+ if (sourceMaps === "inline") {
195
+ map = undefined;
196
+ }
197
+ }
198
+ }
199
+
200
+ dep = file.markoOpts.resolveVirtualDependency(filename, {
201
+ map,
202
+ code,
203
+ virtualPath,
204
+ });
205
+
206
+ if (!dep) {
207
+ continue;
208
+ }
209
+ } else if (isLassoDep(dep)) {
210
+ if (lassoDeps) {
211
+ lassoDeps.add(
212
+ resolveLassoManifestDepRelativeToEntry(entryFile, file, dep),
213
+ );
214
+ }
215
+ continue;
216
+ }
217
+
218
+ addImport(seenImports, body, resolveRelativeToEntry(entryFile, file, dep));
219
+ }
220
+ }
221
+
222
+ function addImport(seenImports, body, resolved) {
223
+ if (seenImports.has(resolved)) return;
224
+ seenImports.add(resolved);
225
+ body.push(importPath(resolved));
226
+ }
227
+
228
+ function resolveRelativeToEntry(entryFile, file, req) {
229
+ return file === entryFile
230
+ ? resolveRelativePath(file, req)
231
+ : resolveRelativePath(
232
+ entryFile,
233
+ req[0] === "." ? path.join(file.opts.filename, "..", req) : req,
234
+ );
235
+ }
236
+
237
+ function importPath(path) {
238
+ return t.importDeclaration([], t.stringLiteral(path));
239
+ }
240
+
241
+ function tryGetTemplateImports(file, rendererRelativePath) {
242
+ const resolvedRendererPath = path.join(
243
+ file.opts.filename,
244
+ "..",
245
+ rendererRelativePath,
246
+ );
247
+ let templateImports;
248
+
249
+ try {
250
+ for (const statement of parseStatements(
251
+ file,
252
+ file.markoOpts.fileSystem.readFileSync(resolvedRendererPath, "utf-8"),
253
+ )) {
254
+ if (statement.type === "ImportDeclaration") {
255
+ addTemplateImport(statement.source.value);
256
+ } else {
257
+ t.traverseFast(statement, (node) => {
258
+ if (
259
+ node.type === "CallExpression" &&
260
+ (node.callee.name === "require" ||
261
+ (node.callee.type === "MemberExpression" &&
262
+ node.callee.object.type === "Identifier" &&
263
+ node.callee.object.name === "require" &&
264
+ node.callee.property.type === "Identifier" &&
265
+ node.callee.property.name === "resolve")) &&
266
+ node.arguments.length === 1 &&
267
+ node.arguments[0].type === "StringLiteral"
268
+ ) {
269
+ addTemplateImport(node.arguments[0].value);
270
+ }
271
+ });
272
+ }
273
+ }
274
+ } catch {
275
+ // Ignore
276
+ }
277
+
278
+ return templateImports;
279
+
280
+ function addTemplateImport(request) {
281
+ if (request.endsWith(".marko")) {
282
+ const resolvedTemplatePath =
283
+ request[0] === "."
284
+ ? path.resolve(resolvedRendererPath, "..", request)
285
+ : resolveFrom.silent(path.dirname(resolvedRendererPath), request);
286
+ if (resolvedTemplatePath) {
287
+ if (templateImports) {
288
+ templateImports.push(resolvedTemplatePath);
289
+ } else {
290
+ templateImports = [resolvedTemplatePath];
291
+ }
292
+ }
293
+ }
294
+ }
295
+ }
296
+
297
+ function toTestFn(val) {
298
+ if (typeof val === "function") {
299
+ return val;
300
+ }
301
+
302
+ return val.test.bind(val);
303
+ }
304
+
305
+ function isLassoDep(dep) {
306
+ return dep.startsWith(lassoDepPrefix);
307
+ }
308
+
309
+ /**
310
+ * Lasso manifest deps in `lasso-marko` do not support node module resolution.
311
+ * eg `package: @ebay/ebayui-core/browser.json` will not resolve.
312
+ *
313
+ * This resolution returns a direct posix relative path.
314
+ */
315
+ function resolveLassoManifestDepRelativeToEntry(entryFile, targetFile, dep) {
316
+ const entryFileName = entryFile.opts.filename;
317
+ const targetFileName = targetFile.opts.filename;
318
+ if (entryFileName === targetFileName) return dep;
319
+
320
+ const resolved = toPosix(
321
+ path.relative(
322
+ path.dirname(entryFileName),
323
+ path.join(targetFileName, "..", dep.slice(lassoDepPrefix.length)),
324
+ ),
325
+ );
326
+ return lassoDepPrefix + (resolved[0] === "." ? resolved : `./${resolved}`);
327
+ }
328
+
329
+ const toPosix = path.sep === "/" ? (v) => v : (v) => v.replace(/\\/g, "/");
@@ -0,0 +1,4 @@
1
+ const regexpCharsReg = /[\\^$.*+?()[\]{}|]/g;
2
+ export function escapeRegExp(str) {
3
+ return str.replace(regexpCharsReg, "\\$&");
4
+ }
@@ -0,0 +1,86 @@
1
+ import path from "path";
2
+
3
+ import { escapeRegExp } from "./escape-regexp";
4
+
5
+ const COMPONENT_FILES_KEY = "___marko_component_files___";
6
+
7
+ export default function getComponentFiles({ hub: { file } }) {
8
+ const meta = file.metadata.marko;
9
+
10
+ if (meta[COMPONENT_FILES_KEY]) {
11
+ return meta[COMPONENT_FILES_KEY];
12
+ }
13
+
14
+ const { filename } = file.opts;
15
+ const fs = file.markoOpts.fileSystem;
16
+ const dirname = path.dirname(filename);
17
+ const dirFiles = fs.readdirSync(dirname).sort();
18
+ const base = getBase(filename);
19
+ const isEntry = "index" === base || "template" === base;
20
+ const fileMatch = `(${escapeRegExp(base)}\\.${isEntry ? "|" : ""})`;
21
+ const styleMatch = new RegExp(`^${fileMatch}style\\.\\w+$`);
22
+ const componentMatch = new RegExp(`^${fileMatch}component\\.\\w+$`);
23
+ const splitComponentMatch = new RegExp(
24
+ `^${fileMatch}component-browser\\.\\w+$`,
25
+ );
26
+ const packageMatch = new RegExp(`^${fileMatch}browser\\.\\json$`);
27
+ let styleFile;
28
+ let packageFile;
29
+ let componentFile;
30
+ let componentBrowserFile;
31
+
32
+ for (const file of dirFiles) {
33
+ if (!styleFile && styleMatch.test(file)) {
34
+ styleFile = `./${file}`;
35
+ } else if (!packageFile && packageMatch.test(file)) {
36
+ packageFile = `./${file}`;
37
+ } else if (!componentFile && componentMatch.test(file)) {
38
+ componentFile = `./${file}`;
39
+ meta.hasComponent = true;
40
+ } else if (!componentBrowserFile && splitComponentMatch.test(file)) {
41
+ componentBrowserFile = `./${file}`;
42
+ meta.hasComponentBrowser = true;
43
+ }
44
+ }
45
+
46
+ return (meta[COMPONENT_FILES_KEY] = {
47
+ styleFile,
48
+ packageFile,
49
+ componentFile,
50
+ componentBrowserFile,
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Given a filename, gets the base name, strips off the file extension
56
+ * and removes any arc flags (https://github.com/eBay/arc).
57
+ *
58
+ * @example
59
+ * getBase("/dir/foo.marko") // => "foo"
60
+ * getBase("/dir/foo.bar.marko") // => "foo.bar"
61
+ * getBase("/dir/foo[bar].marko") // => "foo"
62
+ * getBase("/dir/foo[bar].baz.marko") // => "foo.baz"
63
+ */
64
+ function getBase(filename) {
65
+ const start = filename.lastIndexOf(path.sep) + 1;
66
+ const leftDot = filename.indexOf(".", start);
67
+
68
+ if (leftDot === -1) {
69
+ return filename.slice(start);
70
+ }
71
+
72
+ const rightDot = filename.lastIndexOf(".");
73
+ const closeBracket = leftDot - 1;
74
+ if (filename[closeBracket] === "]") {
75
+ const openBracket = filename.lastIndexOf("[", closeBracket);
76
+ if (openBracket > start) {
77
+ // If we match a "]" before the extension and find a "[" before that,
78
+ // then we have an arc flag. Strip it off.
79
+ return (
80
+ filename.slice(start, openBracket) + filename.slice(leftDot, rightDot)
81
+ );
82
+ }
83
+ }
84
+
85
+ return filename.slice(start, rightDot);
86
+ }
@@ -0,0 +1,15 @@
1
+ import { types as t } from "@marko/compiler";
2
+ import { normalizeTemplateString } from "@marko/compiler/babel-utils";
3
+
4
+ export default function write(strings, ...expressions) {
5
+ const template = normalizeTemplateString(strings, ...expressions);
6
+
7
+ if (template) {
8
+ return t.expressionStatement(
9
+ t.callExpression(
10
+ t.memberExpression(t.identifier("out"), t.identifier("w")),
11
+ [template],
12
+ ),
13
+ );
14
+ }
15
+ }
@@ -0,0 +1,176 @@
1
+ import { types as t } from "@marko/compiler";
2
+ import {
3
+ isLoopTag,
4
+ isTransparentTag,
5
+ normalizeTemplateString,
6
+ } from "@marko/compiler/babel-utils";
7
+ const KeyManagerLookup = new WeakMap();
8
+
9
+ /**
10
+ * @returns {KeyManager}
11
+ */
12
+ export function getKeyManager(path) {
13
+ const { hub } = path;
14
+ return (
15
+ KeyManagerLookup.get(hub) ||
16
+ KeyManagerLookup.set(hub, new KeyManager()).get(hub)
17
+ );
18
+ }
19
+
20
+ export function hasAutoKey(path) {
21
+ const key = path.get("key").node;
22
+ return Boolean(key && key._isAutoKey);
23
+ }
24
+
25
+ export function hasUserKey(path) {
26
+ return path.node._hasUserKey;
27
+ }
28
+
29
+ class KeyManager {
30
+ constructor() {
31
+ this._nextKey = 0;
32
+ }
33
+
34
+ nextKey() {
35
+ return Object.assign(t.stringLiteral(String(this._nextKey++)), {
36
+ _isAutoKey: true,
37
+ });
38
+ }
39
+
40
+ resolveKey(path) {
41
+ if (isLoopTag(path)) {
42
+ // Record the first child key if found under a loop.
43
+ const firstChildTag = path
44
+ .get("body.body")
45
+ .find((child) => child.isMarkoTag());
46
+ const firstChildKey = firstChildTag && getUserKey(firstChildTag);
47
+
48
+ if (firstChildKey) {
49
+ const keyValueIdentifier = path.scope.generateUidIdentifier("keyValue");
50
+ firstChildTag.set("key", keyValueIdentifier);
51
+ firstChildTag.insertBefore(
52
+ t.variableDeclaration("const", [
53
+ t.variableDeclarator(keyValueIdentifier, firstChildKey),
54
+ ]),
55
+ );
56
+
57
+ path.set("keyValue", keyValueIdentifier);
58
+ path.get("body").scope.crawl();
59
+ }
60
+ return;
61
+ }
62
+
63
+ if (isTransparentTag(path)) {
64
+ return;
65
+ }
66
+
67
+ if (getUserKey(path)) {
68
+ return;
69
+ }
70
+
71
+ const parentKeyScope = getParentKeyScope(path);
72
+ const autoKey = path.get("key").node || this.nextKey();
73
+ path.set(
74
+ "key",
75
+ parentKeyScope
76
+ ? t.binaryExpression("+", autoKey, parentKeyScope)
77
+ : autoKey,
78
+ );
79
+ }
80
+ }
81
+
82
+ function getParentKeyScope(path) {
83
+ const parentLoopTag = path.findParent(isLoopTag);
84
+ return parentLoopTag && getKeyScope(parentLoopTag);
85
+ }
86
+
87
+ function getKeyScope(path) {
88
+ const existingKeyScope = path.get("keyScope").node;
89
+ if (existingKeyScope) {
90
+ return existingKeyScope;
91
+ }
92
+
93
+ const keyScopeIdentifier = path.scope.generateUidIdentifier("keyScope");
94
+ const firstChildKeyValue = path.get("keyValue").node;
95
+
96
+ if (firstChildKeyValue) {
97
+ const valuePath = path
98
+ .get("body")
99
+ .scope.getOwnBinding(firstChildKeyValue.name).path;
100
+ const declarationPath = valuePath.parentPath;
101
+ declarationPath.pushContainer(
102
+ "declarations",
103
+ t.variableDeclarator(
104
+ keyScopeIdentifier,
105
+ normalizeTemplateString`[${firstChildKeyValue}]`,
106
+ ),
107
+ );
108
+ } else {
109
+ let keyValue;
110
+
111
+ if (path.get("name.value").node === "for") {
112
+ if (path.node.attributes.some((attr) => attr.name === "of")) {
113
+ keyValue = path.node.body.params[1];
114
+ } else {
115
+ keyValue = path.node.body.params[0];
116
+ }
117
+ }
118
+
119
+ if (!keyValue) {
120
+ const keyValueIdentifier = path.scope.generateUidIdentifier("keyValue");
121
+ path.insertBefore(
122
+ t.variableDeclaration("let", [
123
+ t.variableDeclarator(keyValueIdentifier, t.numericLiteral(0)),
124
+ ]),
125
+ );
126
+
127
+ keyValue = t.updateExpression("++", keyValueIdentifier);
128
+ }
129
+
130
+ const parentKeyScope = getParentKeyScope(path);
131
+ if (parentKeyScope) {
132
+ keyValue = t.binaryExpression("+", keyValue, parentKeyScope);
133
+ }
134
+
135
+ const keyScopeDecl = t.variableDeclaration("const", [
136
+ t.variableDeclarator(
137
+ keyScopeIdentifier,
138
+ normalizeTemplateString`[${keyValue}]`,
139
+ ),
140
+ ]);
141
+
142
+ if (path.node.attributeTags.length) {
143
+ path.unshiftContainer("attributeTags", keyScopeDecl);
144
+ } else {
145
+ path.get("body").unshiftContainer("body", keyScopeDecl);
146
+ }
147
+ }
148
+
149
+ path.set("keyScope", keyScopeIdentifier);
150
+ return keyScopeIdentifier;
151
+ }
152
+
153
+ function getUserKey(path) {
154
+ if (hasAutoKey(path)) {
155
+ return undefined;
156
+ }
157
+
158
+ let key = path.get("key").node;
159
+ if (key === undefined) {
160
+ const keyAttr = path
161
+ .get("attributes")
162
+ .find((attr) => attr.get("name").node === "key");
163
+
164
+ if (keyAttr) {
165
+ key = normalizeTemplateString`@${keyAttr.get("value").node}`;
166
+ path.node._hasUserKey = true;
167
+ keyAttr.remove();
168
+ } else {
169
+ key = null;
170
+ }
171
+
172
+ path.set("key", key);
173
+ }
174
+
175
+ return key;
176
+ }
@@ -0,0 +1,52 @@
1
+ import { normalizeTemplateString } from "@marko/compiler/babel-utils";
2
+
3
+ const mergeWriteCallsVisitor = {
4
+ ExpressionStatement(path) {
5
+ let curPath = path;
6
+ const quasis = [""];
7
+ const expressions = [];
8
+ const removals = [];
9
+
10
+ do {
11
+ const content = getOutContent(curPath);
12
+ if (!content) break;
13
+ if (curPath !== path) removals.push(curPath);
14
+ quasis.push("");
15
+ expressions.push(content);
16
+ } while ((curPath = curPath.getNextSibling()));
17
+
18
+ removals.forEach((removal) => removal.remove());
19
+
20
+ if (expressions.length > 1) {
21
+ path
22
+ .get("expression.arguments.0")
23
+ .replaceWith(normalizeTemplateString(quasis, ...expressions));
24
+ }
25
+ },
26
+ };
27
+
28
+ export function optimizeHTMLWrites(path) {
29
+ const {
30
+ hub: {
31
+ file: { markoOpts },
32
+ },
33
+ } = path;
34
+
35
+ if (markoOpts.optimize && markoOpts.output === "html") {
36
+ path.traverse(mergeWriteCallsVisitor);
37
+ }
38
+ }
39
+
40
+ function getOutContent(path) {
41
+ if (path.isExpressionStatement()) {
42
+ return getOutContent(path.get("expression"));
43
+ }
44
+
45
+ return (
46
+ path.isCallExpression() &&
47
+ path.get("callee").isMemberExpression() &&
48
+ path.get("callee.object.name").node === "out" &&
49
+ path.get("callee.property.name").node === "w" &&
50
+ path.get("arguments.0").node
51
+ );
52
+ }