Files
martinfencl.eu/locenice/tools/vendor_three.py
T
2026-10-22 01:22:01 +02:00

43 lines
2.0 KiB
Python

"""Optional: download pinned Three.js r180 locally, on a computer with internet.
python tools/vendor_three.py
Then upload the generated locenice/vendor folder AND data/app-config.json.
Does not upload anything. No credentials or server-side installer required.
"""
from pathlib import Path
from urllib.request import Request, urlopen
import json, re, hashlib
ROOT=Path(__file__).resolve().parent.parent
BASE='https://raw.githubusercontent.com/mrdoob/three.js/r180/'
VENDOR=ROOT/'vendor'/'three-r180'
seen=set()
def download(relative: str):
if relative in seen:return
if '..' in Path(relative).parts or relative.startswith('/'):
raise ValueError('Unsafe dependency path: '+relative)
seen.add(relative)
req=Request(BASE+relative,headers={'User-Agent':'Locenice-vendor-setup/1.0'})
with urlopen(req,timeout=30) as response:
data=response.read()
destination=VENDOR/relative
destination.parent.mkdir(parents=True,exist_ok=True)
destination.write_bytes(data)
if relative.endswith('.js'):
code=data.decode('utf-8')
for dep in re.findall(r"(?:from\s*|import\s*)['\"]([^'\"]+)['\"]",code):
if not dep.startswith('.'):continue
joined=(destination.parent/dep).resolve()
if not joined.is_relative_to(VENDOR.resolve()):raise ValueError('Out of vendor root')
download(joined.relative_to(VENDOR.resolve()).as_posix())
print(relative,hashlib.sha256(data).hexdigest())
if __name__=='__main__':
for filename in ['build/three.module.js','examples/jsm/loaders/GLTFLoader.js','LICENSE']:
download(filename)
config_path=ROOT/'data'/'app-config.json'
config=json.loads(config_path.read_text())
config['threeModule']='./vendor/three-r180/build/three.module.js'
config['threeLoader']='./vendor/three-r180/examples/jsm/loaders/GLTFLoader.js'
config_path.write_text(json.dumps(config,ensure_ascii=False,indent=2))
print('Done. Upload the vendor folder and app-config.json.')