kireji 0.5.0 → 0.6.6

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 (154) hide show
  1. package/package.json +1 -1
  2. package/src/app/kireji/attributes_.js +3 -0
  3. package/src/app/kireji/editor/part.json +13 -11
  4. package/src/app/kireji/editor/point.js +2 -1
  5. package/src/app/kireji/editor/sections/properties/part.html_.js +5 -5
  6. package/src/app/kireji/editor/sections/section/part.json +6 -4
  7. package/src/app/kireji/editor/sections/section/view-update.js +8 -0
  8. package/src/app/kireji/editor/sections/state-space/part.html_.js +4 -4
  9. package/src/app/kireji/editor/tab-group/build.js +2 -30
  10. package/src/app/kireji/editor/tab-group/listeners-attach.js +2 -1
  11. package/src/app/kireji/editor/tab-group/listeners-detach.js +2 -1
  12. package/src/app/kireji/editor/tab-group/part.css +1 -1
  13. package/src/app/kireji/editor/tab-group/part.json +26 -24
  14. package/src/app/kireji/editor/tab-group/routeID-distribute.js +1 -1
  15. package/src/app/kireji/editor/tab-group/routeID-get-permutation.js +1 -1
  16. package/src/app/kireji/editor/tab-group/type.d.ts +0 -9
  17. package/src/app/kireji/editor/tab-group/{view-add.js → view-hydrate.js} +5 -7
  18. package/src/app/kireji/editor/tab-group/view-update.js +115 -0
  19. package/src/app/kireji/sidebar/open/view-update.js +10 -0
  20. package/src/app/kireji/sidebar/part.json +3 -1
  21. package/src/app/kireji/sidebar/width/part.json +6 -4
  22. package/src/app/kireji/tool-bar/button/view-add.js +5 -7
  23. package/src/app/kireji/tool-bar/part.css +1 -1
  24. package/src/app/kireji/tool-bar/part.json +7 -5
  25. package/src/application-goto.js +1 -1
  26. package/src/build.js +102 -21
  27. package/src/images-inject.js +34 -0
  28. package/src/part.html_.js +39 -60
  29. package/src/part.json +21 -20
  30. package/src/parts/abstract/application/attributes_.js +3 -0
  31. package/src/parts/abstract/application/classes_.js +1 -0
  32. package/src/parts/abstract/application/type.d.ts +2 -2
  33. package/src/parts/abstract/body-mode/view-add.js +0 -1
  34. package/src/parts/abstract/boolean/part.json +5 -3
  35. package/src/parts/abstract/clip/build.js +0 -1
  36. package/src/parts/abstract/clip/loop.js +12 -0
  37. package/src/parts/abstract/clip/part.json +6 -4
  38. package/src/parts/abstract/clip/playback-stop.js +0 -5
  39. package/src/parts/abstract/error/part.json +13 -11
  40. package/src/parts/abstract/error/type.d.ts +1 -1
  41. package/src/parts/abstract/facet/part.json +10 -8
  42. package/src/parts/abstract/match/build.js +15 -13
  43. package/src/parts/abstract/match/equation.html_.js +1 -1
  44. package/src/parts/abstract/match/part.json +6 -4
  45. package/src/parts/abstract/match/routeID-collect.js +2 -11
  46. package/src/parts/abstract/mix/build.js +12 -10
  47. package/src/parts/abstract/mix/model_.js +1 -1
  48. package/src/parts/abstract/mix/part.json +6 -4
  49. package/src/parts/abstract/part/build.js +7 -1
  50. package/src/parts/abstract/part/constants.js +2 -5
  51. package/src/parts/abstract/part/manifest-resolve-owner-of.js +6 -0
  52. package/src/parts/abstract/part/manifest-resolve-part-from.js +10 -0
  53. package/src/parts/abstract/part/part.json +76 -68
  54. package/src/parts/abstract/part/routeID-set.js +20 -7
  55. package/src/parts/abstract/part/type.d.ts +44 -19
  56. package/src/parts/abstract/part/view-collect-update.js +13 -0
  57. package/src/parts/abstract/part/view-distribute-hydrate.js +10 -0
  58. package/src/parts/abstract/part/view-distribute-update.js +14 -0
  59. package/src/parts/abstract/part/view-update.js +0 -0
  60. package/src/parts/abstract/part-mask/part.json +3 -1
  61. package/src/parts/abstract/part-outliner/folders/view-update.js +18 -0
  62. package/src/parts/abstract/part-outliner/part.json +29 -27
  63. package/src/parts/abstract/part-outliner/point-toggle.js +0 -20
  64. package/src/parts/abstract/permutation/build.js +1 -30
  65. package/src/parts/abstract/permutation/part.json +45 -43
  66. package/src/parts/abstract/permutation/routeID-distribute.js +1 -4
  67. package/src/parts/abstract/permutation/routeID-get-permutation.js +1 -1
  68. package/src/parts/abstract/permutation/type.d.ts +0 -6
  69. package/src/parts/abstract/permutation/view-hydrate.js +3 -0
  70. package/src/parts/abstract/permutation/view-update.js +32 -0
  71. package/src/parts/abstract/scroller/build.js +4 -0
  72. package/src/parts/abstract/scroller/constants.js +0 -1
  73. package/src/parts/abstract/scroller/part.json +16 -14
  74. package/src/parts/abstract/scroller/view-add.js +1 -20
  75. package/src/parts/abstract/scroller/view-hydrate.js +19 -0
  76. package/src/parts/abstract/scroller/view-remove.js +4 -2
  77. package/src/parts/abstract/scroller/view-update.js +7 -0
  78. package/src/parts/core/address-bar/part.json +6 -4
  79. package/src/parts/core/client/async-install.js +53 -6
  80. package/src/parts/core/client/build.js +1 -15
  81. package/src/parts/core/client/description +1 -1
  82. package/src/parts/core/client/part.json +1 -4
  83. package/src/parts/core/hot-keys/combo_.js +7 -7
  84. package/src/parts/core/hot-keys/part.json +4 -2
  85. package/src/parts/core/pointer/constants.js +1 -0
  86. package/src/parts/core/pointer/handle.js +7 -1
  87. package/src/parts/core/pointer/part.json +5 -3
  88. package/src/parts/core/server/sync-install.js +4 -8
  89. package/src/parts/core/update/part.json +9 -7
  90. package/src/parts/core/worker/part.html_.js +1 -1
  91. package/src/parts/core/worker/part.json +6 -4
  92. package/src/parts/core/worker/sync-install.js +0 -1
  93. package/src/parts/desktop/attributes_.js +3 -1
  94. package/src/parts/desktop/color/part.json +19 -17
  95. package/src/parts/desktop/color/type.d.ts +3 -3
  96. package/src/parts/desktop/era/part.json +6 -4
  97. package/src/parts/desktop/era/type.d.ts +3 -3
  98. package/src/parts/desktop/era/vintage/static.css +25 -6
  99. package/src/parts/desktop/icons/part.json +6 -4
  100. package/src/parts/desktop/icons/view-update.js +13 -0
  101. package/src/parts/desktop/task-bar/menu/classes_.js +9 -0
  102. package/src/parts/desktop/task-bar/menu/clip/type.d.ts +1 -1
  103. package/src/parts/desktop/task-bar/menu/clip/view-update.js +1 -0
  104. package/src/parts/desktop/task-bar/menu/closed/view-add.js +1 -1
  105. package/src/parts/desktop/task-bar/menu/closed/view-remove.js +1 -1
  106. package/src/parts/desktop/task-bar/menu/introduce/view-add.js +1 -2
  107. package/src/parts/desktop/task-bar/menu/introduce/view-hydrate.js +1 -0
  108. package/src/parts/desktop/task-bar/menu/menu.html_.js +1 -1
  109. package/src/parts/desktop/task-bar/menu/opened/view-add.js +1 -4
  110. package/src/parts/desktop/task-bar/menu/opened/view-remove.js +1 -3
  111. package/src/parts/desktop/task-bar/menu/part.json +6 -4
  112. package/src/parts/desktop/task-bar/menu/type.d.ts +2 -0
  113. package/src/parts/desktop/task-bar/tray/item/part.json +6 -4
  114. package/src/parts/desktop/task-bar/view-hydrate.js +21 -0
  115. package/src/parts/desktop/windows/HTML-render-task.js +1 -1
  116. package/src/parts/desktop/windows/part.json +23 -21
  117. package/src/parts/desktop/windows/point.js +4 -3
  118. package/src/parts/desktop/windows/{view-add.js → view-hydrate.js} +1 -1
  119. package/src/route-set.js +5 -5
  120. package/src/type.d.ts +22 -24
  121. package/src/validate.js +0 -4
  122. package/src/view-hydrate.js +12 -0
  123. package/src/app/kireji/editor/sections/section/view-populate.js +0 -10
  124. package/src/app/kireji/editor/tab-group/view-populate.js +0 -116
  125. package/src/app/kireji/sidebar/open/view-populate.js +0 -12
  126. package/src/app/kireji/style_.js +0 -1
  127. package/src/early-get-images.js +0 -25
  128. package/src/parts/abstract/clip/view-add.js +0 -1
  129. package/src/parts/abstract/clip/view-populate.js +0 -20
  130. package/src/parts/abstract/part/view-collect-populate.js +0 -13
  131. package/src/parts/abstract/part/view-distribute-populate.js +0 -14
  132. package/src/parts/abstract/part-outliner/folders/view-populate.js +0 -20
  133. package/src/parts/abstract/permutation/view-add.js +0 -4
  134. package/src/parts/abstract/permutation/view-populate.js +0 -36
  135. package/src/parts/abstract/scroller/view-populate.js +0 -17
  136. package/src/parts/desktop/icons/view-populate.js +0 -15
  137. package/src/parts/desktop/task-bar/menu/clip/view-populate.js +0 -2
  138. package/src/parts/desktop/task-bar/menu/introduce/view-remove.js +0 -2
  139. package/src/parts/desktop/task-bar/view-add.js +0 -20
  140. package/src/parts/desktop/windows/view-populate.js +0 -1
  141. package/src/view-add.js +0 -22
  142. /package/src/app/kireji/sidebar/{view-add.js → view-hydrate.js} +0 -0
  143. /package/src/app/kireji/sidebar/width/{view-populate.js → view-update.js} +0 -0
  144. /package/src/parts/abstract/application/{view-add.js → view-hydrate.js} +0 -0
  145. /package/src/parts/abstract/part/{view-populate.js → view-hydrate.js} +0 -0
  146. /package/src/parts/desktop/color/{view-populate.js → view-update.js} +0 -0
  147. /package/src/parts/desktop/era/{view-populate.js → view-update.js} +0 -0
  148. /package/src/parts/desktop/task-bar/menu/closed/{attr-style → style} +0 -0
  149. /package/src/parts/desktop/task-bar/menu/introduce/{attr-style_.js → style_.js} +0 -0
  150. /package/src/parts/desktop/task-bar/menu/opened/{attr-style → style} +0 -0
  151. /package/src/parts/desktop/task-bar/menu/{view-add.js → view-hydrate.js} +0 -0
  152. /package/src/parts/desktop/task-bar/tray/clock/{view-add.js → view-hydrate.js} +0 -0
  153. /package/src/parts/desktop/task-bar/tray/item/{view-add.js → view-hydrate.js} +0 -0
  154. /package/src/{view-populate.js → view-update.js} +0 -0
