@torpor/view 0.0.11 → 0.0.13

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 (174) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{ServerSlotRender-AWF3bD5B.d.cts → ServerSlotRender-t1sOutne.d.cts} +1 -1
  3. package/dist/{ServerSlotRender-AWF3bD5B.d.ts → ServerSlotRender-t1sOutne.d.ts} +1 -1
  4. package/dist/{chunk-GO2L324Q.js → chunk-T6JGCJ5T.js} +5 -2
  5. package/dist/chunk-T6JGCJ5T.js.map +1 -0
  6. package/dist/compile.cjs +42 -31
  7. package/dist/compile.cjs.map +1 -1
  8. package/dist/compile.d.cts +1 -0
  9. package/dist/compile.d.ts +1 -0
  10. package/dist/compile.js +42 -31
  11. package/dist/compile.js.map +1 -1
  12. package/dist/index.cjs +4 -1
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +2 -2
  15. package/dist/index.d.ts +2 -2
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/metafile-cjs.json +1 -1
  19. package/dist/metafile-esm.json +1 -1
  20. package/dist/ssr.cjs +4 -1
  21. package/dist/ssr.cjs.map +1 -1
  22. package/dist/ssr.d.cts +2 -2
  23. package/dist/ssr.d.ts +2 -2
  24. package/dist/ssr.js +1 -1
  25. package/dist/ssr.js.map +1 -1
  26. package/package.json +6 -6
  27. package/scripts/buildTestOutput.ts +2 -121
  28. package/src/compile/build/client/buildAddFragment.ts +1 -1
  29. package/src/compile/build/client/buildAwaitNode.ts +1 -1
  30. package/src/compile/build/client/buildComponentNode.ts +1 -1
  31. package/src/compile/build/client/buildControlNode.ts +1 -1
  32. package/src/compile/build/client/buildElementNode.ts +7 -1
  33. package/src/compile/build/client/buildForNode.ts +1 -1
  34. package/src/compile/build/client/buildFragment.ts +1 -1
  35. package/src/compile/build/client/buildFragmentText.ts +7 -1
  36. package/src/compile/build/client/buildHeadNode.ts +1 -1
  37. package/src/compile/build/client/buildHtmlNode.ts +1 -1
  38. package/src/compile/build/client/buildIfNode.ts +1 -1
  39. package/src/compile/build/client/buildMount.ts +1 -1
  40. package/src/compile/build/client/buildNode.ts +1 -1
  41. package/src/compile/build/client/buildReplaceNode.ts +1 -1
  42. package/src/compile/build/client/buildRootNode.ts +1 -1
  43. package/src/compile/build/client/buildRun.ts +1 -1
  44. package/src/compile/build/client/buildScriptNode.ts +1 -1
  45. package/src/compile/build/client/buildSlotNode.ts +1 -1
  46. package/src/compile/build/client/buildSwitchNode.ts +1 -1
  47. package/src/compile/build/client/buildTextNode.ts +1 -1
  48. package/src/compile/build/client/replaceForVarNames.ts +1 -1
  49. package/src/compile/build/server/buildServerAwaitNode.ts +1 -1
  50. package/src/compile/build/server/buildServerComponentNode.ts +1 -1
  51. package/src/compile/build/server/buildServerControlNode.ts +1 -1
  52. package/src/compile/build/server/buildServerElementNode.ts +9 -1
  53. package/src/compile/build/server/buildServerForNode.ts +1 -1
  54. package/src/compile/build/server/buildServerHtmlNode.ts +1 -1
  55. package/src/compile/build/server/buildServerIfNode.ts +1 -1
  56. package/src/compile/build/server/buildServerNode.ts +5 -1
  57. package/src/compile/build/server/buildServerReplaceNode.ts +1 -1
  58. package/src/compile/build/server/buildServerRootNode.ts +5 -1
  59. package/src/compile/build/server/buildServerScriptNode.ts +1 -1
  60. package/src/compile/build/server/buildServerSlotNode.ts +1 -1
  61. package/src/compile/build/server/buildServerSpecialNode.ts +1 -1
  62. package/src/compile/build/server/buildServerSwitchNode.ts +1 -1
  63. package/src/compile/build/server/buildServerTextNode.ts +1 -1
  64. package/src/compile/build/utils/isFullyReactive.ts +1 -1
  65. package/src/compile/build/utils/isReactive.ts +1 -1
  66. package/src/compile/build/utils/isReactiveAttribute.ts +1 -1
  67. package/src/compile/parse/addSpaceElement.ts +4 -1
  68. package/src/compile/parse/parseCode.ts +4 -0
  69. package/src/compile/parse/parseControl.ts +4 -1
  70. package/src/compile/parse/parseImports.ts +1 -1
  71. package/src/compile/parse/parseMarkup.ts +1 -1
  72. package/src/compile/parse/parseStyles.ts +1 -1
  73. package/src/compile/parse/scopeStyles.ts +13 -21
  74. package/src/compile/parse/slottifyChildNodes.ts +1 -1
  75. package/src/compile/parse/utils/addError.ts +5 -1
  76. package/src/compile/parse/utils/consumeUntil.ts +1 -1
  77. package/src/compile/parse/utils/isAlphaNumeric.ts +1 -1
  78. package/src/compile/parse/utils/isAlphaNumericChar.ts +1 -1
  79. package/src/compile/parse/utils/isSpace.ts +1 -1
  80. package/src/compile/parse/utils/isSpaceChar.ts +1 -1
  81. package/src/compile/types/nodes/TemplateNode.ts +3 -0
  82. package/src/compile/utils/Builder.ts +3 -3
  83. package/src/compile/utils/trimEnd.ts +1 -1
  84. package/src/compile/utils/trimMatched.ts +1 -1
  85. package/src/compile/utils/trimQuotes.ts +1 -1
  86. package/src/compile/utils/trimStart.ts +1 -1
  87. package/src/compile/utils/trimStartAndEnd.ts +1 -1
  88. package/src/compile/utils/voidTags.ts +1 -1
  89. package/src/debug/printHtml.ts +1 -1
  90. package/src/motion/animate.ts +1 -1
  91. package/src/render/$mount.ts +1 -1
  92. package/src/render/$run.ts +1 -1
  93. package/src/render/$serverMount.ts +1 -1
  94. package/src/render/$serverRun.ts +1 -1
  95. package/src/render/$stream.ts +1 -1
  96. package/src/render/addAnimation.ts +1 -1
  97. package/src/render/addEvent.ts +1 -1
  98. package/src/render/addFragment.ts +1 -1
  99. package/src/render/applyProps.ts +1 -1
  100. package/src/render/clearRange.ts +1 -1
  101. package/src/render/createComment.ts +1 -1
  102. package/src/render/createElement.ts +1 -1
  103. package/src/render/createFragment.ts +1 -1
  104. package/src/render/createText.ts +1 -1
  105. package/src/render/flushMountEffects.ts +1 -1
  106. package/src/render/getClasses.ts +4 -1
  107. package/src/render/hydrate.ts +1 -1
  108. package/src/render/hydrateRoot.ts +1 -1
  109. package/src/render/mount.ts +1 -1
  110. package/src/render/moveRange.ts +1 -1
  111. package/src/render/popRange.ts +1 -1
  112. package/src/render/runControl.ts +1 -1
  113. package/src/render/runControlBranch.ts +1 -1
  114. package/src/render/runList.ts +1 -1
  115. package/src/render/runListItems.ts +1 -1
  116. package/src/render/setAttribute.ts +1 -1
  117. package/src/render/setDynamicElement.ts +1 -1
  118. package/src/watch/proxyGet.ts +1 -1
  119. package/src/watch/removeEffect.ts +1 -1
  120. package/src/watch/runEffect.ts +1 -1
  121. package/src/watch/symbols.ts +1 -1
  122. package/src/watch/trackEffect.ts +1 -1
  123. package/src/watch/transferEffects.ts +1 -1
  124. package/src/watch/triggerEffects.ts +1 -1
  125. package/test/bench/components/output/Bench-client.ts +0 -204
  126. package/test/bench/components/output/Bench-server.ts +0 -130
  127. package/test/bench/components/temp/Bench-client-5fee290225ae4771aa847360006123671e8f17f1.ts +208 -0
  128. package/test/bench/components/temp/Bench-server-00cefa588803c01ca4f2741c595e4f045cdd101e.ts +130 -0
  129. package/test/build-server/components/{output/IfNested-client.ts → temp/IfNested-client-979db97eea5b4595550b9b46f297f3fbc31796d2.ts} +11 -0
  130. package/test/buildHtml.ts +1 -1
  131. package/test/buildOutputFiles.ts +47 -12
  132. package/test/class/class.test.ts +29 -6
  133. package/test/class/components/Class.torp +15 -1
  134. package/test/class/components/output/Class-client.ts +10 -6
  135. package/test/class/components/output/Class-server.ts +1 -1
  136. package/test/class/components/temp/{Class-client-600bf865c14f1052d24e1c79242f837aaf5ae5e8.ts → Class-client-8c3f9e0257cc2b687e9bb7106cccbab94a4b5adf.ts} +10 -6
  137. package/test/class/components/temp/Class-server-2218c3284845fdab80d1a41ebace9a9e2ddd6fc1.ts +17 -0
  138. package/test/component/components/temp/Header-client-ac151eea86e3f6b058fab101661e13ae73864968.ts +34 -0
  139. package/test/component/components/temp/Header-server-4f10f2332f3ca7a097517cfb938ab1e6f31d68ac.ts +17 -0
  140. package/test/console/components/temp/{Console-client-254d7d4799471401334d698b1631ab1cb5b70558.ts → Console-client-2f206752ce59e59fba9bb91263b4102fd515951e.ts} +1 -1
  141. package/test/console/components/temp/Console-server-b4b15f7a0d1d2b50d87bad4870e1b8d368707c04.ts +17 -0
  142. package/test/globalSetup.ts +1 -1
  143. package/test/helpers.ts +6 -2
  144. package/test/hydrateComponent.ts +1 -1
  145. package/test/importComponent.ts +12 -40
  146. package/test/mountComponent.ts +5 -1
  147. package/test/party/components/temp/AnswerButton-client-243454cd7bf84c648f244b3587e60d01a0401039.ts +33 -0
  148. package/test/party/components/temp/AnswerButton-server-938e46c1d2510ea37454854ef527e4aa64eb8e52.ts +16 -0
  149. package/test/party/components/temp/FunnyButton-client-2e6bec8259065b5bc9ae16d1ca93dd1bd0c56b7c.ts +40 -0
  150. package/test/party/components/temp/FunnyButton-server-e8ab55e47c735f7e42c55d2b7504dfa4190a1b40.ts +32 -0
  151. package/test/party/components/temp/Time-client-7ba4ca9322af2cb88a873c812fc776760c337c64.ts +47 -0
  152. package/test/party/components/temp/Time-server-08f66c7f3f32b13de06d75fe679cf58b5727c473.ts +31 -0
  153. package/test/party/components/temp/UserProfile-client-938bcef20a2555de22aca939022a32742ac5e729.ts +51 -0
  154. package/test/party/components/temp/UserProfile-server-9df5c59b8797fa67c479bc76450104d45e6076f9.ts +22 -0
  155. package/test/party/components/temp/UserProfileContext-client-93211cdba795b8baf926f60f5b17da90701743b3.ts +44 -0
  156. package/test/party/components/temp/UserProfileContext-server-cf58767df1e2d1dde919f59de73cdd9764bbc006.ts +20 -0
  157. package/test/slots/components/temp/Article-client-741f94eab2e96655f4c9d69ccd7d9c7cc998f4ce.ts +41 -0
  158. package/test/slots/components/temp/Article-server-a6bd47a621cc213db4313eb775a52246541dd203.ts +28 -0
  159. package/test/slots/components/temp/Header-client-e2e1e7d60b48b0841cd0c20224f520330ca96458.ts +38 -0
  160. package/test/slots/components/temp/Header-server-1c195508a91c32822da22a08576c8a30c9070636.ts +22 -0
  161. package/test/slots/components/temp/List-client-0659d999cfb48b865fe5b8aaaf2a4ddac3a8a8b6.ts +76 -0
  162. package/test/slots/components/temp/List-server-4b76485a259d054187edad8aa691d80ac918ad86.ts +25 -0
  163. package/test/special-component/components/temp/BigTitle-client-881a9f84876fb3f6d994736edb253b96e71de926.ts +32 -0
  164. package/test/special-component/components/temp/BigTitle-server-9efc738f5eb131a4b859c4a99a8e255d93834e9a.ts +20 -0
  165. package/test/special-component/components/temp/SmallTitle-client-25b3097b7ae47848dd82967403faf7745fc43388.ts +32 -0
  166. package/test/special-component/components/temp/SmallTitle-server-fc105db9a91b83644d67e049ce583a3d1a61f50c.ts +20 -0
  167. package/tsconfig.json +1 -1
  168. package/tsup.config.ts +7 -2
  169. package/vitest.config.ts +2 -2
  170. package/dist/chunk-GO2L324Q.js.map +0 -1
  171. package/test/bench/components/temp/Bench-client-3efcd3b6c03c7a51368df3b8b1bdf2e7fa722432.ts +0 -126
  172. package/test/build-server/components/IfNested.d.ts +0 -18
  173. package/test/class/components/temp/Class-server-082505b03612c762384ffff329472db3f55b8097.ts +0 -17
  174. /package/test/build-server/components/{output/IfNested-server.ts → temp/IfNested-server-3c4e4b6f2162c0906cef685830219b9ea9ee985c.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { type ControlNode } from "../../types/nodes/ControlNode";
2
2
  import Builder from "../../utils/Builder";
3
3
 
4
- export default function buildServerScriptNode(node: ControlNode, b: Builder) {
4
+ export default function buildServerScriptNode(node: ControlNode, b: Builder): void {
5
5
  b.append(`${maybeAppend(node.statement, ";")}`);
6
6
  }
7
7
 
@@ -17,7 +17,7 @@ export default function buildServerSlotNode(
17
17
  node: ElementNode,
18
18
  status: BuildServerStatus,
19
19
  b: Builder,
20
- ) {
20
+ ): void {
21
21
  // Surround the entire control statement with bracketed comments, so that we
22
22
  // can skip to the end to set the anchor node when hydrating
23
23
  status.output += HYDRATION_START_COMMENT;
@@ -9,7 +9,7 @@ export default function buildServerSpecialNode(
9
9
  node: ElementNode,
10
10
  status: BuildServerStatus,
11
11
  b: Builder,
12
- ) {
12
+ ): void {
13
13
  switch (node.tagName) {
14
14
  case ":slot": {
15
15
  buildServerSlotNode(node, status, b);
@@ -13,7 +13,7 @@ export default function buildServerSwitchNode(
13
13
  node: ControlNode,
14
14
  status: BuildServerStatus,
15
15
  b: Builder,
16
- ) {
16
+ ): void {
17
17
  // Surround the entire control statement with bracketed comments, so that we
18
18
  // can skip to the end to set the anchor node when hydrating
19
19
  status.output += HYDRATION_START_COMMENT;
@@ -1,7 +1,7 @@
1
1
  import { type TextNode } from "../../types/nodes/TextNode";
2
2
  import { type BuildServerStatus } from "./BuildServerStatus";
3
3
 
4
- export default function buildServerTextNode(node: TextNode, status: BuildServerStatus) {
4
+ export default function buildServerTextNode(node: TextNode, status: BuildServerStatus): void {
5
5
  let content = node.content || "";
6
6
 
7
7
  if (!status.preserveWhitespace) {
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @returns True if the supplied string is fully reactive
7
7
  */
8
- export default function isFullyReactive(text: string) {
8
+ export default function isFullyReactive(text: string): boolean {
9
9
  // TODO: Need to be more fancy (check that braces match, ignore comments and strings etc)
10
10
  return text.trim().startsWith("{") && text.trim().endsWith("}");
11
11
  }
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @returns True if the supplied string is fully or partially reactive
7
7
  */
8
- export default function isReactive(text: string) {
8
+ export default function isReactive(text: string): boolean {
9
9
  // TODO: Need to be more fancy (check that braces match, ignore comments and strings etc)
10
10
  return text.includes("{") && text.includes("}");
11
11
  }
@@ -10,7 +10,7 @@ import isReactive from "./isReactive";
10
10
  *
11
11
  * @returns True if the supplied attribute is reactive
12
12
  */
13
- export default function isReactiveAttribute(name: string, value: string) {
13
+ export default function isReactiveAttribute(name: string, value: string): boolean {
14
14
  // TODO: Better checking of whether an attribute is reactive
15
15
  return isFullyReactive(name) || isReactive(value) || name.startsWith("on");
16
16
  }
@@ -5,7 +5,10 @@ import isTextNode from "../types/nodes/isTextNode";
5
5
  import { type ParseStatus } from "./ParseStatus";
6
6
  import consumeSpace from "./utils/consumeSpace";
7
7
 
8
- export default function addSpaceElement(parent: ElementNode | ControlNode, status: ParseStatus) {
8
+ export default function addSpaceElement(
9
+ parent: ElementNode | ControlNode,
10
+ status: ParseStatus,
11
+ ): void {
9
12
  const content = consumeSpace(status);
10
13
  if (content) {
11
14
  const previousNode = parent.children[parent.children.length - 1];
@@ -217,17 +217,21 @@ function parseComponentStyle(status: ParseStatus) {
217
217
  // Skip block comments
218
218
  status.i = status.source.indexOf("*/", status.i) + 1;
219
219
  } else if (char === '"' || char === "'") {
220
+ styleSource += char;
220
221
  // Skip string contents
221
222
  for (let j = status.i + 1; j < status.source.length; j++) {
223
+ styleSource += status.source[j];
222
224
  if (status.source[j] === char && status.source[j - 1] !== "\\") {
223
225
  status.i = j;
224
226
  break;
225
227
  }
226
228
  }
227
229
  } else if (char === "`") {
230
+ styleSource += char;
228
231
  // Skip possibly interpolated string contents
229
232
  let level2 = 0;
230
233
  for (let j = status.i + 1; j < status.source.length; j++) {
234
+ styleSource += status.source[j];
231
235
  if (status.source[j] === char && status.source[j - 1] !== "\\" && level2 === 0) {
232
236
  status.i = j;
233
237
  break;
@@ -34,7 +34,10 @@ const controlOperations = [
34
34
 
35
35
  const standaloneOperations = ["@key", "@html", "@const", "@console", "@debugger", "@function"];
36
36
 
37
- export default function parseControl(status: ParseStatus, parentNode: ElementNode | ControlNode) {
37
+ export default function parseControl(
38
+ status: ParseStatus,
39
+ parentNode: ElementNode | ControlNode,
40
+ ): void {
38
41
  const node = parseControlOpen(status);
39
42
  if (!node) {
40
43
  return;
@@ -2,7 +2,7 @@ import trimQuotes from "../utils/trimQuotes";
2
2
  import trimStartAndEnd from "../utils/trimStartAndEnd";
3
3
  import { type ParseStatus } from "./ParseStatus";
4
4
 
5
- export default function parseImports(status: ParseStatus) {
5
+ export default function parseImports(status: ParseStatus): void {
6
6
  let start = 0;
7
7
  let level = 0;
8
8
  for (let i = 0; i < status.source.length + 1; i++) {
@@ -3,7 +3,7 @@ import parseElement from "./parseElement";
3
3
  import accept from "./utils/accept";
4
4
  import addError from "./utils/addError";
5
5
 
6
- export default function parseMarkup(status: ParseStatus, source: string) {
6
+ export default function parseMarkup(status: ParseStatus, source: string): void {
7
7
  const current = status.components.at(-1);
8
8
  if (!current) return;
9
9
 
@@ -8,7 +8,7 @@ import consumeUntil from "./utils/consumeUntil";
8
8
  import expect from "./utils/expect";
9
9
  import isSpaceChar from "./utils/isSpaceChar";
10
10
 
11
- export default function parseStyles(source: string, status: ParseStatus) {
11
+ export default function parseStyles(source: string, status: ParseStatus): void {
12
12
  const current = status.components.at(-1);
13
13
  if (!current) return;
14
14
 
@@ -5,50 +5,42 @@ import { type StyleBlock } from "../types/styles/StyleBlock";
5
5
  import trimQuotes from "../utils/trimQuotes";
6
6
  import { type ParseStatus } from "./ParseStatus";
7
7
 
8
- export default function scopeStyles(status: ParseStatus) {
8
+ export default function scopeStyles(status: ParseStatus): void {
9
9
  let selectors: string[] = [];
10
10
  for (let component of status.components) {
11
11
  if (component.style && component.markup) {
12
12
  for (let block of component.style.blocks) {
13
13
  collectStyleSelectors(block, selectors);
14
14
  }
15
- scopeStylesOnNode(component.markup, selectors, component.style.hash);
15
+ scopeStylesOnNode(component.markup, selectors);
16
16
  }
17
17
  }
18
18
  }
19
19
 
20
- function scopeStylesOnNode(node: TemplateNode, selectors: string[], styleHash: string) {
20
+ function scopeStylesOnNode(node: TemplateNode, selectors: string[]) {
21
21
  if (isElementNode(node)) {
22
- let addClass = selectors.includes(node.tagName);
23
- if (!addClass) {
22
+ let scopeStyles = selectors.includes(node.tagName);
23
+ if (!scopeStyles) {
24
24
  for (let a of node.attributes) {
25
25
  if (a.name === "class" || a.name === ":class") {
26
- addClass = true;
26
+ scopeStyles = true;
27
27
  } else if (a.name === "id" && a.value) {
28
- addClass = selectors.includes(`#${trimQuotes(a.value)}`);
28
+ scopeStyles = selectors.includes(`#${trimQuotes(a.value)}`);
29
29
  } else if (a.name === "class" && a.value) {
30
30
  // TODO: Never getting here?
31
- addClass = selectors.includes(`.${trimQuotes(a.value)}`);
31
+ scopeStyles = selectors.includes(`.${trimQuotes(a.value)}`);
32
+ }
33
+ if (scopeStyles) {
34
+ break;
32
35
  }
33
- if (addClass) break;
34
- }
35
- }
36
- if (addClass) {
37
- let classAttribute = node.attributes.find((a) => a.name === "class");
38
- if (classAttribute && classAttribute.value) {
39
- classAttribute.value = `"${trimQuotes(classAttribute.value)} torp-${styleHash}"`;
40
- } else {
41
- node.attributes.push({
42
- name: "class",
43
- value: `"torp-${styleHash}"`,
44
- });
45
36
  }
46
37
  }
38
+ node.scopeStyles = scopeStyles;
47
39
  }
48
40
 
49
41
  if (isParentNode(node)) {
50
42
  for (let child of node.children) {
51
- scopeStylesOnNode(child, selectors, styleHash);
43
+ scopeStylesOnNode(child, selectors);
52
44
  }
53
45
  }
54
46
  }
@@ -6,7 +6,7 @@ import isSpecialNode from "../types/nodes/isSpecialNode";
6
6
  * Moves any child nodes that aren't already in a <:fill> node into a default
7
7
  * <:fill> node
8
8
  */
9
- export default function slottifyChildNodes(node: ElementNode) {
9
+ export default function slottifyChildNodes(node: ElementNode): void {
10
10
  const nonFillNodes = node.children.filter((c) => !isFillNode(c));
11
11
  // TODO: Not if it's only spaces??
12
12
  if (nonFillNodes.length) {
@@ -8,7 +8,11 @@ import { type ParseStatus } from "../ParseStatus";
8
8
  * @param start (Optional) The start position of the error (defaults to the
9
9
  * current parse position)
10
10
  */
11
- export default function addError(status: ParseStatus, message: string, start: number = status.i) {
11
+ export default function addError(
12
+ status: ParseStatus,
13
+ message: string,
14
+ start: number = status.i,
15
+ ): void {
12
16
  let line = 1;
13
17
  let lastLineStart = 0;
14
18
  for (let i = 0; i < start; i++) {
@@ -10,7 +10,7 @@ import { type ParseStatus } from "../ParseStatus";
10
10
  * @returns The string of characters from the current parse position to the
11
11
  * found character
12
12
  */
13
- export default function consumeUntil(chars: string, status: ParseStatus) {
13
+ export default function consumeUntil(chars: string, status: ParseStatus): string {
14
14
  const start = status.i;
15
15
  for (status.i; status.i < status.source.length; status.i++) {
16
16
  if (chars.includes(status.source[status.i])) {
@@ -7,7 +7,7 @@ import isAlphaNumericChar from "./isAlphaNumericChar";
7
7
  *
8
8
  * @returns True if the supplied string contains only alpha-numeric characters
9
9
  */
10
- export default function isAlphaNumeric(text: string) {
10
+ export default function isAlphaNumeric(text: string): boolean {
11
11
  for (let i = 0; i < text.length; i++) {
12
12
  if (!isAlphaNumericChar(text, i)) {
13
13
  return false;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @returns True if the supplied character is alpha-numeric
8
8
  */
9
- export default function isAlphaNumericChar(text: string, index: number) {
9
+ export default function isAlphaNumericChar(text: string, index: number): boolean {
10
10
  let code = text.charCodeAt(index);
11
11
  return (
12
12
  // 0-9
@@ -7,7 +7,7 @@ import isSpaceChar from "./isSpaceChar";
7
7
  *
8
8
  * @returns True if the supplied string contains only space characters
9
9
  */
10
- export default function isSpace(text: string) {
10
+ export default function isSpace(text: string): boolean {
11
11
  for (let i = 0; i < text.length; i++) {
12
12
  if (!isSpaceChar(text, i)) {
13
13
  return false;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @returns True if the supplied character is a space
8
8
  */
9
- export default function isSpaceChar(text: string, index: number) {
9
+ export default function isSpaceChar(text: string, index: number): boolean {
10
10
  let code = text.charCodeAt(index);
11
11
  return code === 32 || (code >= 9 && code <= 13);
12
12
  }
@@ -3,6 +3,9 @@ import { type NodeType } from "./NodeType";
3
3
  export type TemplateNode = {
4
4
  type: NodeType;
5
5
 
6
+ // Whether to add a scoped class name
7
+ scopeStyles?: boolean;
8
+
6
9
  // This gets set when building
7
10
  // For element and text nodes, it is the name of the element that is created
8
11
  // For control nodes, it is the name of the anchor element
@@ -2,11 +2,11 @@ export default class Builder {
2
2
  #text = "";
3
3
  #space = 0;
4
4
 
5
- prepend(text: string) {
5
+ prepend(text: string): void {
6
6
  this.#text = text + "\n" + this.#text;
7
7
  }
8
8
 
9
- append(text: string) {
9
+ append(text: string): void {
10
10
  text = text.trim();
11
11
  let i = 0;
12
12
  //let newline = !!text.length && !text.endsWith("\n");
@@ -69,7 +69,7 @@ export default class Builder {
69
69
  }
70
70
  }
71
71
 
72
- toString() {
72
+ toString(): string {
73
73
  return this.#text;
74
74
  }
75
75
  }
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @returns The text without the char on the end
8
8
  */
9
- export default function trimEnd(text: string, char: string) {
9
+ export default function trimEnd(text: string, char: string): string {
10
10
  let end = text.length;
11
11
  while (text[end - 1] === char) {
12
12
  end -= 1;
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @returns The text without the chars at the start or the end
7
7
  */
8
- export default function trimMatched(text: string, startChar: string, endChar: string) {
8
+ export default function trimMatched(text: string, startChar: string, endChar: string): string {
9
9
  let start = 0;
10
10
  let end = text.length;
11
11
  while (text[start] === startChar && text[end - 1] === endChar) {
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @returns The text without the quotes at the start or the end
7
7
  */
8
- export default function trimQuotes(text: string) {
8
+ export default function trimQuotes(text: string): string {
9
9
  let start = 0;
10
10
  let end = text.length;
11
11
  while (
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @returns The text without the char on the start
8
8
  */
9
- export default function trimStart(text: string, char: string) {
9
+ export default function trimStart(text: string, char: string): string {
10
10
  let start = 0;
11
11
  while (text[start] === char) {
12
12
  start += 1;
@@ -10,6 +10,6 @@ import trimStart from "./trimStart";
10
10
  *
11
11
  * @returns The text without the char at the start or the end
12
12
  */
13
- export default function trimStartAndEnd(text: string, startChar: string, endChar: string) {
13
+ export default function trimStartAndEnd(text: string, startChar: string, endChar: string): string {
14
14
  return trimEnd(trimStart(text, startChar), endChar);
15
15
  }
@@ -1,5 +1,5 @@
1
1
  // From https://developer.mozilla.org/en-US/docs/Glossary/Void_element
2
- const voidTags = [
2
+ const voidTags: string[] = [
3
3
  "area",
4
4
  "base",
5
5
  "br",
@@ -1,4 +1,4 @@
1
- export default function printHtml(html: string) {
1
+ export default function printHtml(html: string): string {
2
2
  let lines = html
3
3
  .replaceAll("<", "\n<")
4
4
  .replaceAll(">", ">\n")
@@ -12,7 +12,7 @@ export default async function animate(
12
12
  enter: boolean,
13
13
  keyframes: Keyframe[] | PropertyIndexedKeyframes | null,
14
14
  options?: number | KeyframeAnimationOptions,
15
- ) {
15
+ ): Promise<void> {
16
16
  // This is quite simplistic
17
17
  // We might need to
18
18
  // - store the animation
@@ -6,6 +6,6 @@ import context from "./context";
6
6
  *
7
7
  * @param fn The function to run, which may return a cleanup function
8
8
  */
9
- export default function $mount(fn: () => Cleanup | void) {
9
+ export default function $mount(fn: () => Cleanup | void): void {
10
10
  context.mountEffects.push(fn);
11
11
  }
@@ -10,7 +10,7 @@ import context from "./context";
10
10
  *
11
11
  * @param fn The function to run, which may return a cleanup function
12
12
  */
13
- export default function $run(fn: () => Cleanup | void) {
13
+ export default function $run(fn: () => Cleanup | void): void {
14
14
  let effect: Effect = {
15
15
  run: fn,
16
16
  cleanup: null,
@@ -1,3 +1,3 @@
1
1
  import { type Cleanup } from "../types/Cleanup";
2
2
 
3
- export default function $serverMount(_: () => Cleanup | void) {}
3
+ export default function $serverMount(_: () => Cleanup | void): void {}
@@ -1,3 +1,3 @@
1
1
  import { type Cleanup } from "../types/Cleanup";
2
2
 
3
- export default function $serverRun(_: () => Cleanup | void) {}
3
+ export default function $serverRun(_: () => Cleanup | void): void {}
@@ -1 +1 @@
1
- export default function $stream() {}
1
+ export default function $stream(): void {}
@@ -1,7 +1,7 @@
1
1
  import { type Animation } from "../types/Animation";
2
2
  import context from "./context";
3
3
 
4
- export default function addAnimation(el: HTMLElement, entry?: Animation, exit?: Animation) {
4
+ export default function addAnimation(el: HTMLElement, entry?: Animation, exit?: Animation): void {
5
5
  // Stash the event in context so that it can be added when the fragment is
6
6
  // added to the DOM
7
7
  // NOTE: We don't need to do this for hydration, but it's simpler to do it
@@ -4,7 +4,7 @@ export default function addEvent(
4
4
  el: Element,
5
5
  type: string,
6
6
  listener: (this: Element, ev: any) => any,
7
- ) {
7
+ ): void {
8
8
  // Stash the event in context so that it can be added when the fragment is
9
9
  // added to the DOM
10
10
  // NOTE: We don't need to do this for hydration, but it's simpler to do it
@@ -6,7 +6,7 @@ export default function addFragment(
6
6
  fragment: DocumentFragment,
7
7
  parent: ParentNode,
8
8
  before: Node | null,
9
- ) {
9
+ ): void {
10
10
  //console.log(`adding fragment '${fragment.textContent}' to ${printNode(parent)}`);
11
11
  //console.log("before", printNode(before));
12
12
 
@@ -4,7 +4,7 @@ export default function applyProps(
4
4
  el: Element,
5
5
  props: Record<string, any> | undefined,
6
6
  propNamesUsed: string[],
7
- ) {
7
+ ): void {
8
8
  if (props) {
9
9
  for (let [name, value] of Object.entries(props)) {
10
10
  if (!propNamesUsed.includes(name)) {
@@ -2,7 +2,7 @@ import { type Range } from "../types/Range";
2
2
  import removeEffect from "../watch/removeEffect";
3
3
  import context from "./context";
4
4
 
5
- export default function clearRange(range: Range) {
5
+ export default function clearRange(range: Range): void {
6
6
  //console.log(`clearing range ${printNode(range.startNode)} to ${printNode(range.endNode)}`);
7
7
 
8
8
  // Clear effects and collect animations that take place within this range and its children
@@ -1,3 +1,3 @@
1
- export default function createComment(content?: string) {
1
+ export default function createComment(content?: string): Comment {
2
2
  return document.createComment(content || "");
3
3
  }
@@ -2,7 +2,7 @@ export default function createElement(
2
2
  tagName: string,
3
3
  attributes: Record<string, string>,
4
4
  children: Node[],
5
- ) {
5
+ ): HTMLElement {
6
6
  let el = document.createElement(tagName);
7
7
  // Set any attributes that aren't reactive
8
8
  // Reactive attributes will be set in $run effects
@@ -1,4 +1,4 @@
1
- export default function createFragment(children: Node[]) {
1
+ export default function createFragment(children: Node[]): DocumentFragment {
2
2
  let el = document.createDocumentFragment();
3
3
  for (let child of children) {
4
4
  el.appendChild(child);
@@ -1,4 +1,4 @@
1
- export default function createText(content: string) {
1
+ export default function createText(content: string): Text {
2
2
  return document.createTextNode(isReactiveText(content) ? " " : content);
3
3
  }
4
4
 
@@ -1,7 +1,7 @@
1
1
  import $run from "./$run";
2
2
  import context from "./context";
3
3
 
4
- export default function flushMountEffects() {
4
+ export default function flushMountEffects(): void {
5
5
  for (let fn of context.mountEffects) {
6
6
  $run(fn);
7
7
  }
@@ -1,6 +1,9 @@
1
- export default function getClasses(value: unknown): string {
1
+ export default function getClasses(value: unknown, styleHash?: string): string {
2
2
  let classes: string[] = [];
3
3
  gatherNames("", value, classes);
4
+ if (styleHash) {
5
+ classes.push(styleHash);
6
+ }
4
7
  return classes.join(" ");
5
8
  }
6
9
 
@@ -13,7 +13,7 @@ export default function hydrate(
13
13
  component: Component,
14
14
  props?: Record<string, any>,
15
15
  slots?: Record<string, SlotRender>,
16
- ) {
16
+ ): void {
17
17
  // When mounting, the parent must have no child elements, so we can just set
18
18
  // the hydration node to the first child node
19
19
  context.hydrationNode = parent.firstChild;
@@ -19,7 +19,7 @@ export default function hydrateRoot(
19
19
  component: Component,
20
20
  props?: Record<string, any>,
21
21
  slots?: Record<string, SlotRender>,
22
- ) {
22
+ ): void {
23
23
  let html = document.documentElement;
24
24
 
25
25
  // With server side rendering, we start hydrating at the <html> element
@@ -13,7 +13,7 @@ export default function mount(
13
13
  component: Component,
14
14
  props?: Record<string, any>,
15
15
  slots?: Record<string, SlotRender>,
16
- ) {
16
+ ): void {
17
17
  // The parent node must have no child elements, so that we can hydrate
18
18
  // without worrying about where to start
19
19
  if (parent.childElementCount) {
@@ -1,6 +1,6 @@
1
1
  import { type Range } from "../types/Range";
2
2
 
3
- export default function moveRange(parent: Node, range: Range, before: ChildNode | null) {
3
+ export default function moveRange(parent: Node, range: Range, before: ChildNode | null): void {
4
4
  const endNode = range.endNode || range.startNode;
5
5
  let currentNode = range.startNode;
6
6
  while (currentNode) {
@@ -1,6 +1,6 @@
1
1
  import { type Range } from "../types/Range";
2
2
  import context from "./context";
3
3
 
4
- export default function popRange(oldRange: Range | null) {
4
+ export default function popRange(oldRange: Range | null): void {
5
5
  context.activeRange = oldRange;
6
6
  }
@@ -12,7 +12,7 @@ export default function runControl(
12
12
  range: Range,
13
13
  anchor: Node | null,
14
14
  create: (anchor: Node | null) => void,
15
- ) {
15
+ ): void {
16
16
  // Store the index in the range so that it can be accessed by the statement's
17
17
  // branches
18
18
  range.index = -1;
@@ -4,7 +4,7 @@ import newRange from "./newRange";
4
4
  import popRange from "./popRange";
5
5
  import pushRange from "./pushRange";
6
6
 
7
- export default function runControlBranch(range: Range, index: number, create: () => void) {
7
+ export default function runControlBranch(range: Range, index: number, create: () => void): void {
8
8
  // Only run the branch if it's not the current branch
9
9
  if (index >= 0 && range.index === index) {
10
10
  return;
@@ -16,7 +16,7 @@ export default function runList(
16
16
  anchor: Node | null,
17
17
  buildItems: () => ListItem[],
18
18
  create: (item: ListItem, anchor: Node | null) => void,
19
- ) {
19
+ ): void {
20
20
  const oldRange = pushRange(range, true);
21
21
 
22
22
  let listItems: ListItem[] = [];