@lampdotdev/lamp 0.0.0-stage → 0.35.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 (464) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -2
  3. package/Resources/Devices/roku.json +410 -0
  4. package/Resources/Devices/xbox-one.json +367 -0
  5. package/Resources/GameKit/NOTICE.md +63 -0
  6. package/Resources/GameKit/apple/LampPage.swift +1646 -0
  7. package/Resources/GameKit/apple/LampPlayer.swift +46 -0
  8. package/Resources/GameKit/apple/LampWebApp.swift +63 -0
  9. package/Resources/GameKit/apple/LampWebGame.swift +87 -0
  10. package/Resources/GameKit/apple/Native.swift +12 -0
  11. package/Resources/GameKit/build.sh +55 -0
  12. package/Resources/GameKit/lamp_game.h +116 -0
  13. package/Resources/GameKit/lamp_host.h +19 -0
  14. package/Resources/GameKit/lamp_kit.cpp +61 -0
  15. package/Resources/GameKit/lamp_sound.cpp +455 -0
  16. package/Resources/GameKit/lamp_xbox.cpp +374 -0
  17. package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
  18. package/Resources/GameKit/libraries/cgltf.h +7240 -0
  19. package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
  20. package/Resources/GameKit/libraries/dr_wav.h +9209 -0
  21. package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
  22. package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
  23. package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
  24. package/Resources/GameKit/libraries/sokol_log.h +335 -0
  25. package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
  26. package/Resources/GameKit/libraries/stb_image.h +7988 -0
  27. package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
  28. package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
  29. package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
  30. package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
  31. package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
  32. package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
  33. package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
  34. package/Resources/GameKit/web/lamp-game.js +3036 -0
  35. package/Resources/GameKit/web/lamp-phaser.js +128 -0
  36. package/Resources/WebHost/App.exe +0 -0
  37. package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
  38. package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
  39. package/Resources/WebHost/lamp_controllers.h +1506 -0
  40. package/Resources/WebHost/lamp_web_host.cpp +1173 -0
  41. package/Resources/WebLibraries/earlier.txt +318 -0
  42. package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
  43. package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
  44. package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
  45. package/Resources/WebLibraries/qrcode/LICENSE +21 -0
  46. package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
  47. package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
  48. package/Resources/WebLibraries/rapier/LICENSE +201 -0
  49. package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
  50. package/Resources/WebLibraries/rapier/rapier.js +2 -0
  51. package/Resources/WebLibraries/three/LICENSE +21 -0
  52. package/Resources/WebLibraries/three/NOTICE.md +4 -0
  53. package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
  54. package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
  55. package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
  56. package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
  57. package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
  58. package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
  59. package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
  60. package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
  61. package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
  62. package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
  63. package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
  64. package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
  65. package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
  66. package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
  67. package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
  68. package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
  69. package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
  70. package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
  71. package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
  72. package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
  73. package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
  74. package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
  75. package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
  76. package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
  77. package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
  78. package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
  79. package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
  80. package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
  81. package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
  82. package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
  83. package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
  84. package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
  85. package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
  86. package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
  87. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
  88. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
  89. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
  90. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
  91. package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
  92. package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
  93. package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
  94. package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
  95. package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
  96. package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
  97. package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
  98. package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
  99. package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
  100. package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
  101. package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
  102. package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
  103. package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
  104. package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
  105. package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
  106. package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
  107. package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
  108. package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
  109. package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
  110. package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
  111. package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
  112. package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
  113. package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
  114. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
  115. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
  116. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
  117. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
  118. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
  119. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
  120. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
  121. package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
  122. package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
  123. package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
  124. package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
  125. package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
  126. package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
  127. package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
  128. package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
  129. package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
  130. package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
  131. package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
  132. package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
  133. package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
  134. package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
  135. package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
  136. package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
  137. package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
  138. package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
  139. package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
  140. package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
  141. package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
  142. package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
  143. package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
  144. package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
  145. package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
  146. package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
  147. package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
  148. package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
  149. package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
  150. package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
  151. package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
  152. package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
  153. package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
  154. package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
  155. package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
  156. package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
  157. package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
  158. package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
  159. package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
  160. package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
  161. package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
  162. package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
  163. package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
  164. package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
  165. package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
  166. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
  167. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
  168. package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
  169. package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
  170. package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
  171. package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
  172. package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
  173. package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
  174. package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
  175. package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
  176. package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
  177. package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
  178. package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
  179. package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
  180. package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
  181. package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
  182. package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
  183. package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
  184. package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
  185. package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
  186. package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
  187. package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
  188. package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
  189. package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
  190. package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
  191. package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
  192. package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
  193. package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
  194. package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
  195. package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
  196. package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
  197. package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
  198. package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
  199. package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
  200. package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
  201. package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
  202. package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
  203. package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
  204. package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
  205. package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
  206. package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
  207. package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
  208. package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
  209. package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
  210. package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
  211. package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
  212. package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
  213. package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
  214. package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
  215. package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
  216. package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
  217. package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
  218. package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
  219. package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
  220. package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
  221. package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
  222. package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
  223. package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
  224. package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
  225. package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
  226. package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
  227. package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
  228. package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
  229. package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
  230. package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
  231. package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
  232. package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
  233. package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
  234. package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
  235. package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
  236. package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
  237. package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
  238. package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
  239. package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
  240. package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
  241. package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
  242. package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
  243. package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
  244. package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
  245. package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
  246. package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
  247. package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
  248. package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
  249. package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
  250. package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
  251. package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
  252. package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
  253. package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
  254. package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
  255. package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
  256. package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
  257. package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
  258. package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
  259. package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
  260. package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
  261. package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
  262. package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
  263. package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
  264. package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
  265. package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
  266. package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
  267. package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
  268. package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
  269. package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
  270. package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
  271. package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
  272. package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
  273. package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
  274. package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
  275. package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
  276. package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
  277. package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
  278. package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
  279. package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
  280. package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
  281. package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
  282. package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
  283. package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
  284. package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
  285. package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
  286. package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
  287. package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
  288. package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
  289. package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
  290. package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
  291. package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
  292. package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
  293. package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
  294. package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
  295. package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
  296. package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
  297. package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
  298. package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
  299. package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
  300. package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
  301. package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
  302. package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
  303. package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
  304. package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
  305. package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
  306. package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
  307. package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
  308. package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
  309. package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
  310. package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
  311. package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
  312. package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
  313. package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
  314. package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
  315. package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
  316. package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
  317. package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
  318. package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
  319. package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
  320. package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
  321. package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
  322. package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
  323. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
  324. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
  325. package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
  326. package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
  327. package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
  328. package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
  329. package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
  330. package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
  331. package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
  332. package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
  333. package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
  334. package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
  335. package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
  336. package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
  337. package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
  338. package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
  339. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
  340. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
  341. package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
  342. package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
  343. package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
  344. package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
  345. package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
  346. package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
  347. package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
  348. package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
  349. package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
  350. package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
  351. package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
  352. package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
  353. package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
  354. package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
  355. package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
  356. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
  357. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
  358. package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
  359. package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
  360. package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
  361. package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
  362. package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
  363. package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
  364. package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
  365. package/Resources/WebLibraries/three/three.core.js +61162 -0
  366. package/Resources/WebLibraries/three/three.module.js +19537 -0
  367. package/Resources/WebLibraries/three/three.tsl.js +41903 -0
  368. package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
  369. package/Resources/skills/2d-game/SKILL.md +305 -0
  370. package/Resources/skills/3d-game/SKILL.md +274 -0
  371. package/Resources/skills/accounts/SKILL.md +41 -0
  372. package/Resources/skills/android-design/SKILL.md +159 -0
  373. package/Resources/skills/app-ai/SKILL.md +154 -0
  374. package/Resources/skills/app-intents/SKILL.md +31 -0
  375. package/Resources/skills/app-kinds/SKILL.md +122 -0
  376. package/Resources/skills/apple-watch/SKILL.md +43 -0
  377. package/Resources/skills/assets/SKILL.md +183 -0
  378. package/Resources/skills/building-blocks/SKILL.md +97 -0
  379. package/Resources/skills/device-control/SKILL.md +56 -0
  380. package/Resources/skills/device-integrations/SKILL.md +278 -0
  381. package/Resources/skills/finder-files/SKILL.md +19 -0
  382. package/Resources/skills/game/SKILL.md +414 -0
  383. package/Resources/skills/game-3d/SKILL.md +12 -0
  384. package/Resources/skills/game-art/SKILL.md +11 -0
  385. package/Resources/skills/game-feel/SKILL.md +13 -0
  386. package/Resources/skills/game-levels/SKILL.md +12 -0
  387. package/Resources/skills/game-live/SKILL.md +12 -0
  388. package/Resources/skills/game-physics/SKILL.md +13 -0
  389. package/Resources/skills/game-playtest/SKILL.md +26 -0
  390. package/Resources/skills/game-ui/SKILL.md +278 -0
  391. package/Resources/skills/github-projects/SKILL.md +59 -0
  392. package/Resources/skills/icloud-sync/SKILL.md +30 -0
  393. package/Resources/skills/iphone-hardware/SKILL.md +57 -0
  394. package/Resources/skills/iphone-widgets/SKILL.md +53 -0
  395. package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
  396. package/Resources/skills/mac-widgets/SKILL.md +60 -0
  397. package/Resources/skills/maps/SKILL.md +8 -0
  398. package/Resources/skills/menu-bar/SKILL.md +36 -0
  399. package/Resources/skills/more-apps/SKILL.md +53 -0
  400. package/Resources/skills/phone-controllers/SKILL.md +79 -0
  401. package/Resources/skills/phone-pages/SKILL.md +173 -0
  402. package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
  403. package/Resources/skills/scene-3d/SKILL.md +27 -0
  404. package/Resources/skills/scripting/SKILL.md +17 -0
  405. package/Resources/skills/share-extension/SKILL.md +22 -0
  406. package/Resources/skills/tv-design/SKILL.md +72 -0
  407. package/Resources/skills/web-app/SKILL.md +136 -0
  408. package/Resources/skills/web-game/SKILL.md +95 -0
  409. package/Resources/skills/web-or-native/SKILL.md +103 -0
  410. package/Resources/skills/wish-links/SKILL.md +156 -0
  411. package/THIRD_PARTY_NOTICES.md +170 -0
  412. package/cli/android.mjs +941 -0
  413. package/cli/browser.mjs +268 -0
  414. package/cli/calls.mjs +390 -0
  415. package/cli/dev.mjs +773 -0
  416. package/cli/devices.mjs +984 -0
  417. package/cli/lamp.mjs +1016 -0
  418. package/cli/lampapp.mjs +332 -0
  419. package/cli/lamps/android-host/LampPageGateway.kt +345 -0
  420. package/cli/lamps/android-host/app/build.gradle.kts +40 -0
  421. package/cli/lamps/android-host/build.gradle.kts +4 -0
  422. package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
  423. package/cli/lamps/android-host/game/MainActivity.kt +173 -0
  424. package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
  425. package/cli/lamps/android-host/gradle.properties +8 -0
  426. package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
  427. package/cli/lamps/android-host/page/MainActivity.kt +193 -0
  428. package/cli/lamps/android-host/settings.gradle.kts +30 -0
  429. package/cli/lamps/android-host/tools.json +43 -0
  430. package/cli/lamps/lamp-controllers.js +2 -0
  431. package/cli/lamps/lamp-for-games.js +6863 -0
  432. package/cli/lamps/lamp.js +7023 -0
  433. package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
  434. package/cli/lamps/mac-starter/APP.md +12 -0
  435. package/cli/lamps/mac-starter/Package.swift +8 -0
  436. package/cli/lamps/mac-starter/Sources/App.swift +11 -0
  437. package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
  438. package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
  439. package/cli/lamps/mac-starter/build.sh +336 -0
  440. package/cli/lamps/mac-starter/gitignore +3 -0
  441. package/cli/lamps/mac-starter/lamp-starter.json +6 -0
  442. package/cli/lamps/web-starter/APP.md +8 -0
  443. package/cli/lamps/web-starter/app.js +1 -0
  444. package/cli/lamps/web-starter/index.html +17 -0
  445. package/cli/lamps/web-starter/lamp-starter.json +5 -0
  446. package/cli/lamps/web-starter/lamp.js +7023 -0
  447. package/cli/lamps/web-starter/style.css +25 -0
  448. package/cli/link.mjs +138 -0
  449. package/cli/mac.mjs +621 -0
  450. package/cli/mdns.mjs +205 -0
  451. package/cli/msix.mjs +413 -0
  452. package/cli/network.mjs +209 -0
  453. package/cli/outside.mjs +140 -0
  454. package/cli/page.js +165 -0
  455. package/cli/place.mjs +298 -0
  456. package/cli/png.mjs +184 -0
  457. package/cli/share.mjs +202 -0
  458. package/cli/skill/SKILL.md +255 -0
  459. package/cli/skills.mjs +71 -0
  460. package/cli/state.mjs +173 -0
  461. package/cli/update.mjs +57 -0
  462. package/package.json +20 -4
  463. package/site/lib/quota.js +59 -0
  464. package/site/lib/shared-wishes.js +996 -0