package/src/build.js CHANGED
@@ -77,6 +77,43 @@ function ƒ(_, compressedSubjectOrigins) {
77
77
  btoaUnicode = string => btoa(new TextEncoder("utf-8").encode(string).reduce((data, byte) => data + String.fromCharCode(byte), "")),
78
78
  sanitizeAttr = string => string.replaceAll(/&/g, '&amp;').replaceAll(/"/g, '&quot;').replaceAll(/'/g, '&#39;').replaceAll(/</g, '&lt;').replaceAll(/>/g, '&gt;')
79
79
 
80
+ // Math Utilities
81
+ class FenwickTree {
82
+ static LSB = []
83
+ constructor(size) {
84
+
85
+ const oldSize = BigInt(FenwickTree.LSB.length)
86
+
87
+ for (let newSize = oldSize + 1n; newSize <= size; newSize++)
88
+ FenwickTree.LSB[newSize - 1n] = newSize & -newSize
89
+
90
+ this.size = size
91
+ this.tree = FenwickTree.LSB.slice(0, Number(size))
92
+ this.powerFloor = 2n ** BigInt(size.toString(2).length - 1)
93
+ }
94
+ update(i, val) {
95
+ for (; i < this.size; i += FenwickTree.LSB[i])
96
+ this.tree[i] += val
97
+ }
98
+ query(i) {
99
+ let sum = 0n
100
+ for (; i >= 0n; i -= FenwickTree.LSB[i])
101
+ sum += this.tree[i]
102
+ return sum
103
+ }
104
+ findNthAvailable(n) {
105
+ let nthAvailable = 0n
106
+ for (let p = this.powerFloor; p > 0n; p /= 2n) {
107
+ const i = nthAvailable + p
108
+ if (i <= this.size && this.tree[i - 1n] <= n) {
109
+ n -= this.tree[i - 1n]
110
+ nthAvailable = i
111
+ }
112
+ }
113
+ return nthAvailable
114
+ }
115
+ }
116
+
80
117
  // Random Number Generation
81
118
  const
82
119
  randomBits = bitCount => {
@@ -476,6 +513,8 @@ function ƒ(_, compressedSubjectOrigins) {
476
513
  }
477
514
  }
478
515
 
516
+ let buildTimeHydrationIsComplete = false
517
+
479
518
  const
480
519
  hydrationStartTime = Date.now(),
481
520
  instances = [],
@@ -484,6 +523,27 @@ function ƒ(_, compressedSubjectOrigins) {
484
523
  earlyImageSources = [],
485
524
  partsByHost = {},
486
525
  preHydrationArchive = serialize(_),
526
+ resolveRelativeHost = (relativeHost, base) => {
527
+
528
+ if (typeof relativeHost !== "string")
529
+ throw new TypeError(`Resolve Relative Host Error: the given relative host must be a string (got ${typeof relativeHost}).`)
530
+
531
+ const relativeStepsBack = relativeHost.match(/\.*$/)[0].length
532
+
533
+ if (relativeStepsBack) {
534
+ if (typeof base === "string")
535
+ base = base.split(".")
536
+ else if (!Array.isArray(base))
537
+ throw new TypeError(`Cannot resolve relative host "${relativeHost}" because the given base is not an absolute string host or an array of domains.`)
538
+
539
+ return `${relativeHost.slice(0, -relativeStepsBack)}.${base.slice(relativeStepsBack - 1).join(".")}`
540
+ }
541
+
542
+ if (relativeHost.includes("."))
543
+ return relativeHost
544
+
545
+ return `${relativeHost}.abstract.parts`
546
+ },
487
547
  hydratePartsRecursive = (part, domains = []) => {
488
548
 
489
549
  let host
@@ -520,21 +580,34 @@ function ƒ(_, compressedSubjectOrigins) {
520
580
  })
521
581
  let prototype = null
522
582
  if (host === "part.abstract.parts") {
523
- Object.defineProperty(part, "define", { value(descriptor) { return Object.defineProperties(this, descriptor) } })
583
+ Object.defineProperty(part, "define", {
584
+ value(descriptorMap) {
585
+ // Resolve late-bound properties in the order they were added to the descriptor map.
586
+ for (const propertyKey of Reflect.ownKeys(descriptorMap)) {
587
+ const propertyDescriptor = descriptorMap[propertyKey]
588
+ if ("resolve" in propertyDescriptor) {
589
+ propertyDescriptor.value = propertyDescriptor.resolve.call(this)
590
+ delete propertyDescriptor.resolve
591
+ }
592
+ Object.defineProperty(this, propertyKey, propertyDescriptor)
593
+ }
594
+ return this
595
+ }
596
+ })
524
597
  part.define({ isAbstract: { value: part.manifest.abstract } })
525
598
  } else {
526
- const extendsString = part.manifest.extends ?? "part"
527
- const relativeStepsBack = extendsString.match(/\.*$/)[0].length
528
- const typename = relativeStepsBack ? `${extendsString.slice(0, -relativeStepsBack)}.${domains.slice(relativeStepsBack - 1).join(".")}` : extendsString.includes(".") ? extendsString : `${extendsString}.abstract.parts`
529
- prototype = hydratePartsRecursive(typename)
599
+ prototype = hydratePartsRecursive(resolveRelativeHost(part.manifest.extends ?? "part", domains))
530
600
  if (!prototype.isAbstract)
531
601
  throw new Error(`Hydration Error: parts can only extend abstract parts (${host} tried to extend ${prototype.host}).`)
532
602
  Object.setPrototypeOf(part, prototype)
533
603
  part.define({
534
604
  isAbstract: { value: part.manifest.abstract }
535
605
  })
606
+ part.manifest.methods ??= {}
536
607
  Object.setPrototypeOf(part.manifest, prototype.manifest)
537
- prototype.inheritors.push(part)
608
+ Object.setPrototypeOf(part.manifest.methods, prototype.manifest.methods)
609
+ if (!buildTimeHydrationIsComplete)
610
+ prototype.inheritors.push(part)
538
611
  }
539
612
  const sourceFile = new SourceMappedFile(pathFromRepo, pathToRepo, "compiled-part.js")
540
613
  const buildSource = sourceFile.addSource(pathToRepo + "/build.js", ƒ.toString())
@@ -640,10 +713,10 @@ function ƒ(_, compressedSubjectOrigins) {
640
713
  property.niceNameIsValidIdentifier = property.isSymbol || property.isGenerated || Property.identifierPattern.test(property.niceName)
641
714
  property.propertyReference = property.niceNameIsValidIdentifier ? property.niceName : `["${property.niceName}"]`
642
715
  property.propertyAccessor = property.propertyReference.startsWith("[") ? property.propertyReference : "." + property.niceName
643
- const args = part.manifest[PROPERTY_ID];
716
+ const args = part.manifest.methods[PROPERTY_ID]
644
717
  const errorIndex = args?.findIndex(arg => !arg || typeof arg !== "string") ?? -1
645
718
  if (errorIndex !== -1)
646
- throw `Invalid method argument\n\t_.${[...domains].reverse().join(".")}.manifest["${PROPERTY_ID}"][${errorIndex}]\n\tAll arguments must be non-empty strings.`
719
+ throw `Invalid method argument\n\t_.${[...domains].reverse().join(".")}.manifest.methods["${PROPERTY_ID}"][${errorIndex}]\n\tAll arguments must be non-empty strings.`
647
720
  property.argumentString = "(" + (args?.join(", ") ?? (PROPERTY_ID.startsWith("set-") ? "VALUE" : "")) + ")"
648
721
  property.modifiers = property.isAsync ? "async " : (property.isGenerated || property.isAlias ? "get " : "")
649
722
  property.signature = "\n\n " + property.propertyReference + `: {\n ${(property.isGenerated || property.isAlias) ? property.modifiers : ((property.isAsync ? property.modifiers : "") + "value")}${property.argumentString} {`
@@ -656,38 +729,43 @@ function ƒ(_, compressedSubjectOrigins) {
656
729
  }
657
730
  part.define({
658
731
  Property: { value: Property },
659
- prototype: { value: Object.getPrototypeOf(part) }
732
+ prototype: { value: prototype }
660
733
  })
734
+
661
735
  for (const fn of part.filenames) {
662
736
  if (!fn.includes(".") && fn.includes("-")) {
663
737
  Property.ids.add("@" + fn)
664
738
  } else if (fn.endsWith("_.js") || fn.endsWith(".js") && (fn.startsWith("set-") || fn.startsWith("view-"))) {
665
739
  Property.ids.add(fn.slice(0, -3))
666
-
667
740
  if (fn.endsWith(".png_.js") || fn.endsWith(".gif_.js")) {
741
+ if (buildTimeHydrationIsComplete)
742
+ throw new Error(`Adding images to runtime part instances is currently not supported.`)
668
743
  if (fn.startsWith("early-"))
669
744
  earlyImageSources.push([part, fn.slice(6, -4)])
670
745
  imageSources.push([part, fn.slice(0, -4)])
671
746
  }
672
747
  } else if (fn.endsWith(".png") || fn.endsWith(".gif")) {
748
+ if (buildTimeHydrationIsComplete)
749
+ throw new Error(`Adding images to runtime part instances is currently not supported.`)
673
750
  if (fn.startsWith("early-"))
674
751
  earlyImageSources.push([part, fn.slice(6)])
675
752
  imageSources.push([part, fn])
676
753
  }
677
- subjectIndices.set(`${host}/${fn}`, allSubjects.length)
678
- allSubjects.push([host, fn])
754
+ if (!buildTimeHydrationIsComplete) {
755
+ subjectIndices.set(`${host}/${fn}`, allSubjects.length)
756
+ allSubjects.push([host, fn])
757
+ }
679
758
  }
680
- for (const methodID in part.manifest)
681
- if (!["extends", "abstract"].includes(methodID))
682
- Property.ids.add(methodID)
759
+
760
+ for (const methodID in part.manifest.methods)
761
+ Property.ids.add(methodID)
683
762
 
684
763
  sourceFile.addSection(`@descriptor-map-open@({\n // ${host}${!prototype ? "" : ` instanceof ${prototype.host}`}\n`, buildSource)
685
764
  for (const id of Property.ids) new Property(id)
686
765
  sourceFile.addLine("@descriptor-map-close@})", buildSource)
687
766
  const propertyDescriptorScript = sourceFile.packAndMap()
688
767
  try {
689
- const propertyDescriptor = eval(propertyDescriptorScript)
690
- part.define(propertyDescriptor)
768
+ part.define(eval(propertyDescriptorScript))
691
769
  } catch (evalError) {
692
770
  throw new Error(`Failed to construct property descriptor for ${host}.\n${evalError}\n${propertyDescriptorScript}`)
693
771
  }
@@ -711,10 +789,12 @@ function ƒ(_, compressedSubjectOrigins) {
711
789
  if (!childPart.isAbstract)
712
790
  part.subparts.push(childPart)
713
791
  }
714
- if (!part.isAbstract) instances.push(part)
715
- allParts.push(part)
716
- subjectIndices.set(host, allSubjects.length)
717
- allSubjects.push([host])
792
+ if (!buildTimeHydrationIsComplete) {
793
+ if (!part.isAbstract) instances.push(part)
794
+ allParts.push(part)
795
+ subjectIndices.set(host, allSubjects.length)
796
+ allSubjects.push([host])
797
+ }
718
798
  })
719
799
 
720
800
  return part
@@ -748,6 +828,7 @@ function ƒ(_, compressedSubjectOrigins) {
748
828
  hydrateSubjectOrigins()
749
829
  countAndSortInheritorsRecursive(_.parts.abstract.part)
750
830
  hydrateLog(`\nParts hydrated in ${Date.now() - hydrationStartTime}ms.`)
831
+ buildTimeHydrationIsComplete = true
751
832
 
752
833
  _.define({ "..": { value: null } })
753
834
 
@@ -0,0 +1,34 @@
1
+ let injection
2
+
3
+ const [headHTML, bodyHTML] = HTML_DOCUMENT.split(/\s*<\/head>\s*/)
4
+
5
+ if (environment.startsWith("node")) {
6
+
7
+ const bodyDeclarations = []
8
+ const earlies = {}
9
+
10
+ for (const [, host, filename] of bodyHTML.matchAll(/data:image\/svg\+xml;inert;(.+?)\/(.+?),/g))
11
+ (earlies[host] ??= new Set()).add(filename)
12
+
13
+ for (const [, host, filename] of headHTML.matchAll(/var\(--(.+?)--(.+?)\)/g))
14
+ (earlies[host.replaceAll("-", ".").replaceAll("_", "-")] ??= new Set()).add(filename.replace("-", ".").replaceAll("_", "-"))
15
+
16
+ injection = /* html */`<style id="img-css"></style>
17
+ <style id="early-img-css">${earlyImageSources.map(([owner, filename]) => {
18
+ if (earlies[owner.host]?.has(filename)) {
19
+ const varName = `--${owner.host.replaceAll("-", "_").replaceAll(".", "-")}--${filename.replaceAll("-", "_").replaceAll(".", "-")}`
20
+ /* Valid for .png, .gif and .jpeg files only */
21
+ bodyDeclarations.push(`${varName}: url(data:image/${filename.slice(-3)};base64,${owner["early-" + filename]});`)
22
+ return /* css */`img[src*=";${owner.host}/${filename}"] { background: var(${varName}); background-size: 100%; animation: none }`
23
+ }
24
+ return ""
25
+ }).join("") +
26
+ `body {\n ${bodyDeclarations.join("\n ")}\n}`}</style>`
27
+ } else {
28
+ injection = /* html */`<style id="img-css">${_["images.css"]}</style>`
29
+ }
30
+
31
+ return /* html */`${headHTML}
32
+ ${injection}
33
+ </head>
34
+ ${bodyHTML}`
package/src/part.html_.js CHANGED
@@ -1,60 +1,39 @@
1
- const placeholderIcon = application.placeholderImage("part.png")
2
-
3
- const meta =
4
- // `<meta name="robots" content="noindex" />` +
5
- `<meta name="format-detection" content="telephone=no, email=no, address=no, date=no">` +
6
- `<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"/>` +
7
- `<meta name="description" content="${sanitizeAttr(application.descriptionMeta ?? "This app is coming soon.")}">` /* +
8
- `<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">` +
9
- `<meta name="theme-color" content="#000000" media="(prefers-color-scheme: dark)">`*/
10
-
11
- const links =
12
- (production ? `` : `<link rel="manifest"${worker.manifestLink}/>`) +
13
- `<link class=favicon rel=icon href="${placeholderIcon}"/>` +
14
- `<link class=favicon rel="apple-touch-icon" href="${placeholderIcon}"/>` +
15
- `<link rel="canonical" href="https://${application.host}${application.canonicalPathname ?? "/"}" />`
16
-
17
- const title =
18
- `<title>${sanitizeAttr(application.title ?? "Untitled App")}</title>`
19
-
20
- const bodyClassList = ['unhydrated', era.arm.key, color.isLight ? "light" : "dark"]
21
-
22
- if (taskBar.menu.arm?.key === "open")
23
- bodyClassList.push("menu-fully-open")
24
-
25
- if (taskBar.menu.arm?.key !== "closed")
26
- bodyClassList.push("menu-pressed")
27
-
28
- if (application.classes)
29
- bodyClassList.push(...application.classes)
30
-
31
- const bodyHTML =
32
- `<body class="${bodyClassList.join(" ")}">` + (
33
- `<warning->` + (
34
- `🚧 App in Alpha. Features subject to change/break without notice.`
35
- ) +
36
- `</warning->` +
37
- `<title-bar><img class="part-icon" src="${_.application.placeholderImage("part.png")}"/>${application.title}<flex-spacer></flex-spacer><button class=hide ${windows.pointAttr("hidePoint")}></button><button class=restore ${windows.pointAttr("restorePoint")} disabled></button><button class=close ${windows.pointAttr("closePoint")}></button></title-bar>` +
38
- `<wallpaper- class=app-container id=${application.host.replaceAll(".", "_")} tabIndex=0${application.attributes ? ` ${application.attributes}` : ""}${application.style ? ` style="${application.style}"` : ""}>` + (
39
- application["part.html"]
40
- ) +
41
- `</wallpaper->` +
42
- `<!-- windows -->` +
43
- taskBar["part.html"] +
44
- worker["part.html"]
45
- ) +
46
- `</body>`
47
-
48
- const nonImageStyles = `<style id="user-css">${_["part.css"]}</style>` +
49
- `<style id="era-css">${era["part.css"]}</style>` +
50
- `<style id="color-css">${color["part.css"]}</style>` +
51
- `<style id="application-css">${application["part.css"]}</style>`
52
-
53
- const styles = nonImageStyles +
54
- `<style id="img-css">${environment.startsWith("node") ? "" : _["images.css"]}</style>` +
55
- (environment.startsWith("node") ? `<style id="early-img-css">${_.getImagesEarly(bodyHTML, nonImageStyles)}</style>` : "")
56
-
57
- const headHTML =
58
- `<head>${title}${meta}${links}${styles}</head>`
59
-
60
- return `<!DOCTYPE html><html lang=en>${headHTML}${bodyHTML}</html>`
1
+ const
2
+ title = sanitizeAttr(application.title ?? "Untitled App"),
3
+ icon = application.placeholderImage("part.png")
4
+
5
+ return _.injectImages(/* html */`<!DOCTYPE html>
6
+ <html lang=en>
7
+ <head>
8
+ <title>${title}</title>
9
+ <meta name="format-detection" content="telephone=no, email=no, address=no, date=no">
10
+ <meta name="description" content="${sanitizeAttr(application.descriptionMeta ?? "This app is coming soon.")}">
11
+ <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"/>
12
+ <!-- <meta name="theme-color" ... media="(prefers-color-scheme: light)"> -->
13
+ <link class=favicon rel=icon href="${icon}"/>
14
+ <link class=favicon rel="apple-touch-icon" href="${icon}"/>
15
+ <link rel="canonical" href="https://${application.host}${application.canonicalPathname ?? "/"}" />
16
+ <!-- <link rel="manifest"${worker.manifestLink}/> -->
17
+ <style id="user-css">${_["part.css"]}</style>
18
+ <style id="era-css">${era["part.css"]}</style>
19
+ <style id="color-css">${color["part.css"]}</style>
20
+ <style id="application-css">${application["part.css"]}</style>
21
+ </head>
22
+ <body class="unhydrated ${[era.arm.key, color.arm.key, ...taskBar.menu.classes, ...application.classes].join(" ")}">
23
+ <warning->🚧 App in Alpha. Features subject to change/break without notice.</warning->
24
+ <title-bar autofocus tabIndex=0>
25
+ <img class="part-icon" src="${icon}"/>
26
+ <span id=application-title>${title}</span>
27
+ <flex-spacer></flex-spacer>
28
+ <button class=hide ${windows.pointAttr("hidePoint")}></button>
29
+ <button class=restore ${windows.pointAttr("restorePoint")} disabled></button>
30
+ <button class=close ${windows.pointAttr("closePoint")}></button>
31
+ </title-bar>
32
+ <wallpaper- class=app-container id=${application.host.replaceAll(".", "_")} tabIndex=0 ${application.attributes.join(" ")}>
33
+ ${application["part.html"]}
34
+ </wallpaper->
35
+ <!-- windows -->
36
+ ${taskBar["part.html"]}
37
+ ${worker["part.html"]}
38
+ </body>
39
+ </html>`)
package/src/part.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "extends": "mix",
3
- "route-set": [
4
- "REQUEST_URL"
5
- ],
6
- "validate": [],
7
- "point": [
8
- "POINTER_EVENT",
9
- "TARGET_ELEMENT"
10
- ],
11
- "pathname-translate-canonical": [
12
- "HOST",
13
- "PATHNAME",
14
- "HASH"
15
- ],
16
- "early-get-images": [
17
- "BODY_HTML",
18
- "HEAD_HTML"
19
- ],
20
- "application-goto": [
21
- "HOST"
22
- ]
3
+ "methods": {
4
+ "route-set": [
5
+ "REQUEST_URL"
6
+ ],
7
+ "validate": [],
8
+ "point": [
9
+ "POINTER_EVENT",
10
+ "TARGET_ELEMENT"
11
+ ],
12
+ "pathname-translate-canonical": [
13
+ "HOST",
14
+ "PATHNAME",
15
+ "HASH"
16
+ ],
17
+ "images-inject": [
18
+ "HTML_DOCUMENT"
19
+ ],
20
+ "application-goto": [
21
+ "HOST"
22
+ ]
23
+ }
23
24
  }
@@ -0,0 +1,3 @@
1
+ return [
2
+
3
+ ]
@@ -0,0 +1 @@
1
+ return []
@@ -8,7 +8,7 @@ declare interface IApplication<TOwner, TFactor>
8
8
  IApplicationDetails {
9
9
 
10
10
  // Serialized Properties.
11
- /** An optional array of classes which the application wants to have applied to the body. */
11
+ /** An array of classes which the application wants to have applied to the body. */
12
12
  readonly "classes": string[]
13
13
  /** An object corresponding to any custom headers that the application would like to include in the final response for its index pages. */
14
14
  readonly "customHeaders": Record<string, string>
@@ -51,7 +51,7 @@ declare interface IApplicationDetails
51
51
  /** The partial pathname or segment corresponding to the current page of the application. */
52
52
  readonly "pathname": string
53
53
  /** An optional string of attributes which will be added to the application host element. */
54
- readonly "attributes"?: string
54
+ readonly "attributes"?: string[]
55
55
  /** An optional string representing the style attribute of the application host element, which can be used for making quick (quicker than replacing part.css) changes to css variables. */
56
56
  readonly "style"?: string
57
57
  /** For SEO, the portion of the "sitemap.xml" file listing the application or application section's available canonical links. */
@@ -1,3 +1,2 @@
1
1
  document.body.classList.add(bodyMode.key)
2
-
3
2
  Q("#" + bodyMode.id)?.setAttribute("data-state", bodyMode.stateData)
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "abstract": true,
3
- "toggle": [],
4
- "clear": [],
5
- "set": []
3
+ "methods": {
4
+ "toggle": [],
5
+ "clear": [],
6
+ "set": []
7
+ }
6
8
  }
@@ -7,6 +7,5 @@ clip.define({
7
7
  elapsedTime: { value: undefined, writable: true },
8
8
  elapsedFrames: { value: undefined, writable: true },
9
9
  playing: { value: undefined, writable: true },
10
- pendingFrame: { value: undefined, writable: true },
11
10
  nextClip: { value: null, writable: true }
12
11
  })
@@ -0,0 +1,12 @@
1
+ if (clip.playing) {
2
+ clip.elapsedTime = _.now - clip.playbackStartTime
3
+ const newElapsedFrames = Math.round(clip.elapsedTime / clip.frameTime)
4
+
5
+ if (clip.elapsedFrames !== newElapsedFrames) {
6
+ clip.elapsedFrames = newElapsedFrames
7
+ const nextFrame = clip.playbackStartFrame + BigInt(clip.elapsedFrames)
8
+ if (nextFrame < clip.cardinality)
9
+ clip.setRouteID(nextFrame)
10
+ else clip.handleEndPlayback()
11
+ }
12
+ }
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "abstract": true,
3
- "playback-initiate": [],
4
- "playback-stop": [],
5
- "playback-handle-end": [],
6
- "next": []
3
+ "methods": {
4
+ "playback-initiate": [],
5
+ "playback-stop": [],
6
+ "playback-handle-end": [],
7
+ "next": []
8
+ }
7
9
  }
@@ -1,8 +1,3 @@
1
- if (clip.pendingFrame) {
2
- cancelAnimationFrame(clip.pendingFrame)
3
- clip.pendingFrame = undefined
4
- }
5
-
6
1
  clip.playbackStartTime = undefined
7
2
  clip.playbackStartFrame = undefined
8
3
  clip.elapsedTime = undefined
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "abstract": true,
3
3
  "extends": "application",
4
- "CSS-get-error": [
5
- "MESSAGE"
6
- ],
7
- "HTML-get-error": [
8
- "STATUS",
9
- "MESSAGE"
10
- ],
11
- "response-get-error": [
12
- "ERROR_STRING",
13
- "REQUEST_HOST"
14
- ]
4
+ "methods": {
5
+ "CSS-get-error": [
6
+ "MESSAGE"
7
+ ],
8
+ "HTML-get-error": [
9
+ "STATUS",
10
+ "MESSAGE"
11
+ ],
12
+ "response-get-error": [
13
+ "ERROR_STRING",
14
+ "REQUEST_HOST"
15
+ ]
16
+ }
15
17
  }
