@lampdotdev/lamp 0.0.0-stage → 0.36.2-nightly.16
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.
- package/LICENSE +21 -0
- package/README.md +397 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1813 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/page/lamp-live.js +672 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3042 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/share-rules.json +64 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +416 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +62 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +170 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +108 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/ai.mjs +237 -0
- package/cli/android.mjs +941 -0
- package/cli/app-ai.mjs +473 -0
- package/cli/browser.mjs +284 -0
- package/cli/calls.mjs +594 -0
- package/cli/dev.mjs +820 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1326 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6922 -0
- package/cli/lamps/lamp.js +7082 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18215 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7082 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +202 -0
- package/cli/local-ai.mjs +193 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/openrouter.mjs +133 -0
- package/cli/outside.mjs +203 -0
- package/cli/page.js +317 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +270 -0
- package/cli/skill/SKILL.md +280 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +176 -0
- package/cli/update.mjs +162 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +1727 -0
package/cli/png.mjs
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Just enough PNG for the pictures lamp makes itself: an app's icon on the tile a device shows it on, at the sizes the
|
|
2
|
+
// device's package names (`DeviceSupport.iconPNG` in Lamp's app, which draws the same tile with AppKit).
|
|
3
|
+
|
|
4
|
+
import { deflateSync, inflateSync } from "node:zlib";
|
|
5
|
+
|
|
6
|
+
const SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
7
|
+
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; });
|
|
8
|
+
function crc32(bytes) {
|
|
9
|
+
let c = 0xffffffff;
|
|
10
|
+
for (let i = 0; i < bytes.length; i++) c = CRC[(c ^ bytes[i]) & 0xff] ^ (c >>> 8);
|
|
11
|
+
return (c ^ 0xffffffff) >>> 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function chunk(type, data) {
|
|
15
|
+
const head = Buffer.alloc(8), sum = Buffer.alloc(4);
|
|
16
|
+
head.writeUInt32BE(data.length, 0);
|
|
17
|
+
head.write(type, 4, "latin1");
|
|
18
|
+
sum.writeUInt32BE(crc32(Buffer.concat([head.subarray(4), data])), 0);
|
|
19
|
+
return Buffer.concat([head, data, sum]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A PNG of these pixels (four bytes each: red, green, blue, alpha). */
|
|
23
|
+
export function encode(width, height, rgba) {
|
|
24
|
+
const header = Buffer.alloc(13);
|
|
25
|
+
header.writeUInt32BE(width, 0);
|
|
26
|
+
header.writeUInt32BE(height, 4);
|
|
27
|
+
header[8] = 8; // eight bits a channel
|
|
28
|
+
header[9] = 6; // color with alpha
|
|
29
|
+
const rows = Buffer.alloc((width * 4 + 1) * height);
|
|
30
|
+
for (let y = 0; y < height; y++) rgba.copy(rows, y * (width * 4 + 1) + 1, y * width * 4, (y + 1) * width * 4);
|
|
31
|
+
return Buffer.concat([SIGNATURE, chunk("IHDR", header), chunk("IDAT", deflateSync(rows)), chunk("IEND", Buffer.alloc(0))]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A PNG's pixels (four bytes each), or null for one this doesn't read: only what an icon is saved as, eight bits a
|
|
36
|
+
* channel and not interlaced.
|
|
37
|
+
*/
|
|
38
|
+
export function decode(bytes) {
|
|
39
|
+
try {
|
|
40
|
+
if (bytes.length < 33 || !bytes.subarray(0, 8).equals(SIGNATURE)) return null;
|
|
41
|
+
let width = 0, height = 0, kind = 0, palette = null, clear = null;
|
|
42
|
+
const packed = [];
|
|
43
|
+
for (let at = 8; at + 12 <= bytes.length;) {
|
|
44
|
+
const length = bytes.readUInt32BE(at), type = bytes.toString("latin1", at + 4, at + 8), data = bytes.subarray(at + 8, at + 8 + length);
|
|
45
|
+
if (type === "IHDR") {
|
|
46
|
+
width = data.readUInt32BE(0); height = data.readUInt32BE(4); kind = data[9];
|
|
47
|
+
if (data[8] !== 8 || data[12] !== 0 || ![0, 2, 3, 4, 6].includes(kind)) return null;
|
|
48
|
+
} else if (type === "PLTE") palette = data;
|
|
49
|
+
else if (type === "tRNS") clear = data;
|
|
50
|
+
else if (type === "IDAT") packed.push(data);
|
|
51
|
+
else if (type === "IEND") break;
|
|
52
|
+
at += 12 + length;
|
|
53
|
+
}
|
|
54
|
+
if (!width || !height || width > 8192 || height > 8192) return null;
|
|
55
|
+
const channels = { 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 }[kind], stride = width * channels;
|
|
56
|
+
const raw = inflateSync(Buffer.concat(packed));
|
|
57
|
+
if (raw.length < (stride + 1) * height) return null;
|
|
58
|
+
const lines = Buffer.alloc(stride * height);
|
|
59
|
+
for (let y = 0; y < height; y++) {
|
|
60
|
+
const filter = raw[y * (stride + 1)], from = y * (stride + 1) + 1, to = y * stride;
|
|
61
|
+
for (let x = 0; x < stride; x++) {
|
|
62
|
+
const left = x >= channels ? lines[to + x - channels] : 0, up = y ? lines[to + x - stride] : 0;
|
|
63
|
+
const corner = x >= channels && y ? lines[to + x - stride - channels] : 0;
|
|
64
|
+
let guess = 0;
|
|
65
|
+
if (filter === 1) guess = left;
|
|
66
|
+
else if (filter === 2) guess = up;
|
|
67
|
+
else if (filter === 3) guess = (left + up) >> 1;
|
|
68
|
+
else if (filter === 4) {
|
|
69
|
+
const p = left + up - corner, a = Math.abs(p - left), b = Math.abs(p - up), c = Math.abs(p - corner);
|
|
70
|
+
guess = a <= b && a <= c ? left : b <= c ? up : corner;
|
|
71
|
+
}
|
|
72
|
+
lines[to + x] = (raw[from + x] + guess) & 0xff;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const rgba = Buffer.alloc(width * height * 4);
|
|
76
|
+
for (let i = 0; i < width * height; i++) {
|
|
77
|
+
const at = i * channels;
|
|
78
|
+
let r, g, b, a = 255;
|
|
79
|
+
if (kind === 0) r = g = b = lines[at];
|
|
80
|
+
else if (kind === 4) { r = g = b = lines[at]; a = lines[at + 1]; }
|
|
81
|
+
else if (kind === 2) { r = lines[at]; g = lines[at + 1]; b = lines[at + 2]; }
|
|
82
|
+
else if (kind === 6) { r = lines[at]; g = lines[at + 1]; b = lines[at + 2]; a = lines[at + 3]; }
|
|
83
|
+
else {
|
|
84
|
+
if (!palette) return null;
|
|
85
|
+
const index = lines[at];
|
|
86
|
+
r = palette[index * 3]; g = palette[index * 3 + 1]; b = palette[index * 3 + 2];
|
|
87
|
+
a = clear && index < clear.length ? clear[index] : 255;
|
|
88
|
+
}
|
|
89
|
+
rgba[i * 4] = r; rgba[i * 4 + 1] = g; rgba[i * 4 + 2] = b; rgba[i * 4 + 3] = a;
|
|
90
|
+
}
|
|
91
|
+
return { width, height, rgba };
|
|
92
|
+
} catch { return null; }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** A PNG's size in pixels, read from its header; null when it isn't one. */
|
|
96
|
+
export function sizeOf(bytes) {
|
|
97
|
+
if (bytes.length < 24 || !bytes.subarray(0, 8).equals(SIGNATURE)) return null;
|
|
98
|
+
return { width: bytes.readUInt32BE(16), height: bytes.readUInt32BE(20) };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The app's icon as a square of that many pixels, clear where the icon is: what a phone's home screen shows. Null for
|
|
103
|
+
* no icon, or one this can't read.
|
|
104
|
+
*/
|
|
105
|
+
export function scaled(icon, side) {
|
|
106
|
+
const picture = icon && decode(icon);
|
|
107
|
+
if (!picture) return null;
|
|
108
|
+
const out = Buffer.alloc(side * side * 4), across = picture.width / side, down = picture.height / side;
|
|
109
|
+
for (let y = 0; y < side; y++) {
|
|
110
|
+
for (let x = 0; x < side; x++) {
|
|
111
|
+
const x0 = Math.floor(x * across), x1 = Math.max(x0 + 1, Math.min(picture.width, Math.ceil((x + 1) * across)));
|
|
112
|
+
const y0 = Math.floor(y * down), y1 = Math.max(y0 + 1, Math.min(picture.height, Math.ceil((y + 1) * down)));
|
|
113
|
+
let r = 0, g = 0, b = 0, a = 0;
|
|
114
|
+
for (let sy = y0; sy < y1; sy++) {
|
|
115
|
+
for (let sx = x0; sx < x1; sx++) {
|
|
116
|
+
const at = (Math.min(sy, picture.height - 1) * picture.width + Math.min(sx, picture.width - 1)) * 4, alpha = picture.rgba[at + 3];
|
|
117
|
+
r += picture.rgba[at] * alpha; g += picture.rgba[at + 1] * alpha; b += picture.rgba[at + 2] * alpha; a += alpha;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (!a) continue;
|
|
121
|
+
const at = (y * side + x) * 4;
|
|
122
|
+
out[at] = Math.round(r / a); out[at + 1] = Math.round(g / a); out[at + 2] = Math.round(b / a);
|
|
123
|
+
out[at + 3] = Math.round(a / ((x1 - x0) * (y1 - y0)));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return encode(side, side, out);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** A PNG made `width` pixels wide, its height in proportion; null for one this can't read. */
|
|
130
|
+
export function resized(bytes, width) {
|
|
131
|
+
const picture = decode(bytes);
|
|
132
|
+
if (!picture) return null;
|
|
133
|
+
width = Math.max(1, Math.round(width));
|
|
134
|
+
const height = Math.max(1, Math.round((picture.height * width) / picture.width)), out = Buffer.alloc(width * height * 4);
|
|
135
|
+
const across = picture.width / width, down = picture.height / height;
|
|
136
|
+
for (let y = 0; y < height; y++) {
|
|
137
|
+
for (let x = 0; x < width; x++) {
|
|
138
|
+
const x0 = Math.floor(x * across), x1 = Math.max(x0 + 1, Math.min(picture.width, Math.ceil((x + 1) * across)));
|
|
139
|
+
const y0 = Math.floor(y * down), y1 = Math.max(y0 + 1, Math.min(picture.height, Math.ceil((y + 1) * down)));
|
|
140
|
+
const sum = [0, 0, 0, 0];
|
|
141
|
+
for (let sy = y0; sy < y1; sy++) for (let sx = x0; sx < x1; sx++) { const at = (sy * picture.width + sx) * 4; for (let c = 0; c < 4; c++) sum[c] += picture.rgba[at + c]; }
|
|
142
|
+
const count = (x1 - x0) * (y1 - y0), at = (y * width + x) * 4;
|
|
143
|
+
for (let c = 0; c < 4; c++) out[at + c] = Math.round(sum[c] / count);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return encode(width, height, out);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// The tile's color: Lamp's dark blue, the same one the package's manifest names for the tile behind it.
|
|
150
|
+
const TILE = [27, 27, 58];
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The app's icon centered on its tile's color at a logo's size, or the color alone when the app has no icon (or one
|
|
154
|
+
* this can't read): a device's package names these files, and shows nothing in their place without them.
|
|
155
|
+
*/
|
|
156
|
+
export function tile(icon, width, height) {
|
|
157
|
+
const out = Buffer.alloc(width * height * 4);
|
|
158
|
+
for (let i = 0; i < width * height; i++) { out[i * 4] = TILE[0]; out[i * 4 + 1] = TILE[1]; out[i * 4 + 2] = TILE[2]; out[i * 4 + 3] = 255; }
|
|
159
|
+
const picture = icon && decode(icon);
|
|
160
|
+
if (picture) {
|
|
161
|
+
const side = Math.round(Math.min(width, height) * 0.8), left = Math.round((width - side) / 2), top = Math.round((height - side) / 2);
|
|
162
|
+
const across = picture.width / side, down = picture.height / side;
|
|
163
|
+
for (let y = 0; y < side; y++) {
|
|
164
|
+
for (let x = 0; x < side; x++) {
|
|
165
|
+
// Each pixel is the average of the part of the icon it covers, so a large icon made small stays smooth.
|
|
166
|
+
const x0 = Math.floor(x * across), x1 = Math.max(x0 + 1, Math.min(picture.width, Math.ceil((x + 1) * across)));
|
|
167
|
+
const y0 = Math.floor(y * down), y1 = Math.max(y0 + 1, Math.min(picture.height, Math.ceil((y + 1) * down)));
|
|
168
|
+
let r = 0, g = 0, b = 0, a = 0;
|
|
169
|
+
for (let sy = y0; sy < y1; sy++) {
|
|
170
|
+
for (let sx = x0; sx < x1; sx++) {
|
|
171
|
+
const at = (Math.min(sy, picture.height - 1) * picture.width + Math.min(sx, picture.width - 1)) * 4, alpha = picture.rgba[at + 3];
|
|
172
|
+
r += picture.rgba[at] * alpha; g += picture.rgba[at + 1] * alpha; b += picture.rgba[at + 2] * alpha; a += alpha;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!a) continue;
|
|
176
|
+
const cover = a / ((x1 - x0) * (y1 - y0)) / 255, at = ((top + y) * width + left + x) * 4;
|
|
177
|
+
out[at] = Math.round((r / a) * cover + TILE[0] * (1 - cover));
|
|
178
|
+
out[at + 1] = Math.round((g / a) * cover + TILE[1] * (1 - cover));
|
|
179
|
+
out[at + 2] = Math.round((b / a) * cover + TILE[2] * (1 - cover));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return encode(width, height, out);
|
|
184
|
+
}
|
package/cli/share.mjs
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
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 { execFileSync } from "node:child_process";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
13
|
+
import { deflateRawSync } from "node:zlib";
|
|
14
|
+
import { NOTES_FILE, Problem, stateOf } from "./state.mjs";
|
|
15
|
+
import { ANY_BROWSER, CONTROLLERS, CONTROLLERS_FILE, DEVICE_FILE, lampJS, LIBRARIES } from "./dev.mjs";
|
|
16
|
+
import { LIMITS, FILE_LIMITS, PAGE_LIMITS } from "../site/lib/shared-wishes.js";
|
|
17
|
+
import { ideasOf, makerOf, pageUp, publishLink, removeFile, removeIdea, removeLink, replyIdea, sendFile, siteOrigin } from "./link.mjs";
|
|
18
|
+
import { exportApp } from "./lampapp.mjs";
|
|
19
|
+
|
|
20
|
+
export { siteOrigin };
|
|
21
|
+
|
|
22
|
+
const linkFileOf = (folder) => join(stateOf(folder), "link.json");
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The maker's account on a site, as lamp keeps it (`lamp account`): `{ username, key }`, the key sent with every share
|
|
27
|
+
* so a link goes under the username (lamp.dev/<username>/<app>). Kept with lamp's state, never in a folder.
|
|
28
|
+
*/
|
|
29
|
+
const accountsFile = () => join(process.env.LAMP_DEV_HOME || join(homedir(), ".lamp", "dev"), "account.json");
|
|
30
|
+
export function accountFor(site = siteOrigin()) {
|
|
31
|
+
try { const kept = JSON.parse(readFileSync(accountsFile(), "utf8"))[site]; return kept?.key ? kept : null; } catch { return null; }
|
|
32
|
+
}
|
|
33
|
+
export function keepAccount(site, account) {
|
|
34
|
+
let all = {};
|
|
35
|
+
try { all = JSON.parse(readFileSync(accountsFile(), "utf8")) || {}; } catch {}
|
|
36
|
+
all[site] = account;
|
|
37
|
+
mkdirSync(dirname(accountsFile()), { recursive: true });
|
|
38
|
+
writeFileSync(accountsFile(), JSON.stringify(all, null, 2), { mode: 0o600 });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The folder's link, as it was last shared: its address, its secret and the words it went out with. */
|
|
42
|
+
export function readLink(folder) {
|
|
43
|
+
try { return JSON.parse(readFileSync(linkFileOf(folder), "utf8")); } catch { return null; }
|
|
44
|
+
}
|
|
45
|
+
/** Forgets the folder's link here, leaving it on the site (one Lamp's app let go of, say). */
|
|
46
|
+
export function forgetLink(folder) { rmSync(linkFileOf(folder), { force: true }); }
|
|
47
|
+
export function writeLink(folder, link) {
|
|
48
|
+
mkdirSync(stateOf(folder), { recursive: true });
|
|
49
|
+
writeFileSync(linkFileOf(folder), JSON.stringify(link, null, 2), { mode: 0o600 });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// MARK: The page, as a zip
|
|
53
|
+
|
|
54
|
+
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; });
|
|
55
|
+
function crc32(bytes) {
|
|
56
|
+
let c = 0xffffffff;
|
|
57
|
+
for (let i = 0; i < bytes.length; i++) c = CRC[(c ^ bytes[i]) & 0xff] ^ (c >>> 8);
|
|
58
|
+
return (c ^ 0xffffffff) >>> 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** A zip of these files (`[path, bytes]`), each packed where that makes it smaller. */
|
|
62
|
+
export function zipOf(files) {
|
|
63
|
+
const parts = [], listing = [];
|
|
64
|
+
let offset = 0;
|
|
65
|
+
for (const [path, bytes] of files) {
|
|
66
|
+
const name = Buffer.from(path, "utf8"), packed = deflateRawSync(bytes), stored = packed.length >= bytes.length;
|
|
67
|
+
const data = stored ? bytes : packed, sum = crc32(bytes);
|
|
68
|
+
const head = Buffer.alloc(30);
|
|
69
|
+
head.writeUInt32LE(0x04034b50, 0);
|
|
70
|
+
head.writeUInt16LE(20, 4);
|
|
71
|
+
head.writeUInt16LE(0x0800, 6); // the name is UTF-8
|
|
72
|
+
head.writeUInt16LE(stored ? 0 : 8, 8);
|
|
73
|
+
head.writeUInt32LE(sum, 14);
|
|
74
|
+
head.writeUInt32LE(data.length, 18);
|
|
75
|
+
head.writeUInt32LE(bytes.length, 22);
|
|
76
|
+
head.writeUInt16LE(name.length, 26);
|
|
77
|
+
const entry = Buffer.alloc(46);
|
|
78
|
+
entry.writeUInt32LE(0x02014b50, 0);
|
|
79
|
+
entry.writeUInt16LE(20, 4);
|
|
80
|
+
entry.writeUInt16LE(20, 6);
|
|
81
|
+
head.copy(entry, 8, 6, 30); // the same flags, method, sum, sizes and name length
|
|
82
|
+
entry.writeUInt32LE(offset, 42);
|
|
83
|
+
parts.push(head, name, data);
|
|
84
|
+
listing.push(entry, name);
|
|
85
|
+
offset += 30 + name.length + data.length;
|
|
86
|
+
}
|
|
87
|
+
const directory = Buffer.concat(listing), end = Buffer.alloc(22);
|
|
88
|
+
end.writeUInt32LE(0x06054b50, 0);
|
|
89
|
+
end.writeUInt16LE(files.length, 8);
|
|
90
|
+
end.writeUInt16LE(files.length, 10);
|
|
91
|
+
end.writeUInt32LE(directory.length, 12);
|
|
92
|
+
end.writeUInt32LE(offset, 16);
|
|
93
|
+
return Buffer.concat([...parts, directory, end]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Every file of the page as it's played from the link: what's in its folder (nothing hidden, no link followed, the
|
|
98
|
+
* 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
|
|
99
|
+
* (`GamePage.stage`): the device a browser on any device is, the build's name, and what the folder has none of.
|
|
100
|
+
* A copy for one device (place.mjs) is given that device in its place.
|
|
101
|
+
*/
|
|
102
|
+
export function pageFiles(layout, { device = ANY_BROWSER } = {}) {
|
|
103
|
+
const files = new Map();
|
|
104
|
+
const walk = (dir, prefix) => {
|
|
105
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
106
|
+
const path = prefix + entry.name;
|
|
107
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || path === NOTES_FILE) continue;
|
|
108
|
+
if (entry.isDirectory()) walk(join(dir, entry.name), path + "/");
|
|
109
|
+
else if (entry.isFile()) files.set(path, readFileSync(join(dir, entry.name)));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
walk(layout.root, "");
|
|
113
|
+
if (layout.game) {
|
|
114
|
+
files.set(DEVICE_FILE, Buffer.from(device));
|
|
115
|
+
if (!files.has(CONTROLLERS_FILE)) files.set(CONTROLLERS_FILE, readFileSync(CONTROLLERS));
|
|
116
|
+
if (!files.has("lamp.js")) files.set("lamp.js", Buffer.from(lampJS(true)));
|
|
117
|
+
// A library the page's import map names from beside it and the folder has none of: Lamp's copy.
|
|
118
|
+
const map = /<script[^>]*type=["']importmap["'][^>]*>([\s\S]*?)<\/script>/i.exec(String(files.get("index.html") ?? ""))?.[1] ?? "";
|
|
119
|
+
for (const name of ["three", "phaser", "rapier"]) {
|
|
120
|
+
if (!new RegExp(`:\\s*["'](?:\\./)?${name}/`).test(map) || [...files.keys()].some((path) => path.startsWith(`${name}/`))) continue;
|
|
121
|
+
const from = join(LIBRARIES, name);
|
|
122
|
+
if (!existsSync(from)) continue;
|
|
123
|
+
const copy = (dir, prefix) => {
|
|
124
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
125
|
+
if (entry.isDirectory()) copy(join(dir, entry.name), `${prefix}${entry.name}/`);
|
|
126
|
+
else if (entry.isFile() && !lstatSync(join(dir, entry.name)).isSymbolicLink()) files.set(prefix + entry.name, readFileSync(join(dir, entry.name)));
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
copy(from, `${name}/`);
|
|
130
|
+
}
|
|
131
|
+
// The build's name, for the runtime to tell a newer copy of the game by: named for the files as they are.
|
|
132
|
+
files.delete("lamp-build.js");
|
|
133
|
+
const hash = createHash("sha256");
|
|
134
|
+
for (const path of [...files.keys()].sort()) hash.update(path).update(files.get(path));
|
|
135
|
+
files.set("lamp-build.js", Buffer.from(`export default "${hash.digest("hex").slice(0, 16)}";\n`));
|
|
136
|
+
}
|
|
137
|
+
return [...files].sort(([a], [b]) => a.localeCompare(b));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// MARK: The site
|
|
141
|
+
|
|
142
|
+
/** The repository a git remote's address names on GitHub, as "owner/name", or null for any other place. */
|
|
143
|
+
export function githubRepoOf(remote) {
|
|
144
|
+
const found = /^(?:https:\/\/(?:[^@/]+@)?github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)([A-Za-z0-9-]{1,39})\/([A-Za-z0-9._-]{1,100}?)(?:\.git)?\/?$/.exec(String(remote ?? "").trim());
|
|
145
|
+
return found && found[2] !== "." && found[2] !== ".." ? `${found[1]}/${found[2]}` : null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The folder's repository on GitHub, for its link's page to point to: only when the folder is the top of a git
|
|
150
|
+
* checkout whose origin is on GitHub, and GitHub, asked with no sign-in, says anyone can read it. Null otherwise, and
|
|
151
|
+
* when git or GitHub can't answer, so nothing is linked that might not be public.
|
|
152
|
+
*/
|
|
153
|
+
export async function publicRepoOf(folder) {
|
|
154
|
+
let top, remote;
|
|
155
|
+
try {
|
|
156
|
+
top = execFileSync("git", ["-C", folder, "rev-parse", "--show-toplevel"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
157
|
+
remote = execFileSync("git", ["-C", folder, "remote", "get-url", "origin"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
158
|
+
} catch { return null; }
|
|
159
|
+
if (resolve(top) !== resolve(folder)) return null;
|
|
160
|
+
const repo = githubRepoOf(remote);
|
|
161
|
+
if (!repo) return null;
|
|
162
|
+
try {
|
|
163
|
+
const answer = await fetch(`https://api.github.com/repos/${repo}`, { headers: { accept: "application/vnd.github+json" }, signal: AbortSignal.timeout(6000) });
|
|
164
|
+
if (!answer.ok) return null;
|
|
165
|
+
return (await answer.json())?.private === false ? repo : null;
|
|
166
|
+
} catch { return null; }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const megabytes = (bytes) => `${(bytes / 1_000_000).toFixed(bytes < 10_000_000 ? 1 : 0)} MB`;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Shares the page, or sends it again to the link the folder has: the link's words and picture, then the page. `words`
|
|
173
|
+
* are what the link says (`name`, `words`, and `line`, `by` and `asks` when given), `picture` a PNG or JPEG of the
|
|
174
|
+
* page or null, `shape` "fill" or the page's width over its height. Answers the link and what went up.
|
|
175
|
+
*/
|
|
176
|
+
export async function share({ layout, words, picture = null, shape = "fill", site = siteOrigin(), said = () => {}, file = true, anyway = false, github, fromLamp = false }) {
|
|
177
|
+
// 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
|
|
178
|
+
// Lamp too: made first, with Share…'s checks, so a page that can't be shared (a key in it) puts nothing up.
|
|
179
|
+
const app = file ? exportApp(layout.folder, { anyway }) : null;
|
|
180
|
+
const files = pageFiles(layout);
|
|
181
|
+
const unpacked = files.reduce((total, [, bytes]) => total + bytes.length, 0);
|
|
182
|
+
if (!files.some(([path]) => path === "index.html")) throw new Problem("the page has no index.html at its top");
|
|
183
|
+
if (files.length > PAGE_LIMITS.files) throw new Problem(`the page is ${files.length} files, and a link carries ${PAGE_LIMITS.files} at most`);
|
|
184
|
+
if (unpacked > PAGE_LIMITS.total) throw new Problem(`the page is ${megabytes(unpacked)}, and a link carries ${megabytes(PAGE_LIMITS.total)} at most`);
|
|
185
|
+
const zip = zipOf(files);
|
|
186
|
+
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`);
|
|
187
|
+
if (picture && picture.length > LIMITS.picture) picture = null;
|
|
188
|
+
// The page links to the folder's public repository on GitHub, when it's one (`github` given in its place by a test).
|
|
189
|
+
const repo = github === undefined ? await publicRepoOf(layout.folder) : github;
|
|
190
|
+
|
|
191
|
+
const body = {
|
|
192
|
+
name: words.name, words: words.words, shape,
|
|
193
|
+
...(words.line ? { line: words.line } : {}), ...(words.by ? { by: words.by } : {}),
|
|
194
|
+
...(words.asks?.length ? { asks: words.asks } : {}), ...(picture ? { picture: picture.toString("base64") } : {}),
|
|
195
|
+
...(repo ? { github: repo } : {}),
|
|
196
|
+
};
|
|
197
|
+
// The folder's own link when it has one on this site, changed in place; a link that's gone is made again.
|
|
198
|
+
let earlier = readLink(layout.folder);
|
|
199
|
+
if (earlier && earlier.site !== site) earlier = null;
|
|
200
|
+
// A file an earlier share sent stays on the record until it's taken away, so a retry after a failed removal tries again.
|
|
201
|
+
// A link that's a Lamp's (`fromLamp`, the app in its own folder) stays so in every write, a share that fails partway too.
|
|
202
|
+
let link = { site, ...(await publishLink({ site, body, earlier, account: accountFor(site)?.key })), ...words, shape, ...(earlier?.file ? { file: true } : {}),
|
|
203
|
+
...(fromLamp ? { fromLamp: true } : {}) };
|
|
204
|
+
// 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.
|
|
205
|
+
writeLink(layout.folder, link);
|
|
206
|
+
|
|
207
|
+
// The file, or none: a link that carried one and shouldn't now has it taken away (and its page with it, sent next).
|
|
208
|
+
if (app) {
|
|
209
|
+
link.file = true;
|
|
210
|
+
writeLink(layout.folder, link);
|
|
211
|
+
await sendFile({ site, link, bytes: app.bytes, said });
|
|
212
|
+
} else if (link.file) {
|
|
213
|
+
await removeFile({ site, link });
|
|
214
|
+
link.file = false;
|
|
215
|
+
writeLink(layout.folder, link);
|
|
216
|
+
}
|
|
217
|
+
const version = await sendFile({ site, link, bytes: zip, page: true, said });
|
|
218
|
+
link = { ...link, version, shared: new Date().toISOString() };
|
|
219
|
+
writeLink(layout.folder, link);
|
|
220
|
+
await pageUp({ site, id: link.id, version, said });
|
|
221
|
+
return { url: link.url, version, files: files.length, bytes: zip.length, picture: !!picture, file: !!app, github: repo || null };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Takes the folder's link down, with its page and the ideas sent to it. */
|
|
225
|
+
export async function unshare(folder) {
|
|
226
|
+
const link = readLink(folder);
|
|
227
|
+
if (!link) throw new Problem("this folder has no link");
|
|
228
|
+
await removeLink({ site: link.site, link });
|
|
229
|
+
rmSync(linkFileOf(folder), { force: true });
|
|
230
|
+
return link.url;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** The ideas people playing the link have sent its maker and that are still open: each with its number. */
|
|
234
|
+
export async function ideas(folder, { earlier = false } = {}) {
|
|
235
|
+
const link = readLink(folder);
|
|
236
|
+
if (!link) throw new Problem("this folder has no link: lamp share makes one");
|
|
237
|
+
return { url: link.url, ideas: await ideasOf({ site: link.site, link, earlier }) };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Says what became of an idea: it's in (the site writes to whoever asked to hear), or it's let go. */
|
|
241
|
+
export async function finishIdea(folder, n, built, note) {
|
|
242
|
+
const link = readLink(folder);
|
|
243
|
+
if (!link) throw new Problem("this folder has no link");
|
|
244
|
+
return removeIdea({ site: link.site, link, n, built, note });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Says something more about an idea to whoever sent it; with no note, that their answer is seen to. */
|
|
248
|
+
export async function answerIdea(folder, n, note) {
|
|
249
|
+
const link = readLink(folder);
|
|
250
|
+
if (!link) throw new Problem("this folder has no link");
|
|
251
|
+
return replyIdea({ site: link.site, link, n, note });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** The maker's own address for the link's ideas, or, with `email`, given ("" takes it away). */
|
|
255
|
+
export async function makerEmail(folder, email) {
|
|
256
|
+
const link = readLink(folder);
|
|
257
|
+
if (!link) throw new Problem("this folder has no link: lamp share makes one");
|
|
258
|
+
return makerOf({ site: link.site, link, email });
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** The page's name where nothing gave one: its title, or its folder's name. */
|
|
262
|
+
export function nameOf(layout) {
|
|
263
|
+
try {
|
|
264
|
+
const title = /<title[^>]*>([^<]*)<\/title>/i.exec(readFileSync(join(layout.root, "index.html"), "utf8"))?.[1]?.trim();
|
|
265
|
+
if (title) return title.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').slice(0, LIMITS.name);
|
|
266
|
+
} catch {}
|
|
267
|
+
return basename(layout.folder).slice(0, LIMITS.name);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export { LIMITS };
|