package/cli/share.mjs ADDED
@@ -0,0 +1,202 @@
1
+ // A link to the page on lamp.dev: anyone who opens it plays the page there, and can send its maker an idea. The page
2
+ // zipped as the site takes it, then the link's words and picture and the page sent in parts, through the site's API
3
+ // as link.mjs speaks it (the same for Lamp's app's Share Link card).
4
+ //
5
+ // The link's secret, which is what lets it be changed or taken down, is kept with lamp's own state for the folder,
6
+ // never in the folder: a folder is committed and published, and the secret is whoever shared it's alone.
7
+
8
+ import { createHash } from "node:crypto";
9
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
10
+ import { basename, join } from "node:path";
11
+ import { deflateRawSync } from "node:zlib";
12
+ import { Problem, stateOf } from "./state.mjs";
13
+ import { ANY_BROWSER, CONTROLLERS, CONTROLLERS_FILE, DEVICE_FILE, lampJS, LIBRARIES } from "./dev.mjs";
14
+ import { LIMITS, FILE_LIMITS, PAGE_LIMITS } from "../site/lib/shared-wishes.js";
15
+ import { ideasOf, publishLink, removeFile, removeIdea, removeLink, sendFile, siteOrigin } from "./link.mjs";
16
+ import { exportApp } from "./lampapp.mjs";
17
+
18
+ export { siteOrigin };
19
+
20
+ const linkFileOf = (folder) => join(stateOf(folder), "link.json");
21
+
22
+ /** The folder's link, as it was last shared: its address, its secret and the words it went out with. */
23
+ export function readLink(folder) {
24
+ try { return JSON.parse(readFileSync(linkFileOf(folder), "utf8")); } catch { return null; }
25
+ }
26
+ function writeLink(folder, link) {
27
+ mkdirSync(stateOf(folder), { recursive: true });
28
+ writeFileSync(linkFileOf(folder), JSON.stringify(link, null, 2), { mode: 0o600 });
29
+ }
30
+
31
+ // MARK: The page, as a zip
32
+
33
+ const CRC = Array.from({ length: 256 }, (_, n) => { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; return c >>> 0; });
34
+ function crc32(bytes) {
35
+ let c = 0xffffffff;
36
+ for (let i = 0; i < bytes.length; i++) c = CRC[(c ^ bytes[i]) & 0xff] ^ (c >>> 8);
37
+ return (c ^ 0xffffffff) >>> 0;
38
+ }
39
+
40
+ /** A zip of these files (`[path, bytes]`), each packed where that makes it smaller. */
41
+ export function zipOf(files) {
42
+ const parts = [], listing = [];
43
+ let offset = 0;
44
+ for (const [path, bytes] of files) {
45
+ const name = Buffer.from(path, "utf8"), packed = deflateRawSync(bytes), stored = packed.length >= bytes.length;
46
+ const data = stored ? bytes : packed, sum = crc32(bytes);
47
+ const head = Buffer.alloc(30);
48
+ head.writeUInt32LE(0x04034b50, 0);
49
+ head.writeUInt16LE(20, 4);
50
+ head.writeUInt16LE(0x0800, 6); // the name is UTF-8
51
+ head.writeUInt16LE(stored ? 0 : 8, 8);
52
+ head.writeUInt32LE(sum, 14);
53
+ head.writeUInt32LE(data.length, 18);
54
+ head.writeUInt32LE(bytes.length, 22);
55
+ head.writeUInt16LE(name.length, 26);
56
+ const entry = Buffer.alloc(46);
57
+ entry.writeUInt32LE(0x02014b50, 0);
58
+ entry.writeUInt16LE(20, 4);
59
+ entry.writeUInt16LE(20, 6);
60
+ head.copy(entry, 8, 6, 30); // the same flags, method, sum, sizes and name length
61
+ entry.writeUInt32LE(offset, 42);
62
+ parts.push(head, name, data);
63
+ listing.push(entry, name);
64
+ offset += 30 + name.length + data.length;
65
+ }
66
+ const directory = Buffer.concat(listing), end = Buffer.alloc(22);
67
+ end.writeUInt32LE(0x06054b50, 0);
68
+ end.writeUInt16LE(files.length, 8);
69
+ end.writeUInt16LE(files.length, 10);
70
+ end.writeUInt32LE(directory.length, 12);
71
+ end.writeUInt32LE(offset, 16);
72
+ return Buffer.concat([...parts, directory, end]);
73
+ }
74
+
75
+ /**
76
+ * Every file of the page as it's played from the link: what's in its folder (nothing hidden, no link followed, the
77
+ * app's notes left out), and for a game Lamp's own files beside it, as Lamp's app puts them in a copy it publishes
78
+ * (`GamePage.stage`): the device a browser on any device is, the build's name, and what the folder has none of.
79
+ * A copy for one device (place.mjs) is given that device in its place.
80
+ */
81
+ export function pageFiles(layout, { device = ANY_BROWSER } = {}) {
82
+ const files = new Map();
83
+ const walk = (dir, prefix) => {
84
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
85
+ const path = prefix + entry.name;
86
+ if (entry.name.startsWith(".") || entry.name === "node_modules" || path === "APP.md") continue;
87
+ if (entry.isDirectory()) walk(join(dir, entry.name), path + "/");
88
+ else if (entry.isFile()) files.set(path, readFileSync(join(dir, entry.name)));
89
+ }
90
+ };
91
+ walk(layout.root, "");
92
+ if (layout.game) {
93
+ files.set(DEVICE_FILE, Buffer.from(device));
94
+ if (!files.has(CONTROLLERS_FILE)) files.set(CONTROLLERS_FILE, readFileSync(CONTROLLERS));
95
+ if (!files.has("lamp.js")) files.set("lamp.js", Buffer.from(lampJS(true)));
96
+ // A library the page's import map names from beside it and the folder has none of: Lamp's copy.
97
+ const map = /<script[^>]*type=["']importmap["'][^>]*>([\s\S]*?)<\/script>/i.exec(String(files.get("index.html") ?? ""))?.[1] ?? "";
98
+ for (const name of ["three", "phaser", "rapier"]) {
99
+ if (!new RegExp(`:\\s*["'](?:\\./)?${name}/`).test(map) || [...files.keys()].some((path) => path.startsWith(`${name}/`))) continue;
100
+ const from = join(LIBRARIES, name);
101
+ if (!existsSync(from)) continue;
102
+ const copy = (dir, prefix) => {
103
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
104
+ if (entry.isDirectory()) copy(join(dir, entry.name), `${prefix}${entry.name}/`);
105
+ else if (entry.isFile() && !lstatSync(join(dir, entry.name)).isSymbolicLink()) files.set(prefix + entry.name, readFileSync(join(dir, entry.name)));
106
+ }
107
+ };
108
+ copy(from, `${name}/`);
109
+ }
110
+ // The build's name, for the runtime to tell a newer copy of the game by: named for the files as they are.
111
+ files.delete("lamp-build.js");
112
+ const hash = createHash("sha256");
113
+ for (const path of [...files.keys()].sort()) hash.update(path).update(files.get(path));
114
+ files.set("lamp-build.js", Buffer.from(`export default "${hash.digest("hex").slice(0, 16)}";\n`));
115
+ }
116
+ return [...files].sort(([a], [b]) => a.localeCompare(b));
117
+ }
118
+
119
+ // MARK: The site
120
+
121
+ const megabytes = (bytes) => `${(bytes / 1_000_000).toFixed(bytes < 10_000_000 ? 1 : 0)} MB`;
122
+
123
+ /**
124
+ * Shares the page, or sends it again to the link the folder has: the link's words and picture, then the page. `words`
125
+ * are what the link says (`name`, `words`, and `line`, `by` and `asks` when given), `picture` a PNG or JPEG of the
126
+ * page or null, `shape` "fill" or the page's width over its height. Answers the link and what went up.
127
+ */
128
+ export async function share({ layout, words, picture = null, shape = "fill", site = siteOrigin(), said = () => {}, file = true, anyway = false }) {
129
+ // The app's own file goes with the link, as Lamp's Share Link sends it, so whoever follows the link can open it in
130
+ // Lamp too: made first, with Share…'s checks, so a page that can't be shared (a key in it) puts nothing up.
131
+ const app = file ? exportApp(layout.folder, { anyway }) : null;
132
+ const files = pageFiles(layout);
133
+ const unpacked = files.reduce((total, [, bytes]) => total + bytes.length, 0);
134
+ if (!files.some(([path]) => path === "index.html")) throw new Problem("the page has no index.html at its top");
135
+ if (files.length > PAGE_LIMITS.files) throw new Problem(`the page is ${files.length} files, and a link carries ${PAGE_LIMITS.files} at most`);
136
+ if (unpacked > PAGE_LIMITS.total) throw new Problem(`the page is ${megabytes(unpacked)}, and a link carries ${megabytes(PAGE_LIMITS.total)} at most`);
137
+ const zip = zipOf(files);
138
+ if (zip.length > FILE_LIMITS.total) throw new Problem(`the page is ${megabytes(zip.length)} packed, and a link carries ${megabytes(FILE_LIMITS.total)} at most`);
139
+ if (picture && picture.length > LIMITS.picture) picture = null;
140
+
141
+ const body = {
142
+ name: words.name, words: words.words, shape,
143
+ ...(words.line ? { line: words.line } : {}), ...(words.by ? { by: words.by } : {}),
144
+ ...(words.asks?.length ? { asks: words.asks } : {}), ...(picture ? { picture: picture.toString("base64") } : {}),
145
+ };
146
+ // The folder's own link when it has one on this site, changed in place; a link that's gone is made again.
147
+ let earlier = readLink(layout.folder);
148
+ if (earlier && earlier.site !== site) earlier = null;
149
+ // A file an earlier share sent stays on the record until it's taken away, so a retry after a failed removal tries again.
150
+ let link = { site, ...(await publishLink({ site, body, earlier })), ...words, shape, ...(earlier?.file ? { file: true } : {}) };
151
+ // Kept before the page goes up: a link whose page didn't make it is still this folder's to send again or take down.
152
+ writeLink(layout.folder, link);
153
+
154
+ // The file, or none: a link that carried one and shouldn't now has it taken away (and its page with it, sent next).
155
+ if (app) {
156
+ link.file = true;
157
+ writeLink(layout.folder, link);
158
+ await sendFile({ site, link, bytes: app.bytes, said });
159
+ } else if (link.file) {
160
+ await removeFile({ site, link });
161
+ link.file = false;
162
+ writeLink(layout.folder, link);
163
+ }
164
+ const version = await sendFile({ site, link, bytes: zip, page: true, said });
165
+ link = { ...link, version, shared: new Date().toISOString() };
166
+ writeLink(layout.folder, link);
167
+ return { url: link.url, version, files: files.length, bytes: zip.length, picture: !!picture, file: !!app };
168
+ }
169
+
170
+ /** Takes the folder's link down, with its page and the ideas sent to it. */
171
+ export async function unshare(folder) {
172
+ const link = readLink(folder);
173
+ if (!link) throw new Problem("this folder has no link");
174
+ await removeLink({ site: link.site, link });
175
+ rmSync(linkFileOf(folder), { force: true });
176
+ return link.url;
177
+ }
178
+
179
+ /** The ideas people playing the link have sent its maker and that are still open: each with its number. */
180
+ export async function ideas(folder) {
181
+ const link = readLink(folder);
182
+ if (!link) throw new Problem("this folder has no link: lamp share makes one");
183
+ return { url: link.url, ideas: await ideasOf({ site: link.site, link }) };
184
+ }
185
+
186
+ /** Says what became of an idea: it's in (the site writes to whoever asked to hear), or it's let go. */
187
+ export async function finishIdea(folder, n, built) {
188
+ const link = readLink(folder);
189
+ if (!link) throw new Problem("this folder has no link");
190
+ return removeIdea({ site: link.site, link, n, built });
191
+ }
192
+
193
+ /** The page's name where nothing gave one: its title, or its folder's name. */
194
+ export function nameOf(layout) {
195
+ try {
196
+ const title = /<title[^>]*>([^<]*)<\/title>/i.exec(readFileSync(join(layout.root, "index.html"), "utf8"))?.[1]?.trim();
197
+ if (title) return title.replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').slice(0, LIMITS.name);
198
+ } catch {}
199
+ return basename(layout.folder).slice(0, LIMITS.name);
200
+ }
201
+
202
+ export { LIMITS };
@@ -0,0 +1,255 @@
1
+ ---
2
+ name: lamp
3
+ description: Make, run, see and try an app with lamp's command line - a web app, a web game, or a Mac app Lamp made in Swift. Use when the person asks for a new web game, or when working in a folder made with Lamp (a page beside lamp-game.js or in Web/, or Package.swift with build.sh and Sources/LampSupport.swift) or in a plain site's folder and they ask to change the app, to see it, or to check that a change works. Every saved change goes into the open app, and a game keeps the player's place.
4
+ ---
5
+
6
+ # Working on an app with lamp
7
+
8
+ `{{lamp}}` runs the page in the app's folder and puts each change into it while it's open. Save a file and the change
9
+ goes in. Never build, restart or reload anything for a change.
10
+
11
+ Run the commands from the app's folder, or give the folder after the command (`{{lamp}} look path/to/app`).
12
+
13
+ Most of this is about an app that is a web page: a web game, a web app, a plain site. An app Lamp made that way has
14
+ the page in `Web/`, beside the Swift of the app around it, which stays as it is. An app whose own screens are Swift
15
+ is a Mac app: "A Mac app" below says what's different for one.
16
+
17
+ ## A new game
18
+
19
+ `{{lamp}} new path/to/folder --name "Its Name"` makes a new web game's folder from Lamp's starting files: the game
20
+ runtime (`lamp-game.js`), three.js and Phaser, `APP.md`, and a page that shows a card until the game replaces it. The
21
+ page is at the top of the folder: what Lamp's skills call `Web/` is the folder itself.
22
+
23
+ Before writing, read Lamp's `web-game` and `game-feel` skills, which are for every game, and `game-playtest` when
24
+ you're asked to play it; "Lamp's skills" below says what in them is Lamp's app's doing. The card's `game.js`,
25
+ `world.js` and `making.js` are yours to replace, as `web-game` says.
26
+
27
+ The card is a small game of its own, and the runtime keeps what it registered (a state called `play`, a camera)
28
+ through a change, as it would the player's place. So write the whole game before the first look, and make that look
29
+ with `--reopen` (`{{lamp}} look --reopen`): the game then opens from its beginning, not from the card's. If you
30
+ looked earlier, `--reopen` puts it right.
31
+
32
+ ## A new web app
33
+
34
+ `{{lamp}} new path/to/folder --web --name "Its Name"` makes a new web app's page from Lamp's starting files:
35
+ `index.html`, `style.css` and `app.js`, which are yours to write, `APP.md`, and `lamp.js`, Lamp's building blocks for
36
+ a page (saved data with `LampStore`, the app's files and more). Read Lamp's `web-app` skill before writing it, and
37
+ the comments in `lamp.js` for how each block is used; never edit `lamp.js`. What a block asks of Lamp's app as the
38
+ page runs (its AI) isn't answered here. A page that wants none of Lamp's needs no starting files: write its
39
+ `index.html` in an empty folder.
40
+
41
+ ## A Mac app
42
+
43
+ A folder with `Package.swift`, `build.sh` and `Sources/LampSupport.swift` and no page is a Mac app Lamp made in
44
+ Swift. `{{lamp}} new path/to/folder --mac --name "Its Name"` makes a new one: Lamp's building blocks, and a card it
45
+ shows until its code in `Sources/` is written. The same commands work on it, with these differences:
46
+
47
+ - **Lamp's building blocks** are what the app is made with: saved data, AI, windows, the menu bar and the rest.
48
+ `{{lamp}} blocks` lists them with what each is for, and `{{lamp}} blocks LampStore` says how one is used: read the
49
+ ones the app needs before writing it. Lamp's `building-blocks` and `app-kinds` skills say which to reach for and
50
+ how such an app is laid out; where a skill points to rules of Lamp's own that aren't here (a base design), use
51
+ your judgment.
52
+ - **A change is a build.** Each save to the app's code builds it again, a few seconds for a small change, and opens
53
+ it again: what was typed or open in it is gone, so change first and try after. `look` waits for the build.
54
+ - **`look`** answers pictures of the app's windows (taken by the app itself, so nothing is asked of the person),
55
+ what it printed, and when it didn't build, the compiler's errors with their file and line: the app is then as it
56
+ was before the change. It answers the screen as text too once the app has been in front with the Mac unlocked;
57
+ without it, aim by the picture, whose points are the points to click. `look --reopen` quits the app and opens it
58
+ again first, as `{{lamp}} reload` does.
59
+ - **`use`** takes `click` (a point of the picture, or a name or id from the screen as text: `{{lamp}} use click "Add"`),
60
+ `type`, `key` (`return`, `escape`, `cmd+a`…), `drag`, `scroll` and `wait`. It brings the app to the front. Only
61
+ when asked to try it.
62
+ - **What you add while trying it is the app's real saved data**, kept under the app's own name in the person's
63
+ Application Support: take it out again, or tell them it's there.
64
+ - **The app stays open** when you finish, as the person's to use. `{{lamp}} stop` quits it, when they only wanted it
65
+ checked.
66
+ - **Lamp's own files** are `Sources/LampSupport.swift`, `build.sh` and `Package.swift`: never edit any of them.
67
+ - **A change into the open app, without reopening it**, is Lamp's app's: when the person has Lamp open and wants that,
68
+ `{{lamp}} open --in-lamp` gives the app to it (Lamp shows them its review the first time). From then on `look`, `dev`
69
+ and `reload` say how each change went in (live, held for their Reload, reopened, not built), and the person tries it
70
+ there, and `use` tries the app Lamp has open, in plain sight. `{{lamp}} open --here` has lamp run its own copy again.
71
+ - **Not here:** the app's AI (`LampAI`), and a link to one on lamp.dev (its Lamp app file is here: see "A Lamp app
72
+ file"). Those
73
+ are Lamp's app's: say so rather than working around it. What the app keeps secret (`LampSecrets`) is kept for it.
74
+
75
+ ## A game that's already there
76
+
77
+ A web game from somewhere else runs as it is: every command here works on it, each change opens its page again from
78
+ the start, and `look` can't know when it has finished loading. Putting it on Lamp's runtime is what lets it take
79
+ changes while it's played and say when it's really playing. `{{lamp}} init` puts Lamp's own files beside its page and
80
+ changes none of the page's; taking the runtime up in the game's code is the work. It goes in steps, each worth having
81
+ by itself:
82
+
83
+ 1. **The runtime runs the game's loop** (`game()` in place of the game's own), with its renderer kept and the
84
+ player's place given and taken back. A change then runs the game's code again in place, where before it opened
85
+ the page again. A page laid out at the window's size that reads its own keys and touches says so to `game()`:
86
+ the options are in `lamp-game.js`'s comments on the frame.
87
+ 2. **The modules that get tuned accept their changes**, and those go in live.
88
+ 3. **What's slow to build is kept**, so running the code again doesn't build it again.
89
+
90
+ Lamp's `game-live` skill says how each is done (its "A game from before this, or one brought in" is step 1), and
91
+ `lamp-game.js`'s comments are the whole interface: read those, not `web-game`, which is for a new game. A game
92
+ brought in reads its own input until its code reads the runtime's, so try it with keys, not Lamp's controller.
93
+
94
+ Where Lamp's `github-projects` skill has Lamp's app keep the project's credit and licenses (`lampify`), nothing does
95
+ here: keep its license file, its copyright headers and its author's credit on screen yourself.
96
+
97
+ ## The loop
98
+
99
+ 1. **Show the person the app** once, when you start, unless they don't want to watch: `{{lamp}} open`. It opens a
100
+ window they can use and play in while you work, and returns at once.
101
+ 2. **Change the files.**
102
+ 3. **Look**: `{{lamp}} look`. It waits for the change to go in, then answers how it went, a picture of the page (a
103
+ file: read it; the last forty are kept), the screen as text, and the errors and the log since your last look. Look
104
+ after every change, and read the errors and the picture before saying it works. `{{lamp}} look --reopen` opens the
105
+ page again from its beginning first, a game with its saves kept: what someone opening it sees. `--size 900x600`
106
+ looks at it as a window of that size shows it, for a layout that has to hold at any shape (with no window open).
107
+
108
+ Nothing has to be running first. With no window open, `look` runs the app itself in a copy of the page nobody sees,
109
+ opened from the files as they are, so the first look has no changes to report. The copy goes on running between
110
+ commands, as a window would: what you clicked and typed is still there, and a game's clock doesn't wait for you. It
111
+ closes by itself ten minutes after you last used it: there's nothing to stop when you finish.
112
+
113
+ ## Trying it
114
+
115
+ Only when the person asks you to try, play or test the app: a request to change it is made and looked at, not played.
116
+
117
+ - `{{lamp}} use click "Add"` clicks a control by its name in the screen as text, and `{{lamp}} use click 640 400` a
118
+ point of the picture, for what has no name there (a canvas, a drawing). The answer names what the click landed on.
119
+ - `{{lamp}} use type hello` types into whatever has the keyboard: click a field first.
120
+ - `{{lamp}} use key w 2` holds a key for two seconds (a letter, a digit, `space`, `enter`, `escape`, `up`, `left`…),
121
+ and `w+d` holds two at once.
122
+ - `{{lamp}} use drag 400 300 700 300` presses at one point, moves to the other and lets go.
123
+ - `{{lamp}} use scroll 600` scrolls down, and up with a negative number. A look shows only what's in the window.
124
+ - `{{lamp}} use wait 3` waits, for something that takes time: thirty seconds at most, so wait again for longer.
125
+
126
+ Several moves go in one command with `then` between them, one after another with nothing in between and one look at
127
+ the end: `{{lamp}} use click 640 400 then key w 3 then key w+d 2`. Play anything with a clock that way, a whole
128
+ stretch of it to a command, and end the stretch on the game's pause when it has one (`… then button menu`): the game
129
+ runs on while you read a picture. Where a canvas is drawn at another size than it's shown, the screen as text says
130
+ how a point of the game is found in the picture.
131
+
132
+ A game on Lamp's runtime is played with Lamp's own controller, as Lamp's game skills say (`use_app`'s `stick` and
133
+ `button`):
134
+
135
+ - `{{lamp}} use stick left 1 0 2` holds the left stick to the right for two seconds: `left` or `right`, then x and y
136
+ from -1 to 1, right and up being 1. A button named after the seconds is held with it (`… 2 a`).
137
+ - `{{lamp}} use button a` presses a button, `a 1.5` holds it, and `a+rt` holds two: `a`, `b`, `x`, `y`, `lb`, `rb`,
138
+ the triggers `lt` and `rt`, `menu`, `view`, `up`, `down`, `left`, `right`.
139
+
140
+ It's the first player's controller, from wherever the game is. It isn't a controller plugged in, so the game's
141
+ prompts go on naming keys. If the person plays meanwhile they have it back at once and the answer says so: the game
142
+ is theirs until they ask again. A key works in a game here too.
143
+
144
+ Each answers with a look. With the window open it happens in the person's own window, where they see it.
145
+
146
+ ## How a change went in
147
+
148
+ `look` says one of these for each change since the last look:
149
+
150
+ - **live**: swapped in while the page ran. Nothing was lost.
151
+ - **reran**: the game's code ran again, with the player where they were. In a small game that takes a moment, and
152
+ is as good as live.
153
+ - **reopened**: the page opened again. A game opens from the player's place. A plain page always takes a change this
154
+ way and starts over: what was typed or counted in it is gone, so change first and try after.
155
+ - **held**: the change waits, and the page shows the person a Reload to apply button. Either it waits for a pause in
156
+ the game (the end of a round, a menu), and goes in by itself then: a later look says so. Or for that button, because
157
+ the page must open again for it: `{{lamp}} reload` presses it, so with a window open ask the person first.
158
+
159
+ The reason given after one names the file that changed, where an `accept()` would have taken the change, and the
160
+ module it's loaded through. A game that takes changes live is written for it. When a change won't go in, needs Reload
161
+ or loses the player's place, read Lamp's `game-live` skill before working around it.
162
+
163
+ ## A Lamp app file
164
+
165
+ A folder with `lamp-app.json` at its top (or in `.lamp-wish/`) is an app in Lamp's format, from GitHub or a shared file:
166
+ every command here works on a web app, a game, a screen or a Mac app in one, and says so for a kind it doesn't run.
167
+
168
+ - `{{lamp}} unpack Name.lampapp` unpacks a Lamp app file (what Lamp's Share… makes) into a new folder beside it, with
169
+ Lamp's own files put in, and says how to see it.
170
+ - `{{lamp}} export` makes the app's Lamp app file beside its folder, for the person to send or open in Lamp: only when
171
+ they ask. It's refused when something in the app is shaped like a key, or a license its credits name is gone; when
172
+ it uses work that came with no license, ask the person before `--anyway`.
173
+
174
+ ## Sharing it
175
+
176
+ Only when the person asks: a link is public, and anyone who has it can play the page.
177
+
178
+ - `{{lamp}} share --words "What it is, in a sentence or a few"` puts the page on lamp.dev and answers its link. `--line`
179
+ is a line under its name, `--asks "Found a bug?|What's missing?"` what the box under the page asks people, and
180
+ `--by "Their Name"` who it's by: only a name the person gave you to show. A page that's logging errors isn't shared
181
+ until they're put right.
182
+ - Again, after changes, it sends the page as it is now to the same link, with the same words unless you give new ones.
183
+ - `{{lamp}} ideas` lists what people playing it have sent. Once one is in the game and the game shared again,
184
+ `{{lamp}} ideas in <number>` says so, and whoever asked to hear is written to; `{{lamp}} ideas dismiss <number>` lets
185
+ one go.
186
+ - `{{lamp}} unshare` takes the link down.
187
+
188
+ Tell the person the link, and that it's public.
189
+
190
+ ## On the person's Xbox
191
+
192
+ A page goes on an Xbox in Developer Mode, in Lamp's own host for the console's browser: the same files, played with
193
+ the console's controller. Only when the person asks for it there, and only on a device they set up.
194
+
195
+ - `{{lamp}} devices` lists the devices set up with lamp and those found on the network. One only found may not be
196
+ theirs: never put anything on it.
197
+ - Setting one up asks for the console's Device Portal password, which only the person types. Ask them to run
198
+ `{{lamp}} devices add` in a terminal themselves; never ask for the password, and never type one.
199
+ - `{{lamp}} open --on xbox` packages the page as it is now, installs it and opens it on the console, in place of the
200
+ copy that was there. A change isn't live there: put the page on again once it works on this computer.
201
+ - `{{lamp}} look --on xbox` is the console's screen as a picture, whether the app is open there, and what it logged
202
+ there. A game on Lamp's runtime logs how many frames a second it gets: that, never this computer's, says how it
203
+ runs on the console.
204
+ - You can't press the controller there. Try the game in its window here (`stick`, `button`), where it's the same
205
+ code, and tell the person what's left for them to try with the controller in their hands.
206
+ - `{{lamp}} stop --on xbox` ends it, and `{{lamp}} remove --on xbox` takes it off the console.
207
+
208
+ ## On Android
209
+
210
+ A page goes on Android in Lamp's own Android app around it: the same files, on a phone, a tablet or a TV. It needs a
211
+ Mac with Android's tools, which `{{lamp}} devices` says are there or not. If they aren't, ask the person to run
212
+ `{{lamp}} devices add android` in a terminal themselves: it downloads Google's tools and accepts Google's terms for
213
+ them, which is theirs to do.
214
+
215
+ - `{{lamp}} open --on android` builds the app and opens it in lamp's Android emulator, a phone in a window on the Mac;
216
+ `--on android-tv` is its TV emulator. Use these when the person asks to see it on Android.
217
+ - For a check of your own, add `--hidden`: the emulator starts with no window and no sound, and
218
+ `{{lamp}} stop --on android` closes it when you're done. Don't leave one running.
219
+ - A phone, tablet or TV of the person's goes by its name (`{{lamp}} devices` lists those plugged in with USB debugging
220
+ on): only when they ask for it there. If it says to allow debugging, that's a tap on the device's own screen, theirs.
221
+ - `{{lamp}} look --on android` is the device's screen as a picture, whether the app is open, and what the page logged
222
+ there: a game on Lamp's runtime logs how many frames a second it gets.
223
+ - `{{lamp}} use --on android click <x> <y>` taps a point of that picture; `drag`, `type`, `key` and `button` work too,
224
+ one key or button at a time, with no stick. A game shows touch controls until a controller's button is pressed.
225
+ - A change isn't live there: `{{lamp}} open --on android` again builds and installs it, in a few seconds.
226
+ - `{{lamp}} remove --on android` takes it off.
227
+
228
+ ## Lamp's skills
229
+
230
+ An app Lamp made (its page loads `lamp.js`) is built from Lamp's own building blocks, and Lamp has guidance for each
231
+ kind of work on one: a new web game, 3D, how a game feels, a web app's page. `{{lamp}} skills game` lists those about a
232
+ word, `{{lamp}} skills` all of them, and `{{lamp}} skill <name>` prints one. Read the ones that fit before changing what
233
+ they cover: they are the one place that says which building blocks to use and how.
234
+
235
+ Those skills are written for Lamp's app, which builds the game, opens it and looks at it for you when your turn
236
+ ends, and so tells you to write and finish without looking or playing. Nothing does that here: you look after every
237
+ change, as above, and that comes first. Where one names a tool of Lamp's:
238
+
239
+ - `look_at_app` is `{{lamp}} look`, and its `reopen` is `--reopen`. There's no `motion`: look twice.
240
+ - `use_app` is `{{lamp}} use`, one move to each of its actions. A control on the page is clicked at its point from the
241
+ screen as text, not by an id.
242
+ - `read_skill` is `{{lamp}} skill <name>`, and `make_app_for` is `{{lamp}} new`, for a web game only.
243
+ - `delete_file` is deleting the file, and putting a change in needs no tool.
244
+ - `assets`, `make_art` and `lampify` aren't here: make what's needed in code, or say what's missing.
245
+
246
+ A plain site, on neither `lamp.js` nor Lamp's runtime, uses none of them: skip the skills there.
247
+
248
+ ## Rules
249
+
250
+ - Lamp's own files in the folder are rewritten by Lamp, so read them and never edit them: `lamp.js`, `lamp-game.js`,
251
+ `lamp-phaser.js`, `lamp-controllers.js`, and the `three/` and `phaser/` folders.
252
+ - The page's whole log is the file `look` names.
253
+ - lamp runs the page in a browser on this computer, and puts it on an Xbox ("On the person's Xbox") and on Android
254
+ ("On Android"). iPhones, Samsung and LG TVs,
255
+ and whatever needs Lamp's Mac app around the page, aren't here: say so rather than working around it.
package/cli/skills.mjs ADDED
@@ -0,0 +1,71 @@
1
+ // Lamp's skills as `lamp skill` prints them: read from Lamp's own folder (Resources/skills), and put together the way
2
+ // Lamp's app puts them together (`Skills.parse`, `Skills.assembled`, `Skills.section`). A skill made of sections of
3
+ // others names them in its frontmatter ("game#Fun; game-ui#Proof") and has them put where its body says
4
+ // `{{sections}}`, so each section is written in one place.
5
+
6
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
7
+ import { dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { RESOURCES } from "./state.mjs";
10
+
11
+ export const SKILLS = join(RESOURCES, "skills");
12
+
13
+ /** A SKILL.md: frontmatter between `---` lines, a field a line, then the instructions. */
14
+ function parse(text) {
15
+ const lines = text.split("\n");
16
+ const close = lines.indexOf("---", 1);
17
+ if (lines[0] !== "---" || close < 0) return null;
18
+ const fields = {};
19
+ for (const line of lines.slice(1, close)) {
20
+ const colon = line.indexOf(":");
21
+ if (colon > 0) fields[line.slice(0, colon).trim()] = line.slice(colon + 1).trim();
22
+ }
23
+ if (!fields.name || !fields.description) return null;
24
+ return { name: fields.name, description: fields.description, sections: fields.sections ?? null, body: lines.slice(close + 1).join("\n").trim() };
25
+ }
26
+
27
+ /** One section of a skill, as "skill#Heading": its heading, made a second-level one, and what's under it. */
28
+ function section(name, skills) {
29
+ const at = name.indexOf("#");
30
+ const source = at < 0 ? null : skills.get(name.slice(0, at))?.body;
31
+ if (source == null) return null;
32
+ const title = name.slice(at + 1), lines = source.split("\n");
33
+ // A line of a code block is never a heading, whatever it starts with.
34
+ let fenced = false;
35
+ const headings = [];
36
+ lines.forEach((line, index) => {
37
+ if (line.startsWith("```")) { fenced = !fenced; return; }
38
+ const marks = /^(#+) /.exec(line);
39
+ if (!fenced && marks) headings.push({ index, level: marks[1].length, title: line.slice(marks[1].length).trim() });
40
+ });
41
+ if (!title) {
42
+ // The text before the skill's first section.
43
+ const first = headings.find((heading) => heading.level === 1), second = headings.find((heading) => heading.level === 2);
44
+ const start = first ? first.index + 1 : 0, end = second ? second.index : lines.length;
45
+ return lines.slice(start, Math.max(start, end)).join("\n").trim() || null;
46
+ }
47
+ const found = headings.findIndex((heading) => heading.title === title && heading.level > 1);
48
+ if (found < 0) return null;
49
+ const heading = headings[found], next = headings.slice(found + 1).find((later) => later.level <= heading.level);
50
+ return `## ${heading.title}\n\n${lines.slice(heading.index + 1, next ? next.index : lines.length).join("\n").trim()}`;
51
+ }
52
+
53
+ /** Every skill by name, each as Lamp's app hands it over. Empty when Lamp's skills aren't beside this copy of lamp. */
54
+ export function allSkills() {
55
+ const skills = new Map();
56
+ if (!existsSync(SKILLS)) return skills;
57
+ for (const entry of readdirSync(SKILLS, { withFileTypes: true })) {
58
+ if (!entry.isDirectory()) continue;
59
+ let skill = null;
60
+ try { skill = parse(readFileSync(join(SKILLS, entry.name, "SKILL.md"), "utf8")); } catch {}
61
+ if (skill) skills.set(skill.name, skill);
62
+ }
63
+ // Sections come from the skills as they're written, never from one already put together.
64
+ const written = new Map(skills);
65
+ for (const skill of written.values()) {
66
+ if (!skill.sections) continue;
67
+ const text = skill.sections.split(";").map((name) => name.trim()).filter(Boolean).map((name) => section(name, written)).filter(Boolean).join("\n\n");
68
+ skills.set(skill.name, { ...skill, body: skill.body.includes("{{sections}}") ? skill.body.replaceAll("{{sections}}", text) : `${skill.body}\n\n${text}` });
69
+ }
70
+ return skills;
71
+ }