@@ -10,7 +10,7 @@ declare interface IErrorApplication<TOwner>
10
10
  readonly getErrorCSS(MESSAGE: string): string
11
11
  /** Returns a stylized error page for the given message and status. */
12
12
  readonly getErrorHTML(STATUS: string | number, MESSAGE: string): string
13
- /** Returns an object based on the given error string which can be used to populate an error response. */
13
+ /** Returns an object based on the given error string which can be used to update an error response. */
14
14
  readonly getErrorResponse(ERROR_STRING: string, REQUEST_HOST: string): string
15
15
  }
16
16
 
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "abstract": true,
3
- "sync-install": [],
4
- "support-check": [],
5
- "install": [
6
- "GATE"
7
- ],
8
- "async-install": [
9
- "PROMISE_ARRAY"
10
- ]
3
+ "methods": {
4
+ "sync-install": [],
5
+ "support-check": [],
6
+ "install": [
7
+ "GATE"
8
+ ],
9
+ "async-install": [
10
+ "PROMISE_ARRAY"
11
+ ]
12
+ }
11
13
  }
@@ -1,16 +1,18 @@
1
- const offsets = new Map()
2
-
3
- let sum = 0n
4
-
5
- if (match.length === 0)
6
- sum = 1n
7
- else for (const subpart of match) {
8
- offsets.set(subpart, sum)
9
- sum += subpart.cardinality
10
- }
11
-
12
1
  match.define({
13
- offsets: { value: offsets },
14
- cardinality: { value: sum },
15
2
  arm: { value: null, writable: true },
3
+ offsets: { value: new Map() },
4
+ cardinality: {
5
+ resolve() {
6
+ let sum = 0n
7
+
8
+ if (this.length === 0)
9
+ sum = 1n
10
+ else for (const subpart of this) {
11
+ this.offsets.set(subpart, sum)
12
+ sum += subpart.cardinality
13
+ }
14
+
15
+ return sum
16
+ }
17
+ }
16
18
  })
@@ -3,7 +3,7 @@ return "<math>" + (
3
3
  match.length > 4 ? (
4
4
  `<mo>∑</mo><msub><mi>𝑘</mi><mi>𝑝</mi></msub><mtext>,</mtext><mspace width="0.5em"/><mi>𝑝</mi><mo>∈</mo><mi>subparts</mi><mo>(</mo><msub><mi>P</mi><mi>${part.key ?? "ecosystem"}</mi></msub><mo>)</mo>`
5
5
  ) : (
6
- match.map(factor => factor["equation-variable.html"]).join("<mo>+</mo>")
6
+ match.map(arm => arm["equation-variable.html"]).join("<mo>+</mo>")
7
7
  )
8
8
  ) : (
9
9
  "<mn>1</mn>"
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "abstract": true,
3
- "routeID-collect": [
4
- "CHANGED_ARMS",
5
- "DEPTH"
6
- ]
3
+ "methods": {
4
+ "routeID-collect": [
5
+ "CHANGED_ARMS",
6
+ "DEPTH"
7
+ ]
8
+ }
7
9
  }
@@ -26,17 +26,8 @@ for (const changedArm of CHANGED_ARMS) {
26
26
  }
27
27
  }
28
28
 
29
- if (!newArm) {
30
- try {
31
- newArm = match.defaultArm
32
- if (newArm !== null)
33
- newArm.distributeRouteID(0n)
34
- else
35
- match.updateRouteID(-1n)
36
- } catch (cause) {
37
- throw new Error("An arm to enable could not be found.", cause)
38
- }
39
- }
29
+ if (!newArm)
30
+ throw new Error("An arm to enable could not be found.")
40
31
 
41
32
  if (oldArm && newArm !== oldArm && !disabledArm)
42
33
  oldArm.distributeRouteID(-1n)