Full Code of codesandbox/nodebox-runtime for AI

main 65a4ccf5507e cached
625 files
52.0 MB
8.1M tokens
129 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (32,463K chars total). Download the full file to get everything.
Repository: codesandbox/nodebox-runtime
Branch: main
Commit: 65a4ccf5507e
Files: 625
Total size: 52.0 MB

Directory structure:
gitextract_k7rtrazz/

├── .codesandbox/
│   └── tasks.json
├── .editorconfig
├── .env.example
├── .env.test
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .release-please-manifest.json
├── ATTRIBUTIONS.md
├── LICENSE
├── README.md
├── dnsmasq.conf
├── internals/
│   ├── esbuild-plugins/
│   │   ├── inline-file.ts
│   │   └── inline-worker.ts
│   └── servers/
│       ├── consumer/
│       │   ├── build.ts
│       │   ├── dist/
│       │   │   └── index.html
│       │   └── serve.ts
│       ├── main-server.ts
│       ├── preview-server.ts
│       ├── test/
│       │   ├── index.html
│       │   └── test-server.ts
│       └── utils.ts
├── package.json
├── packages/
│   ├── nodebox/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── api.md
│   │   ├── build.ts
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── Nodebox.ts
│   │   │   ├── index.ts
│   │   │   ├── logger.ts
│   │   │   ├── messages.ts
│   │   │   ├── modules/
│   │   │   │   ├── fs.ts
│   │   │   │   ├── preview.ts
│   │   │   │   └── shell.ts
│   │   │   └── runtime-protocol.types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   └── utils/
│       ├── jest.config.js
│       ├── package.json
│       ├── withTimeout.test.ts
│       └── withTimeout.ts
├── playwright.config.ts
├── pnpm-workspace.yaml
├── public/
│   └── ws-test.pack
├── release-please-config.json
├── req.conf
├── sync-repo.js
├── tests/
│   ├── cdn-proxy/
│   │   └── v2/
│   │       ├── deps/
│   │       │   ├── QGFwb2xsby9zZXJ2ZXJANC4xLjE7Z3JhcGhxbEAxNi42LjA=
│   │       │   ├── QHN2ZWx0ZWpzL3ZpdGUtcGx1Z2luLXN2ZWx0ZUAyLjAuMztlc2J1aWxkLXdhc21AMC4xNy4xMjtzdmVsdGVAMy41Ny4wO3ZpdGVANC4yLjA=
│   │       │   ├── QHZpdGVqcy9wbHVnaW4tcmVhY3RAMy4xLjA7ZXNidWlsZC13YXNtQDAuMTcuMTI7cmVhY3QtZG9tQF4xOC4yLjA7cmVhY3RAXjE4LjIuMDt2aXRlQDQuMi4w
│   │       │   ├── QHZpdGVqcy9wbHVnaW4tdnVlQDQuMS4wO2VzYnVpbGQtd2FzbUAwLjE3LjEyO3ZpdGVANC4yLjA7dnVlQGxhdGVzdA==
│   │       │   ├── ZXNidWlsZC13YXNtQDAuMTUuMTI7dnVlcHJlc3NAMi4wLjAtYmV0YS41Mw==
│   │       │   ├── ZXNidWlsZC13YXNtQDAuMTcuMTI7dml0ZUA0LjIuMA==
│   │       │   ├── ZXNsaW50QF44LjAuMQ==
│   │       │   ├── ZXhwcmVzc0A0LjE4LjI=
│   │       │   ├── ZmFzdGlmeUBsYXRlc3Q=
│   │       │   └── bm9kZS1mZXRjaEAzLjMuMA==
│   │       └── mod/
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi10aXRsZUAwLjExLjI=
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi10b2NAMC4xMS4y
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1jb21wb25lbnRAMC4xMS4y
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1mcm9udG1hdHRlckAwLjExLjE=
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1oZWFkZXJzQDAuMTEuMg==
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1zZmNAMC4xMS4x
│   │           ├── QG1kaXQtdnVlL3NoYXJlZEAwLjExLjI=
│   │           ├── QG1kaXQtdnVlL3R5cGVzQDAuMTEuMA==
│   │           ├── QG5vZGVsaWIvZnMuc2NhbmRpckAyLjEuNQ==
│   │           ├── QG5vZGVsaWIvZnMuc3RhdEAyLjAuNQ==
│   │           ├── QG5vZGVsaWIvZnMud2Fsa0AxLjIuOA==
│   │           ├── QGFtcHByb2plY3QvcmVtYXBwaW5nQDIuMi4w
│   │           ├── QGFwb2xsby91c2FnZS1yZXBvcnRpbmctcHJvdG9idWZANC4xLjA=
│   │           ├── QGFwb2xsby91dGlscy51c2FnZXJlcG9ydGluZ0AxLjAuMQ==
│   │           ├── QGFwb2xsby91dGlscy53aXRocmVxdWlyZWRAMS4wLjE=
│   │           ├── QGFwb2xsby91dGlscy5jcmVhdGVoYXNoQDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5kcm9wdW51c2VkZGVmaW5pdGlvbnNAMS4xLjA=
│   │           ├── QGFwb2xsby91dGlscy5mZXRjaGVyQDEuMS4x
│   │           ├── QGFwb2xsby91dGlscy5mZXRjaGVyQDIuMC4w
│   │           ├── QGFwb2xsby91dGlscy5pc25vZGVsaWtlQDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5rZXl2YWx1ZWNhY2hlQDEuMC4y
│   │           ├── QGFwb2xsby91dGlscy5rZXl2YWx1ZWNhY2hlQDIuMS4w
│   │           ├── QGFwb2xsby91dGlscy5sb2dnZXJAMS4wLjE=
│   │           ├── QGFwb2xsby91dGlscy5sb2dnZXJAMi4wLjA=
│   │           ├── QGFwb2xsby91dGlscy5wcmludHdpdGhyZWR1Y2Vkd2hpdGVzcGFjZUAxLjEuMA==
│   │           ├── QGFwb2xsby91dGlscy5yZW1vdmVhbGlhc2VzQDEuMC4w
│   │           ├── QGFwb2xsby91dGlscy5zb3J0YXN0QDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5zdHJpcHNlbnNpdGl2ZWxpdGVyYWxzQDEuMi4w
│   │           ├── QGFwb2xsby9jYWNoZS1jb250cm9sLXR5cGVzQDEuMC4y
│   │           ├── QGFwb2xsby9wcm90b2J1ZmpzQDEuMi43
│   │           ├── QGFwb2xsby9zZXJ2ZXItZ2F0ZXdheS1pbnRlcmZhY2VAMS4xLjA=
│   │           ├── QGFwb2xsby9zZXJ2ZXJANC4xLjE=
│   │           ├── QGJhYmVsL2NvZGUtZnJhbWVANy4xOC42
│   │           ├── QGJhYmVsL2NvbXBhdC1kYXRhQDcuMjEuMA==
│   │           ├── QGJhYmVsL2NvcmVANy4yMS4z
│   │           ├── QGJhYmVsL2dlbmVyYXRvckA3LjIxLjM=
│   │           ├── QGJhYmVsL2hlbHBlci12YWxpZGF0b3ItaWRlbnRpZmllckA3LjE5LjE=
│   │           ├── QGJhYmVsL2hlbHBlci12YWxpZGF0b3Itb3B0aW9uQDcuMjEuMA==
│   │           ├── QGJhYmVsL2hlbHBlci1jb21waWxhdGlvbi10YXJnZXRzQDcuMjAuNw==
│   │           ├── QGJhYmVsL2hlbHBlci1lbnZpcm9ubWVudC12aXNpdG9yQDcuMTguOQ==
│   │           ├── QGJhYmVsL2hlbHBlci1mdW5jdGlvbi1uYW1lQDcuMjEuMA==
│   │           ├── QGJhYmVsL2hlbHBlci1ob2lzdC12YXJpYWJsZXNANy4xOC42
│   │           ├── QGJhYmVsL2hlbHBlci1tb2R1bGUtaW1wb3J0c0A3LjE4LjY=
│   │           ├── QGJhYmVsL2hlbHBlci1tb2R1bGUtdHJhbnNmb3Jtc0A3LjIxLjI=
│   │           ├── QGJhYmVsL2hlbHBlci1wbHVnaW4tdXRpbHNANy4yMC4y
│   │           ├── QGJhYmVsL2hlbHBlci1zaW1wbGUtYWNjZXNzQDcuMjAuMg==
│   │           ├── QGJhYmVsL2hlbHBlci1zcGxpdC1leHBvcnQtZGVjbGFyYXRpb25ANy4xOC42
│   │           ├── QGJhYmVsL2hlbHBlci1zdHJpbmctcGFyc2VyQDcuMTkuNA==
│   │           ├── QGJhYmVsL2hlbHBlcnNANy4yMS4w
│   │           ├── QGJhYmVsL2hpZ2hsaWdodEA3LjE4LjY=
│   │           ├── QGJhYmVsL3BhcnNlckA3LjIxLjM=
│   │           ├── QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNlbGZANy4yMS4w
│   │           ├── QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNvdXJjZUA3LjE5LjY=
│   │           ├── QGJhYmVsL3R5cGVzQDcuMjEuMw==
│   │           ├── QGJhYmVsL3RlbXBsYXRlQDcuMjAuNw==
│   │           ├── QGJhYmVsL3RyYXZlcnNlQDcuMjEuMw==
│   │           ├── QGVzbGludC9lc2xpbnRyY0AxLjQuMQ==
│   │           ├── QGZhc3RpZnkvYWp2LWNvbXBpbGVyQDMuNS4w
│   │           ├── QGZhc3RpZnkvZGVlcG1lcmdlQDEuMy4w
│   │           ├── QGZhc3RpZnkvZXJyb3JAMy4yLjA=
│   │           ├── QGZhc3RpZnkvZmFzdC1qc29uLXN0cmluZ2lmeS1jb21waWxlckA0LjIuMA==
│   │           ├── QGdyYXBocWwtdG9vbHMvbWVyZ2VAOC4zLjEx
│   │           ├── QGdyYXBocWwtdG9vbHMvc2NoZW1hQDkuMC45
│   │           ├── QGdyYXBocWwtdG9vbHMvdXRpbHNAOS4xLjA=
│   │           ├── QGh1bWFud2hvY29kZXMvY29uZmlnLWFycmF5QDAuOS41
│   │           ├── QGh1bWFud2hvY29kZXMvb2JqZWN0LXNjaGVtYUAxLjIuMQ==
│   │           ├── QGpvc2VwaGcvcmVzb2x2YWJsZUAxLjAuMQ==
│   │           ├── QGpyaWRnZXdlbGwvZ2VuLW1hcHBpbmdAMC4zLjI=
│   │           ├── QGpyaWRnZXdlbGwvc291cmNlbWFwLWNvZGVjQDEuNC4xNA==
│   │           ├── QGpyaWRnZXdlbGwvc2V0LWFycmF5QDEuMS4y
│   │           ├── QGpyaWRnZXdlbGwvcmVzb2x2ZS11cmlAMy4xLjA=
│   │           ├── QGpyaWRnZXdlbGwvdHJhY2UtbWFwcGluZ0AwLjMuMTc=
│   │           ├── QHByb3RvYnVmanMvY29kZWdlbkAyLjAuNA==
│   │           ├── QHByb3RvYnVmanMvYXNwcm9taXNlQDEuMS4y
│   │           ├── QHByb3RvYnVmanMvYmFzZTY0QDEuMS4y
│   │           ├── QHByb3RvYnVmanMvZXZlbnRlbWl0dGVyQDEuMS4w
│   │           ├── QHByb3RvYnVmanMvZmV0Y2hAMS4xLjA=
│   │           ├── QHByb3RvYnVmanMvZmxvYXRAMS4wLjI=
│   │           ├── QHByb3RvYnVmanMvaW5xdWlyZUAxLjEuMA==
│   │           ├── QHByb3RvYnVmanMvcG9vbEAxLjEuMA==
│   │           ├── QHByb3RvYnVmanMvcGF0aEAxLjEuMg==
│   │           ├── QHByb3RvYnVmanMvdXRmOEAxLjEuMA==
│   │           ├── QHN2ZWx0ZWpzL3ZpdGUtcGx1Z2luLXN2ZWx0ZUAyLjAuMw==
│   │           ├── QHR5cGVzL21hcmtkb3duLWl0LWVtb2ppQDIuMC4y
│   │           ├── QHR5cGVzL21hcmtkb3duLWl0QDEyLjIuMw==
│   │           ├── QHR5cGVzL21kdXJsQDEuMC4y
│   │           ├── QHR5cGVzL21pbWVAMy4wLjE=
│   │           ├── QHR5cGVzL21zQDAuNy4zMQ==
│   │           ├── QHR5cGVzL25vZGUtZmV0Y2hAMi42LjI=
│   │           ├── QHR5cGVzL25vZGVAOS42Ljk=
│   │           ├── QHR5cGVzL2JvZHktcGFyc2VyQDEuMTkuMg==
│   │           ├── QHR5cGVzL2Nvbm5lY3RAMy40LjM1
│   │           ├── QHR5cGVzL2RlYnVnQDQuMS43
│   │           ├── QHR5cGVzL2V4cHJlc3Mtc2VydmUtc3RhdGljLWNvcmVANC4xNy4zMw==
│   │           ├── QHR5cGVzL2V4cHJlc3NANC4xNy4xNw==
│   │           ├── QHR5cGVzL2ZzLWV4dHJhQDkuMC4xMw==
│   │           ├── QHR5cGVzL2hhc2gtc3VtQDEuMC4w
│   │           ├── QHR5cGVzL2xpbmtpZnktaXRAMy4wLjI=
│   │           ├── QHR5cGVzL2xvbmdANC4wLjI=
│   │           ├── QHR5cGVzL3FzQDYuOS43
│   │           ├── QHR5cGVzL3JhbmdlLXBhcnNlckAxLjIuNA==
│   │           ├── QHR5cGVzL3NlcnZlLXN0YXRpY0AxLjcuMzI=
│   │           ├── QHR5cGVzL3dlYi1ibHVldG9vdGhAMC4wLjE2
│   │           ├── QHZ1ZS9jb21waWxlci1jb3JlQDMuMi40Nw==
│   │           ├── QHZ1ZS9jb21waWxlci1kb21AMy4yLjQ3
│   │           ├── QHZ1ZS9jb21waWxlci1zZmNAMy4yLjQ3
│   │           ├── QHZ1ZS9jb21waWxlci1zc3JAMy4yLjQ3
│   │           ├── QHZ1ZS9kZXZ0b29scy1hcGlANi41LjA=
│   │           ├── QHZ1ZS9yZWFjdGl2aXR5LXRyYW5zZm9ybUAzLjIuNDc=
│   │           ├── QHZ1ZS9yZWFjdGl2aXR5QDMuMi40Nw==
│   │           ├── QHZ1ZS9ydW50aW1lLWNvcmVAMy4yLjQ3
│   │           ├── QHZ1ZS9ydW50aW1lLWRvbUAzLjIuNDc=
│   │           ├── QHZ1ZS9zZXJ2ZXItcmVuZGVyZXJAMy4yLjQ3
│   │           ├── QHZ1ZS9zaGFyZWRAMy4yLjQ3
│   │           ├── QHZ1ZXByZXNzL21hcmtkb3duQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL2J1bmRsZXItdml0ZUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NsaUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NsaWVudEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NvcmVAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi10aGVtZS1kYXRhQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1hY3RpdmUtaGVhZGVyLWxpbmtzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1iYWNrLXRvLXRvcEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1jb250YWluZXJAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1leHRlcm5hbC1saW5rLWljb25AMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1naXRAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1tZWRpdW0tem9vbUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1ucHJvZ3Jlc3NAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1wYWxldHRlQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1wcmlzbWpzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3NoYXJlZEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3RoZW1lLWRlZmF1bHRAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3V0aWxzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXVzZS9jb3JlQDkuOS4w
│   │           ├── QHZ1ZXVzZS9tZXRhZGF0YUA5LjkuMA==
│   │           ├── QHZ1ZXVzZS9zaGFyZWRAOS45LjA=
│   │           ├── QHZpdGVqcy9wbHVnaW4tcmVhY3RAMy4xLjA=
│   │           ├── QHZpdGVqcy9wbHVnaW4tdnVlQDMuMi4w
│   │           ├── QHZpdGVqcy9wbHVnaW4tdnVlQDQuMS4w
│   │           ├── Y29sb3ItY29udmVydEAxLjkuMw==
│   │           ├── Y29sb3ItY29udmVydEAyLjAuMQ==
│   │           ├── Y29sb3ItbmFtZUAxLjEuMw==
│   │           ├── Y29sb3ItbmFtZUAxLjEuNA==
│   │           ├── Y29tYmluZWQtc3RyZWFtQDEuMC44
│   │           ├── Y29uY2F0LW1hcEAwLjAuMQ==
│   │           ├── Y29ubmVjdC1oaXN0b3J5LWFwaS1mYWxsYmFja0AyLjAuMA==
│   │           ├── Y29udGVudC10eXBlQDEuMC41
│   │           ├── Y29udGVudC1kaXNwb3NpdGlvbkAwLjUuNA==
│   │           ├── Y29udmVydC1zb3VyY2UtbWFwQDEuOS4w
│   │           ├── Y29va2llLXNpZ25hdHVyZUAxLjAuNg==
│   │           ├── Y29va2llQDAuNS4w
│   │           ├── Y29yc0AyLjguNQ==
│   │           ├── Y2FjQDYuNy4xNA==
│   │           ├── Y2FsbC1iaW5kQDEuMC4y
│   │           ├── Y2FsbHNpdGVzQDMuMS4w
│   │           ├── Y2FuaXVzZS1saXRlQDEuMC4zMDAwMTQ2OA==
│   │           ├── Y2hhbGtAMi40LjI=
│   │           ├── Y2hhbGtANC4xLjI=
│   │           ├── Y2hhbGtANS4yLjA=
│   │           ├── Y2hva2lkYXJAMy41LjM=
│   │           ├── Y2xpLWN1cnNvckA0LjAuMA==
│   │           ├── Y2xpLXNwaW5uZXJzQDIuNy4w
│   │           ├── Y2xvbmVAMS4wLjQ=
│   │           ├── Y3Jvc3Mtc3Bhd25ANy4wLjM=
│   │           ├── Y3NzdHlwZUAyLjYuOQ==
│   │           ├── YW55bWF0Y2hAMy4xLjM=
│   │           ├── YW5zaS1yZWdleEA1LjAuMQ==
│   │           ├── YW5zaS1yZWdleEA2LjAuMQ==
│   │           ├── YW5zaS1zdHlsZXNAMy4yLjE=
│   │           ├── YW5zaS1zdHlsZXNANC4zLjA=
│   │           ├── YWJvcnQtY29udHJvbGxlckAzLjAuMA==
│   │           ├── YWJzdHJhY3QtbG9nZ2luZ0AyLjAuMQ==
│   │           ├── YWNjZXB0c0AxLjMuOA==
│   │           ├── YWNvcm4tanN4QDUuMy4y
│   │           ├── YWNvcm5AOC44LjI=
│   │           ├── YWp2LWZvcm1hdHNAMi4xLjE=
│   │           ├── YWp2QDYuMTIuNg==
│   │           ├── YWp2QDguMTIuMA==
│   │           ├── YXJjaHlAMS4wLjA=
│   │           ├── YXJncGFyc2VAMS4wLjk=
│   │           ├── YXJncGFyc2VAMi4wLjE=
│   │           ├── YXJyYXktZmxhdHRlbkAxLjEuMQ==
│   │           ├── YXN5bmMtcmV0cnlAMS4zLjM=
│   │           ├── YXN5bmNraXRAMC40LjA=
│   │           ├── YXRvbWljLXNsZWVwQDEuMC4w
│   │           ├── YXV0b3ByZWZpeGVyQDEwLjQuMTQ=
│   │           ├── YXZ2aW9AOC4yLjE=
│   │           ├── Ym9keS1wYXJzZXJAMS4yMC4x
│   │           ├── Ym9keS1wYXJzZXJAMS4yMC4y
│   │           ├── YmFsYW5jZWQtbWF0Y2hAMS4wLjI=
│   │           ├── YmFzZTY0LWpzQDEuNS4x
│   │           ├── YmluYXJ5LWV4dGVuc2lvbnNAMi4yLjA=
│   │           ├── YmxANS4xLjA=
│   │           ├── YnJhY2UtZXhwYW5zaW9uQDEuMS45
│   │           ├── YnJhY2VzQDMuMC4y
│   │           ├── YnJvd3NlcnNsaXN0QDQuMjEuNQ==
│   │           ├── YnVmZmVyQDYuMC4z
│   │           ├── Ynl0ZXNAMy4xLjI=
│   │           ├── Z2V0LWludHJpbnNpY0AxLjIuMA==
│   │           ├── Z2V0LXN0cmVhbUA2LjAuMQ==
│   │           ├── Z2Vuc3luY0AxLjAuMC1iZXRhLjI=
│   │           ├── Z2xvYi1wYXJlbnRANS4xLjI=
│   │           ├── Z2xvYi1wYXJlbnRANi4wLjI=
│   │           ├── Z2xvYkA3LjIuMw==
│   │           ├── Z2xvYmFsc0AxMS45LjA=
│   │           ├── Z2xvYmFsc0AxMy4yMC4w
│   │           ├── Z2xvYmJ5QDEzLjEuMw==
│   │           ├── Z3JhY2VmdWwtZnNANC4yLjk=
│   │           ├── Z3JhcGhxbEAxNi42LjA=
│   │           ├── Z3JheS1tYXR0ZXJANC4wLjM=
│   │           ├── ZG9jdHJpbmVAMy4wLjA=
│   │           ├── ZGF0YS11cmktdG8tYnVmZmVyQDQuMC4x
│   │           ├── ZGVidWdAMi42Ljk=
│   │           ├── ZGVidWdANC4zLjQ=
│   │           ├── ZGVlcC1pc0AwLjEuNA==
│   │           ├── ZGVlcG1lcmdlQDQuMy4x
│   │           ├── ZGVmYXVsdHNAMS4wLjQ=
│   │           ├── ZGVsYXllZC1zdHJlYW1AMS4wLjA=
│   │           ├── ZGVwZEAyLjAuMA==
│   │           ├── ZGVzdHJveUAxLjIuMA==
│   │           ├── ZGlyLWdsb2JAMy4wLjE=
│   │           ├── ZW50aXRpZXNAMy4wLjE=
│   │           ├── ZW52aW5mb0A3LjguMQ==
│   │           ├── ZW5jb2RldXJsQDEuMC4y
│   │           ├── ZWUtZmlyc3RAMS4xLjE=
│   │           ├── ZWxlY3Ryb24tdG8tY2hyb21pdW1AMS40LjMzMw==
│   │           ├── ZXN0cmF2ZXJzZUA1LjMuMA==
│   │           ├── ZXN0cmVlLXdhbGtlckAyLjAuMg==
│   │           ├── ZXN1dGlsc0AyLjAuMw==
│   │           ├── ZXNidWlsZC13YXNtQDAuMTUuMTI=
│   │           ├── ZXNidWlsZC13YXNtQDAuMTcuMTI=
│   │           ├── ZXNidWlsZEAwLjE1LjE4
│   │           ├── ZXNidWlsZEAwLjE3Ljk=
│   │           ├── ZXNjYWxhZGVAMy4xLjE=
│   │           ├── ZXNjYXBlLWh0bWxAMS4wLjM=
│   │           ├── ZXNjYXBlLXN0cmluZy1yZWdleHBAMS4wLjU=
│   │           ├── ZXNjYXBlLXN0cmluZy1yZWdleHBANC4wLjA=
│   │           ├── ZXNsaW50LXNjb3BlQDcuMS4x
│   │           ├── ZXNsaW50LXV0aWxzQDMuMC4w
│   │           ├── ZXNsaW50LXZpc2l0b3Ita2V5c0AyLjEuMA==
│   │           ├── ZXNsaW50LXZpc2l0b3Ita2V5c0AzLjMuMA==
│   │           ├── ZXNsaW50QDguOS4w
│   │           ├── ZXNwcmVlQDkuNS4w
│   │           ├── ZXNwcmltYUA0LjAuMQ==
│   │           ├── ZXNxdWVyeUAxLjUuMA==
│   │           ├── ZXNyZWN1cnNlQDQuMy4w
│   │           ├── ZXRhZ0AxLjguMQ==
│   │           ├── ZXZlbnQtdGFyZ2V0LXNoaW1ANS4wLjE=
│   │           ├── ZXZlbnRzQDMuMy4w
│   │           ├── ZXh0ZW5kLXNoYWxsb3dAMi4wLjE=
│   │           ├── ZXhlY2FANi4xLjA=
│   │           ├── ZXhwcmVzc0A0LjE4LjI=
│   │           ├── Zm9ybS1kYXRhQDMuMC4x
│   │           ├── Zm9ybWRhdGEtcG9seWZpbGxANC4wLjEw
│   │           ├── Zm9yd2FyZGVkQDAuMi4w
│   │           ├── ZmFzdC11cmlAMi4yLjA=
│   │           ├── ZmFzdC1jb250ZW50LXR5cGUtcGFyc2VAMS4wLjA=
│   │           ├── ZmFzdC1kZWNvZGUtdXJpLWNvbXBvbmVudEAxLjAuMQ==
│   │           ├── ZmFzdC1kZWVwLWVxdWFsQDMuMS4z
│   │           ├── ZmFzdC1nbG9iQDMuMi4xMg==
│   │           ├── ZmFzdC1qc29uLXN0YWJsZS1zdHJpbmdpZnlAMi4xLjA=
│   │           ├── ZmFzdC1qc29uLXN0cmluZ2lmeUA1LjYuMg==
│   │           ├── ZmFzdC1sZXZlbnNodGVpbkAyLjAuNg==
│   │           ├── ZmFzdC1xdWVyeXN0cmluZ0AxLjEuMQ==
│   │           ├── ZmFzdC1yZWRhY3RAMy4xLjI=
│   │           ├── ZmFzdGlmeUA0LjE0LjE=
│   │           ├── ZmFzdHFAMS45LjA=
│   │           ├── ZmV0Y2gtYmxvYkAzLjIuMA==
│   │           ├── ZmlsZS1lbnRyeS1jYWNoZUA2LjAuMQ==
│   │           ├── ZmlsbC1yYW5nZUA3LjAuMQ==
│   │           ├── ZmluYWxoYW5kbGVyQDEuMi4w
│   │           ├── ZmluZC1teS13YXlANy42LjA=
│   │           ├── ZmxhdC1jYWNoZUAzLjAuNA==
│   │           ├── ZmxhdHRlZEAzLjIuNw==
│   │           ├── ZnJhY3Rpb24uanNANC4yLjA=
│   │           ├── ZnJlc2hAMC41LjI=
│   │           ├── ZnMtZXh0cmFAMTAuMS4w
│   │           ├── ZnMucmVhbHBhdGhAMS4wLjA=
│   │           ├── ZnVuY3Rpb24tYmluZEAxLjEuMQ==
│   │           ├── ZnVuY3Rpb25hbC1yZWQtYmxhY2stdHJlZUAxLjAuMQ==
│   │           ├── a2luZC1vZkA2LjAuMw==
│   │           ├── a2xldXJANC4xLjU=
│   │           ├── aGFzLWZsYWdAMy4wLjA=
│   │           ├── aGFzLWZsYWdANC4wLjA=
│   │           ├── aGFzLXN5bWJvbHNAMS4wLjM=
│   │           ├── aGFzQDEuMC4z
│   │           ├── aGFzaC1zdW1AMi4wLjA=
│   │           ├── aHR0cC1lcnJvcnNAMi4wLjA=
│   │           ├── aHVtYW4tc2lnbmFsc0AzLjAuMQ==
│   │           ├── aW11cm11cmhhc2hAMC4xLjQ=
│   │           ├── aW1tdXRhYmxlQDQuMy4w
│   │           ├── aW1wb3J0LWZyZXNoQDMuMy4w
│   │           ├── aW5mbGlnaHRAMS4wLjY=
│   │           ├── aW5oZXJpdHNAMi4wLjQ=
│   │           ├── aWNvbnYtbGl0ZUAwLjQuMjQ=
│   │           ├── aWVlZTc1NEAxLjIuMQ==
│   │           ├── aWdub3JlQDUuMi40
│   │           ├── aXBhZGRyLmpzQDEuOS4x
│   │           ├── aXMtY29yZS1tb2R1bGVAMi45LjA=
│   │           ├── aXMtYmluYXJ5LXBhdGhAMi4xLjA=
│   │           ├── aXMtZ2xvYkA0LjAuMw==
│   │           ├── aXMtZXh0Z2xvYkAyLjEuMQ==
│   │           ├── aXMtZXh0ZW5kYWJsZUAwLjEuMQ==
│   │           ├── aXMtaW50ZXJhY3RpdmVAMi4wLjA=
│   │           ├── aXMtbnVtYmVyQDcuMC4w
│   │           ├── aXMtc3RyZWFtQDMuMC4w
│   │           ├── aXMtdW5pY29kZS1zdXBwb3J0ZWRAMS4zLjA=
│   │           ├── aXNleGVAMi4wLjA=
│   │           ├── anMtdG9rZW5zQDQuMC4w
│   │           ├── anMteWFtbEA0LjEuMA==
│   │           ├── anMteWFtbEAzLjE0LjE=
│   │           ├── anNlc2NAMi41LjI=
│   │           ├── anNvbi1zY2hlbWEtdHJhdmVyc2VAMC40LjE=
│   │           ├── anNvbi1zY2hlbWEtdHJhdmVyc2VAMS4wLjA=
│   │           ├── anNvbi1zdGFibGUtc3RyaW5naWZ5LXdpdGhvdXQtanNvbmlmeUAxLjAuMQ==
│   │           ├── anNvbjVAMi4yLjM=
│   │           ├── anNvbmZpbGVANi4xLjA=
│   │           ├── b24tZXhpdC1sZWFrLWZyZWVAMi4xLjA=
│   │           ├── b24tZmluaXNoZWRAMi40LjE=
│   │           ├── b25jZUAxLjQuMA==
│   │           ├── b25ldGltZUA1LjEuMg==
│   │           ├── b25ldGltZUA2LjAuMA==
│   │           ├── b2JqZWN0LWFzc2lnbkA0LjEuMQ==
│   │           ├── b2JqZWN0LWluc3BlY3RAMS45LjA=
│   │           ├── b3B0aW9uYXRvckAwLjkuMQ==
│   │           ├── b3JhQDYuMi4w
│   │           ├── bG9kYXNoLm1lcmdlQDQuNi4y
│   │           ├── bG9kYXNoLnNvcnRieUA0LjcuMA==
│   │           ├── bG9nLXN5bWJvbHNANS4xLjA=
│   │           ├── bG9nbGV2ZWxAMS44LjE=
│   │           ├── bG9uZ0A0LjAuMA==
│   │           ├── bG9vc2UtZW52aWZ5QDEuNC4w
│   │           ├── bGV2bkAwLjQuMQ==
│   │           ├── bGlnaHQtbXktcmVxdWVzdEA1LjkuMQ==
│   │           ├── bGlsY29uZmlnQDIuMS4w
│   │           ├── bGlua2lmeS1pdEA0LjAuMQ==
│   │           ├── bHJ1LWNhY2hlQDUuMS4x
│   │           ├── bHJ1LWNhY2hlQDYuMC4w
│   │           ├── bHJ1LWNhY2hlQDcuMTguMw==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjUuOQ==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjcuMA==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjkuMA==
│   │           ├── bWFya2Rvd24taXQtY29udGFpbmVyQDMuMC4w
│   │           ├── bWFya2Rvd24taXQtYW5jaG9yQDguNi43
│   │           ├── bWFya2Rvd24taXQtZW1vamlAMi4wLjI=
│   │           ├── bWFya2Rvd24taXRAMTMuMC4x
│   │           ├── bWR1cmxAMS4wLjE=
│   │           ├── bWV0aG9kc0AxLjEuMg==
│   │           ├── bWVkaWEtdHlwZXJAMC4zLjA=
│   │           ├── bWVkaXVtLXpvb21AMS4wLjg=
│   │           ├── bWVyZ2UtZGVzY3JpcHRvcnNAMS4wLjE=
│   │           ├── bWVyZ2Utc3RyZWFtQDIuMC4w
│   │           ├── bWVyZ2UyQDEuNC4x
│   │           ├── bWljcm9tYXRjaEA0LjAuNQ==
│   │           ├── bWltZS10eXBlc0AyLjEuMzU=
│   │           ├── bWltZS1kYkAxLjUyLjA=
│   │           ├── bWltZUAxLjYuMA==
│   │           ├── bWltaWMtZm5AMi4xLjA=
│   │           ├── bWltaWMtZm5ANC4wLjA=
│   │           ├── bWluaW1hdGNoQDMuMS4y
│   │           ├── bXNAMi4xLjI=
│   │           ├── bXNAMi4xLjM=
│   │           ├── bm9kZS1hYm9ydC1jb250cm9sbGVyQDMuMS4x
│   │           ├── bm9kZS1kb21leGNlcHRpb25AMS4wLjA=
│   │           ├── bm9kZS1mZXRjaEAyLjYuOQ==
│   │           ├── bm9kZS1mZXRjaEAzLjMuMA==
│   │           ├── bm9kZS1yZWxlYXNlc0AyLjAuOQ==
│   │           ├── bm9ybWFsaXplLXBhdGhAMy4wLjA=
│   │           ├── bm9ybWFsaXplLXJhbmdlQDAuMS4y
│   │           ├── bmF0dXJhbC1jb21wYXJlQDEuNC4w
│   │           ├── bmFub2lkQDMuMy40
│   │           ├── bmVnb3RpYXRvckAwLjYuMw==
│   │           ├── bnBtLXJ1bi1wYXRoQDUuMS4w
│   │           ├── c291cmNlLW1hcC1qc0AxLjAuMg==
│   │           ├── c291cmNlLW1hcEAwLjYuMQ==
│   │           ├── c291cmNlbWFwLWNvZGVjQDEuNC44
│   │           ├── c29uaWMtYm9vbUAzLjIuMQ==
│   │           ├── c2FmZS1idWZmZXJANS4yLjE=
│   │           ├── c2FmZS1yZWdleDJAMi4wLjA=
│   │           ├── c2FmZS1zdGFibGUtc3RyaW5naWZ5QDIuNC4z
│   │           ├── c2FmZXItYnVmZmVyQDIuMS4y
│   │           ├── c2Fzc0AxLjU5LjM=
│   │           ├── c2NoZWR1bGVyQDAuMjMuMA==
│   │           ├── c2V0LWNvb2tpZS1wYXJzZXJAMi42LjA=
│   │           ├── c2V0cHJvdG90eXBlb2ZAMS4yLjA=
│   │           ├── c2VjdGlvbi1tYXR0ZXJAMS4wLjA=
│   │           ├── c2VjdXJlLWpzb24tcGFyc2VAMi43LjA=
│   │           ├── c2VtdmVyQDYuMy4w
│   │           ├── c2VtdmVyQDcuMy44
│   │           ├── c2VuZEAwLjE4LjA=
│   │           ├── c2VydmUtc3RhdGljQDEuMTUuMA==
│   │           ├── c2hhLmpzQDIuNC4xMQ==
│   │           ├── c2hlYmFuZy1jb21tYW5kQDIuMC4w
│   │           ├── c2hlYmFuZy1yZWdleEAzLjAuMA==
│   │           ├── c2lkZS1jaGFubmVsQDEuMC40
│   │           ├── c2lnbmFsLWV4aXRAMy4wLjc=
│   │           ├── c2xhc2hANC4wLjA=
│   │           ├── c3BsaXQyQDQuMS4w
│   │           ├── c3ByaW50Zi1qc0AxLjAuMw==
│   │           ├── c3RhdHVzZXNAMi4wLjE=
│   │           ├── c3RkaW4tZGlzY2FyZGVyQDAuMS4w
│   │           ├── c3RyaW5nX2RlY29kZXJAMS4zLjA=
│   │           ├── c3RyaXAtYW5zaUA2LjAuMQ==
│   │           ├── c3RyaXAtYW5zaUA3LjAuMQ==
│   │           ├── c3RyaXAtYm9tLXN0cmluZ0AxLjAuMA==
│   │           ├── c3RyaXAtZmluYWwtbmV3bGluZUAzLjAuMA==
│   │           ├── c3RyaXAtanNvbi1jb21tZW50c0AzLjEuMQ==
│   │           ├── c3VwcG9ydHMtY29sb3JANS41LjA=
│   │           ├── c3VwcG9ydHMtY29sb3JANy4yLjA=
│   │           ├── c3VwcG9ydHMtcHJlc2VydmUtc3ltbGlua3MtZmxhZ0AxLjAuMA==
│   │           ├── c3ZlbHRlLWhtckAwLjE1LjE=
│   │           ├── c3ZlbHRlQDMuNTcuMA==
│   │           ├── cG9zdGNzc0A4LjQuMjE=
│   │           ├── cG9zdGNzcy12YWx1ZS1wYXJzZXJANC4yLjA=
│   │           ├── cG9zdGNzcy1sb2FkLWNvbmZpZ0A0LjAuMQ==
│   │           ├── cGF0aC10by1yZWdleHBAMC4xLjc=
│   │           ├── cGF0aC10eXBlQDQuMC4w
│   │           ├── cGF0aC1pcy1hYnNvbHV0ZUAxLjAuMQ==
│   │           ├── cGF0aC1rZXlAMy4xLjE=
│   │           ├── cGF0aC1rZXlANC4wLjA=
│   │           ├── cGF0aC1wYXJzZUAxLjAuNw==
│   │           ├── cGFyZW50LW1vZHVsZUAxLjAuMQ==
│   │           ├── cGFyc2V1cmxAMS4zLjM=
│   │           ├── cGljb21hdGNoQDIuMy4x
│   │           ├── cGljb2NvbG9yc0AxLjAuMA==
│   │           ├── cGlub0A4LjkuMA==
│   │           ├── cGluby1hYnN0cmFjdC10cmFuc3BvcnRAMS4wLjA=
│   │           ├── cGluby1zdGQtc2VyaWFsaXplcnNANi4xLjA=
│   │           ├── cHJlbHVkZS1sc0AxLjIuMQ==
│   │           ├── cHJpc21qc0AxLjI5LjA=
│   │           ├── cHJvY2Vzc0AwLjExLjEw
│   │           ├── cHJvY2Vzcy13YXJuaW5nQDIuMS4w
│   │           ├── cHJveHktYWRkckAyLjAuNw==
│   │           ├── cHVueWNvZGVAMi4zLjA=
│   │           ├── cXNANi4xMS4w
│   │           ├── cXVldWUtbWljcm90YXNrQDEuMi4z
│   │           ├── cXVpY2stZm9ybWF0LXVuZXNjYXBlZEA0LjAuNA==
│   │           ├── cm9sbHVwQDIuNzkuMQ==
│   │           ├── cm9sbHVwQDMuMjAuMA==
│   │           ├── cmF3LWJvZHlAMi41LjE=
│   │           ├── cmF3LWJvZHlAMi41LjI=
│   │           ├── cmFuZ2UtcGFyc2VyQDEuMi4x
│   │           ├── cmV0QDAuMi4y
│   │           ├── cmV0cnlAMC4xMy4x
│   │           ├── cmV1c2lmeUAxLjAuNA==
│   │           ├── cmVhY3QtZG9tQDE4LjIuMA==
│   │           ├── cmVhY3QtcmVmcmVzaEAwLjE0LjA=
│   │           ├── cmVhY3RAMTguMi4w
│   │           ├── cmVhZGFibGUtc3RyZWFtQDMuNi4y
│   │           ├── cmVhZGFibGUtc3RyZWFtQDQuMy4w
│   │           ├── cmVhZGRpcnBAMy42LjA=
│   │           ├── cmVhbC1yZXF1aXJlQDAuMi4w
│   │           ├── cmVnZXhwcEAzLjIuMA==
│   │           ├── cmVxdWlyZS1mcm9tLXN0cmluZ0AyLjAuMg==
│   │           ├── cmVzb2x2ZS1mcm9tQDQuMC4w
│   │           ├── cmVzb2x2ZUAxLjIyLjE=
│   │           ├── cmVzdG9yZS1jdXJzb3JANC4wLjA=
│   │           ├── cmZkY0AxLjMuMA==
│   │           ├── cmltcmFmQDMuMC4y
│   │           ├── cnVuLXBhcmFsbGVsQDEuMi4w
│   │           ├── d29yZC13cmFwQDEuMi4z
│   │           ├── d2N3aWR0aEAxLjAuMQ==
│   │           ├── d2ViLXN0cmVhbXMtcG9seWZpbGxAMy4yLjE=
│   │           ├── d2ViaWRsLWNvbnZlcnNpb25zQDMuMC4x
│   │           ├── d2hhdHdnLW1pbWV0eXBlQDMuMC4w
│   │           ├── d2hhdHdnLXVybEA1LjAuMA==
│   │           ├── d2hpY2hAMi4wLjI=
│   │           ├── d3JhcHB5QDEuMC4y
│   │           ├── dG8tZmFzdC1wcm9wZXJ0aWVzQDIuMC4w
│   │           ├── dG8tcmVnZXgtcmFuZ2VANS4wLjE=
│   │           ├── dG9pZGVudGlmaWVyQDEuMC4x
│   │           ├── dGV4dC10YWJsZUAwLjIuMA==
│   │           ├── dGhyZWFkLXN0cmVhbUAyLjMuMA==
│   │           ├── dGlueS1scnVAMTAuMi4y
│   │           ├── dHI0NkAwLjAuMw==
│   │           ├── dHMtZGVib3VuY2VANC4wLjA=
│   │           ├── dHNsaWJAMi41LjA=
│   │           ├── dHlwZS1jaGVja0AwLjQuMA==
│   │           ├── dHlwZS1mZXN0QDAuMjAuMg==
│   │           ├── dHlwZS1pc0AxLjYuMTg=
│   │           ├── dW5pdmVyc2FsaWZ5QDIuMC4w
│   │           ├── dW5waXBlQDEuMC4w
│   │           ├── dWMubWljcm9AMS4wLjY=
│   │           ├── dXBhdGhAMi4wLjE=
│   │           ├── dXBkYXRlLWJyb3dzZXJzbGlzdC1kYkAxLjAuMTA=
│   │           ├── dXJpLWpzQDQuNC4x
│   │           ├── dXRpbC1kZXByZWNhdGVAMS4wLjI=
│   │           ├── dXRpbHMtbWVyZ2VAMS4wLjE=
│   │           ├── dXVpZEA5LjAuMA==
│   │           ├── djgtY29tcGlsZS1jYWNoZUAyLjMuMA==
│   │           ├── dmFsdWUtb3ItcHJvbWlzZUAxLjAuMTE=
│   │           ├── dmFyeUAxLjEuMg==
│   │           ├── dml0ZUA0LjIuMA==
│   │           ├── dml0ZUAzLjEuOA==
│   │           ├── dml0ZWZ1QDAuMi40
│   │           ├── dnVlLWRlbWlAMC45LjE=
│   │           ├── dnVlLXJvdXRlckA0LjEuNg==
│   │           ├── dnVlQDMuMi40Nw==
│   │           ├── dnVlcHJlc3Mtdml0ZUAyLjAuMC1iZXRhLjUz
│   │           ├── dnVlcHJlc3NAMi4wLjAtYmV0YS41Mw==
│   │           ├── eWFsbGlzdEA0LjAuMA==
│   │           ├── eWFsbGlzdEAzLjEuMQ==
│   │           └── eWFtbEAyLjIuMQ==
│   ├── compatibility/
│   │   ├── circular-esm.test.ts
│   │   ├── process.binding.test.ts
│   │   └── uv.test.ts
│   ├── examples/
│   │   ├── apollo-server.example.js
│   │   ├── astro.example.js
│   │   ├── console.example.js
│   │   ├── eslint.example.js
│   │   ├── exec.example.js
│   │   ├── express.example.js
│   │   ├── fastify.example.js
│   │   ├── fs-symlinks.example.js
│   │   ├── fs-watch-file.example.js
│   │   ├── http-server.example.js
│   │   ├── multiple.example.js
│   │   ├── next-13-app-simple.example.js
│   │   ├── next-13-app.example.js
│   │   ├── next-13.example.js
│   │   ├── next-api.example.js
│   │   ├── next.example.js
│   │   ├── nodemon.example.js
│   │   ├── nuxt.example.js
│   │   ├── shell-output.example.js
│   │   ├── sveltekit.example.js
│   │   ├── terminal.example.js
│   │   ├── timers.example.js
│   │   ├── vite-react.example.js
│   │   ├── vite-solid.example.js
│   │   ├── vite-svelte.example.js
│   │   ├── vite-vue.example.js
│   │   ├── vite.example.js
│   │   ├── vuepress.example.js
│   │   └── yarn.example.js
│   ├── features/
│   │   ├── child_process.test.ts
│   │   ├── console.test.ts
│   │   ├── files.start.test.ts
│   │   ├── multiple.test.ts
│   │   ├── package-manager/
│   │   │   └── hoist-pattern.test.ts
│   │   ├── shell.start.test.ts
│   │   └── worker_threads.test.ts
│   ├── frameworks/
│   │   ├── astro.start.test.ts
│   │   ├── express.test.ts
│   │   ├── fastify.test.ts
│   │   ├── http-server.start.test.ts
│   │   ├── next.start.test.ts
│   │   ├── vite.start.test.ts
│   │   └── vuepress.start.test.ts
│   ├── global.d.ts
│   ├── index.ts
│   ├── node-packages/
│   │   ├── apollo-server.test.ts
│   │   ├── eslint.test.ts
│   │   ├── node-fetch.test.ts
│   │   └── nodemon.test.ts
│   ├── setup/
│   │   ├── MockCdn.ts
│   │   ├── globalSetup.ts
│   │   ├── runSandpackCDNProxy.ts
│   │   ├── runTestServer.ts
│   │   └── server/
│   │       └── index.html
│   └── tsconfig.json
├── tsconfig.json
├── turbo.json
└── vercel.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .codesandbox/tasks.json
================================================
{
  // These tasks will run in order when initializing your CodeSandbox project.
  "setupTasks": [
    {
      "name": "Install PNPM",
      "command": "npm i -g pnpm@~7.4.0 --force"
    },
    {
      "name": "Install Dependencies",
      "command": "pnpm install"
    },
    {
      "name": "Build Dependencies",
      "command": "pnpm build"
    }
  ],

  // These tasks can be run from CodeSandbox. Running one will open a log in the app.
  "tasks": {
    "install": {
      "name": "Install Dependencies",
      "command": "pnpm install"
    },
    "build": {
      "name": "Build",
      "command": "pnpm build"
    },
    "build:prod": {
      "name": "Build:prod",
      "command": "IS_PROD_BUILD=1 pnpm build"
    },
    "start": {
      "name": "Start",
      "command": "pnpm start",
      "runAtStart": true
    },
    "watch:consumer": {
      "name": "Watch consumer",
      "command": "pnpm watch:consumer",
      "runAtStart": true
    },
    "test:unit": {
      "name": "Unit tests",
      "command": "pnpm run test:unit"
    },
    "Lint": {
      "name": "Lint",
      "command": "pnpm lint"
    },
    "Format:write": {
      "name": "Format:write",
      "command": "pnpm format:write"
    }
  }
}


================================================
FILE: .editorconfig
================================================
root = true

[*]
end_of_line = lf

[*.{js,ts,json}]
indent_style = space
indent_size = 2

[Makefile]
indent_style = tab


================================================
FILE: .env.example
================================================
PREVIEW_HOST=csb.test:3000

================================================
FILE: .env.test
================================================
EMULATOR_HOST=localhost:4000
PREVIEW_HOST=csb.test:3000
SANDPACK_CDN_ROOT=https://localhost:3500


================================================
FILE: .eslintignore
================================================
.turbo
build
internals/servers/consumer/dist/consumer.js
/packages/runtime/preview/**/*.js
/preview
tmp

================================================
FILE: .eslintrc.js
================================================
module.exports = {
  env: { browser: true, es2021: true },
  parser: '@typescript-eslint/parser',
  parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
  plugins: ['@typescript-eslint'],
  rules: { 'no-console': ['error', { allow: ['warn', 'error'] }] },
};


================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
.turbo
build
internals/servers/consumer/dist/consumer.js
internals/servers/consumer/bin
.env*
!.env.test
!.env.example
certificates
/packages/runtime/preview/**/*.js
*-error.log
*.log
/preview
tmp
test-results

================================================
FILE: .prettierignore
================================================
fixture
fixtures
build
internals/servers/consumer/dist/consumer.js
/packages/runtime/preview/**/*.js
/preview
tmp

================================================
FILE: .prettierrc
================================================
{
  "semi": true,
  "singleQuote": true,
  "bracketSpacing": true,
  "printWidth": 120,
  "tabWidth": 2,
  "overrides": [
    {
      "files": "*.(scss|css)",
      "options": {
        "singleQuote": false
      }
    }
  ]
}


================================================
FILE: .release-please-manifest.json
================================================
{"packages/nodebox":"0.1.9"}


================================================
FILE: ATTRIBUTIONS.md
================================================
# Open Source License Attribution

Nodebox uses various components from existing open source projects. You can find the source code of their open source projects along with license information below. We acknowledge and are grateful to these developers for their contributions to open source.

- [Node.js](https://github.com/nodejs/node): MIT - Node.js contributors
- [bun](https://github.com/oven-sh/bun): MIT - Oven.sh
- [browserify](https://github.com/browserify/browserify): MIT - James Halliday
- [os-browserify](https://github.com/CoderPuppy/os-browserify): MIT - CoderPuppy
- [node-process](https://github.com/defunctzombie/node-process): MIT - Roman Shtylman
- [deno_std](https://github.com/denoland/deno_std): MIT - Deno authors


================================================
FILE: LICENSE
================================================
Sustainable Use License

Version 1.0

Acceptance

By using the software, you agree to all of the terms and conditions below.

Copyright License

The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.

Limitations

You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.

Patents

The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.

Notices

You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.

No Other Rights

These terms do not imply any licenses other than those expressly granted in these terms.

Termination

If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.

No Liability

As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.

Definitions

The "licensor" is CodeSandBox B.V.

The "software" is the software the licensor makes available under these terms, including any portion of it.

"You" refers to the individual or entity agreeing to these terms.

"Your company" is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.

"Your license" is the license granted to you for the software under these terms.

"Use" means anything you do with the software requiring your license.

"Trademark" means trademarks, service marks, and similar rights.

================================================
FILE: README.md
================================================
# Nodebox

Nodebox is a runtime for executing Node.js modules in the browser.

## Why we built Nodebox

With `sandpack-bundler`, we allowed any developer anywhere to instantly create a fast, local, shareable playground inside their browser, without having to wait forever to install dependencies and fight with devtools. This improves the learning, experimentation and sharing experience of client-side JavaScript code.

However, server-side JavaScript remained a challenge. At CodeSandbox we have solved this by using [Firecracker VMs](https://codesandbox.io/blog/how-we-clone-a-running-vm-in-2-seconds), allowing us to bring your entire development environment to the cloud regardless of the programming language or tooling you might be using. Unfortunately, as VMs live in the cloud, they require infrastructure and a network connection, resulting in a higher cost compared to our client-side sandboxes.

To solve this problem, we built Nodebox, a runtime that runs entirely in the browser, eliminating the need for a network connection and infrastructure.

Nodebox gives you the same user experience you have come to expect from Sandpack, which means a near-instant server-side JavaScript environment at the click of a button—built for experimentation, examples and documentation.

## The differences between a VM and Nodebox

As mentioned in the previous section, we solved server-side sandboxes in CodeSandbox by using Firecracker VMs. In this section, we'll explain the advantages and disadvantages of each approach.

### Advantages of VMs over Nodebox

- You get dedicated resources, with no resource limits enforced by the browser
- You have an entire Unix OS available
- You can run any language, database, command
- You can use network sockets
- You can run large and complex projects
- A perfect 1:1 environment as compared to your local setup (at least, if you're using a Unix-based system)
- No emulation, so Node.js would run exactly the same way as locally

### Advantages of Nodebox

- No need for any infrastructure
- No need for a network connection
- Instant feedback to any change
- Easy to get started
- Easy and instant reset - simply refresh the page/iframe
- Every page visitor gets their own Nodebox instance automatically

## What makes it different

Nodebox is currently the only cross-browser Node.js runtime supporting all the latest browsers:

- Chrome;
- Firefox;
- Safari \*

> - Support for iOS Safari is in beta

Nodebox does not emulate Node.js but is, instead, a Node.js-compatible runtime. This means that it implements as much of the Node.js API as possible while keeping a minimal performance imprint, using browser API where applicable and, in some cases, leaving out certain parts of Node.js due to browser [limitations](#Limitations) or complexity.

Nodebox uses an internal dependency manager that is fine-tuned to deliver optimal initial load time by utilizing dependency caching via [Sandpack CDN](https://github.com/codesandbox/sandpack-cdn). That CDN is an open-source Rust package manager that runs in the cloud and can be self-hosted pretty easily as well.

While there are alternatives to Nodebox, they are closer to mimicking a container-based environment, running commands step-by-step, or even the entire Linux distributive in your browser. That makes them slower and harder to use compared to Nodebox, which is optimized to run sandboxes fast and with as little friction as possible.

## Limitations

Unfortunately, any type of runtime that does not have access to operating system-level APIs will come with certain limitations. For Nodebox, those are the following:

- N-API modules
- net#Sockets pointing to external IPs
- Synchronous exec/spawn
- async_hooks (planned for implementation)
- Automatic process exiting - users now need to manually call `process.exit` before the process is exited (planned for implementation)

As we implement every module manually one by one, it is possible that some will not behave correctly. If this happens, feel free to open an issue here on GitHub and we'll make sure to fix it.

## Documentation

- [**Getting started**](#getting-started)
- [API documentation](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md)

---

## Getting started

Nodebox is meant for usage in your client-side applications, granting them the capability of running actual Node.js code directly in the browser. Here are a couple of examples of when Nodebox can be used:

- Building interactive examples for server-side code in your documentation;
- Showcasing a UI component library in the actual framework it's built for;
- Generally any evaluation of Node.js code and previewing it in the browser.

In the context of this tutorial, we will be working on a documentation website that illustrates different examples of using a Next.js application. Bear in mind that our documentation itself can be written in any framework of our choosing.

### Install

Nodebox can be installed from NPM just like any other dependency:

```sh
npm install @codesandbox/nodebox
```

### Setup

Nodebox consists of two main parts:

- A runtime environment evaluating the code;
- A preview environment serving the result of the evaluation.

Corresponding to these two parts, let's create two iframes in our application:

```html
<!--
  The "nodebox" iframe will mount the Nodebox runtime,
  allowing it to communicate with the rest of the application.
-->
<iframe id="nodebox-iframe"></iframe>

<!--
  The "preview" iframe will contain the result of running
  the Next.js example we will configure in a moment.
-->
<iframe id="preview-iframe"></iframe>
```

Although the runtime environment can be self-hosted, we will use the default one pointing to the deployed Nodebox instance on CodeSandbox servers. We do need, however, to specify an `iframe` reference in our application where Nodebox should render its preview.

```js
import { Nodebox } from '@codesandbox/nodebox';

const runtime = new Nodebox({
  // Provide a reference to the <iframe> element in the DOM
  // where Nodebox should render the preview.
  iframe: document.getElementById('nodebox-iframe'),
});

// Establish a connection with the runtime environment.
await runtime.connect();
```

> Learn more about the [Nodebox API](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md).

You want to establish **a single Nodebox instance** across your entire application. Bear that in mind during the setup phase and consult your framework's documentation and best practices regarding the most efficient way of achieving this.

Previews correspond to _commands_ executed in Nodebox, meaning that at this stage there will be no previews mounted at the given iframe because we haven't run any commands yet. Let's change that.

### Initialize file system

Much like your own project, the project you create in Nodebox needs files to work with. It can be a single JavaScript file or the entire project, like Astro or Next.js.

Let's describe a Next.js project that we need.

```js
// Populate the in-memory file system of Nodebox
// with a Next.js project files.
await runtime.fs.init({
  'package.json': JSON.stringify({
    name: 'nextjs-preview',
    dependencies: {
      '@next/swc-wasm-nodejs': '12.1.6',
      next: '12.1.6',
      react: '18.2.0',
      'react-dom': '18.2.0',
    },
  }),
  // On the index page, let's illustrate how server-side props
  // propagate to your page component in Next.js.
  'pages/index.jsx': `
export default function Homepage({ name }) {
  return (
    <div>
      <h1>Hello, {name}</h1>
      <p>The name "{name}" has been received from server-side props.</p>
    </div>
  )
}

export function getServerSideProps() {
  return {
    props: {
      name: 'John'
    }
  }
}
    `,
});
```

> You can reference standard Node.js modules, as well as external dependencies while writing your project files. Note that you **don't have to install** those dependencies as Nodebox will manage dependency installation, caching, and resolution automatically.

What we did above was outline a file system state of an actual Next.js project for Nodebox to run. The last step remaining is to run Next.js.

### Run project

To run the project, we will run the `npm dev` command using the Shell API provided by Nodebox.

```js
// First, create a new shell instance.
// You can use the same instance to spawn commands,
// observe stdio, restart and kill the process.
const shell = runtime.shell.create();

// Then, let's run the "dev" script that we've defined
// in "package.json" during the previous step.
const nextProcess = await shell.runCommand('npm', ['dev']);

// Find the preview by the process and mount it
// on the preview iframe on the page.
const previewInfo = await runtime.preview.getByShellId(nextProcess.id);
const previewIframe = document.getElementById('preview-iframe');
previewIframe.setAttribute('src', previewInfo.url);
```

> Note that you can treat `shell.runCommand` similar to `spawn` in Node.js. Learn more about the Shell API in the [documentation](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md).

Once this command runs, it will return a shell reference we can use to retrieve the preview URL. By mounting that preview URL on our preview iframe from the setup, we can see the Next.js project running:

![](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/nextjs-preview.png)

That's it! 🎉 **Not a single server was spawned while running this Next.js application**. Everything was managed by Nodebox directly in your browser.

👉 Check out the [Sandbox for this tutorial](https://codesandbox.io/p/sandbox/nodebox-next-js-example-ji27x8).

================================================
FILE: dnsmasq.conf
================================================
# Handle local wildcard codesandbox domain
address=/csb.test/127.0.0.1

# Don't read /etc/resolv.conf or any other configuration files.
no-resolv
# Never forward plain names (without a dot or domain part)
domain-needed
# Never forward addresses in the non-routed address spaces.
bogus-priv


================================================
FILE: internals/esbuild-plugins/inline-file.ts
================================================
import path from 'path';
import fs from 'fs-extra';
import type { Plugin, OnLoadArgs } from 'esbuild';

export function inlineFilePlugin(): Plugin {
  const { filter, namespace, transform } = {
    /**
     *  A regex filter to match the desired import. Defaults to imports that start with `inline:`, e.g.
     *  import 'inline:./file.ext';
     */
    filter: /^inline:/,

    /**
     * The namespace to use. If you use more than one instance of this plugin, each one should have a unique
     * namespace. This is a random string by default, so you won't need to change it unless you're targeting a
     * specific namespace.
     */
    namespace: '_' + Math.random().toString(36).substr(2, 9),

    /**
     * A function to transform the contents of the imported file. This can be a simple string replace or a more
     * complex operation, such as a call to PostCSS, Sass, etc. The function must return a string.
     *
     * The contents argument will be a string containing the file's contents. The args argument is passed through from
     * esbuild, but the most useful is probably args.path which references the file path.
     *
     * Note that heavy operations here can impact esbuild's performance!
     */
    transform: async (contents: string, args: OnLoadArgs) => contents,
  };

  return {
    name: 'esbuild-inline-plugin',
    setup(build) {
      build.onResolve({ filter }, (args) => {
        const realPath = args.path.replace(filter, '');
        return {
          path: path.resolve(args.resolveDir, realPath),
          namespace,
        };
      });

      build.onLoad({ filter: /.*/, namespace }, async (args) => {
        let contents = await fs.readFile(args.path, 'utf8');

        if (typeof transform === 'function') {
          contents = await transform(contents, args);
        }

        return {
          contents,
          loader: 'text',
        };
      });
    },
  };
}


================================================
FILE: internals/esbuild-plugins/inline-worker.ts
================================================
import crypto from 'crypto';
import path from 'path';
import fs from 'fs-extra';
import type { Plugin } from 'esbuild';
import BaseX from 'base-x';

const WORKER_RE = /(?:new Worker|createNodeWorker|StatefulWorker)\(require\.resolve\(["'`]([.\\/\-\w]*)["'`]\)\)/g;

const base36 = BaseX('0123456789abcdefghijklmnopqrstuvwxyz');
export function hashString(val: string): string {
  const hash = crypto.createHash('sha1');
  const data = hash.update(val, 'utf-8');
  return base36.encode(data.digest());
}

export async function writeWorker(dirname: string, content: string): Promise<string> {
  const filename = `worker-${hashString(content)}.js`;
  await fs.writeFile(path.join(dirname, filename), content, 'utf-8');
  return filename;
}

const existingBundles = new Map<string, string>();
const existingReplaces = new Map<string, string>();

export function inlineWorkerPlugin(outDir: string, bundle: (entry: string) => Promise<string>): Plugin {
  const filter = /^worker-content:/;
  const namespace = '_' + Math.random().toString(36).substr(2, 9);

  return {
    name: 'esbuild-worker-threads-plugin',
    setup(build) {
      // Links worker-content: calls to this namespace
      build.onResolve({ filter }, (args) => {
        const realPath = args.path.replace(filter, '');
        return {
          path: path.resolve(args.resolveDir, realPath),
          namespace,
        };
      });

      // Handles `worker-content:` values to bundle them and replace with new link
      build.onLoad({ filter: /.*/, namespace }, async (args) => {
        // console.log(args);
        let workerPath = existingBundles.get(args.path);
        if (!workerPath) {
          const result = await bundle(args.path);
          workerPath = await writeWorker(outDir, result);
          existingBundles.set(args.path, workerPath);
        }
        return {
          contents: workerPath,
          loader: 'text',
        };
      });

      // Gets called when loading files, extracts worker constructors and replaces them with worker-content:...
      // to be handled by other onLoad
      build.onLoad({ filter: /.*\.(js|ts|mjs|cjs)/ }, async (args) => {
        const content = await fs.readFile(args.path, 'utf8');
        if (WORKER_RE.test(content)) {
          if (existingReplaces.has(args.path)) {
            return {
              contents: content,
              loader: args.path.endsWith('.ts') ? 'ts' : 'js',
            };
          }
          const result = content.replace(WORKER_RE, (...params) => {
            const replacement = /StatefulWorker/.test(params[0])
              ? `StatefulWorker(require("worker-content:${params[1]}"), { eval: true })`
              : `new Worker(require("worker-content:${params[1]}"), { eval: true })`;

            console.log(`Replacing: "${params[0]}" with "${replacement}"`);

            return replacement;
          });
          existingReplaces.set(args.path, result);
          //   console.log(`Rewrote worker constructor for ${path.relative(process.cwd(), args.path)}`);
          return {
            contents: result,
            loader: args.path.endsWith('.ts') ? 'ts' : 'js',
          };
        }
      });
    },
  };
}


================================================
FILE: internals/servers/consumer/build.ts
================================================
import esbuild from 'esbuild';
import path from 'path';
import os from 'os';
import { readFile, writeFile } from 'node:fs/promises';
import glob from 'glob-promise';
import { mkdir } from 'fs/promises';
import { existsSync } from 'fs';

const RUNTIME_PORT = 4000;
const RUNTIME_URL = `https://${os.hostname()}-${RUNTIME_PORT}.${
  process.env.CSB_PREVIEW_BASE_HOST ?? 'preview.csb.app'
}`;

(async function buildConsumer() {
  const files = await glob('tests/**/*.example.js', { cwd: path.resolve(process.cwd()) });
  const fileContent = [];

  for (const file of files) {
    const content = await readFile(file, { encoding: 'utf8' });

    const pickShellProcess = content.replace(
      `const shellProcess = emulator.shell.create();`,
      `const shellProcess = emulator.shell.create();
      onShellProcessAvailable(shellProcess);`
    );

    const splitPath = file.split('/');
    const exampleName = splitPath[splitPath.length - 1].replace('.example.js', '');

    fileContent.push({
      exampleName,
      content: pickShellProcess,
    });
  }

  const fileTemplate = `
  import { Nodebox } from '../../../../packages/nodebox';
      
  /**
   * Global vars
   */
  window.emulatorUrl = '${RUNTIME_URL}?layout=debug';
  window.Nodebox = Nodebox;
  const templates = ${JSON.stringify(fileContent)};
`;

  const output = path.resolve(process.cwd() + '/internals/servers/consumer/bin');

  if (!existsSync(output)) {
    await mkdir(output);
  }

  await writeFile(output + '/consumer.js', fileTemplate);

  await esbuild.build({
    bundle: true,
    minify: false,
    sourcemap: false,
    treeShaking: false,
    platform: 'browser',
    format: 'cjs',
    outdir: path.join(__dirname, './dist'),
    entryPoints: [path.join(__dirname, './bin/consumer.js')],
  });
})();


================================================
FILE: internals/servers/consumer/dist/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/xterm@5.1.0/lib/xterm.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/xterm@5.1.0/css/xterm.min.css" rel="stylesheet" />
    <title>Nodebox</title>
  </head>
  <body class="md:flex" style="border-top: 4px solid #028922">
    <aside class="md:max-w-sm md:w-full md:h-screen p-10 flex flex-col gap-4">
      <h1 class="text-4xl font-medium">Nodebox</h1>

      <div class="p-2 border rounded mt-1 flex">
        <select class="w-full" id="use-cases"></select>
        <button style="color: #028922" class="hover:text-sky-600 font-medium py-1 px-3 rounded text-sm leading-tight" id="run">Run</button>
        <button class="text-gray-600 hover:text-gray-800 py-1 px-3 rounded text-sm leading-tight" id="kill">
          Kill
        </button>
      </div>

      <div class="px-2">
        <table class="text-sm font-light w-full" style="color: #0e0e0e">
          <tr>
            <td>Dependencies:</td>
            <td id="timedependencies" class="tabular-nums text-right"><span></span></td>
          </tr>
          <tr>
            <td class="font-medium">Total: </td>
            <td id="timetotal" class="tabular-nums text-right"><span></span></td>
          </tr>
        </table>
      </div>

      <h2 class="mt-2 font-medium">Dependencies <span id="total-dependencies"></h2>
      <div class="overflow-auto mt-1 text-sm">
        <pre id="dependencies"></pre>
      </div>
    </aside>
    
    <main class="h-96 md:w-full md:h-screen pt-10">
      <iframe id="frame" style="width: 100%; height: 55vh" sandbox="allow-scripts allow-same-origin"></iframe>
      <div style="width: 100%; height: 40vh; padding: 1em; background: black;" id="terminal"></div>
    </main>

    <script src="./consumer.js"></script>
    <script>
      /**
       * User interface
       */
      const select = document.querySelector('#use-cases');
      const exitButton = document.querySelector('#kill');
      const runButton = document.querySelector('#run');
      const dependenciesArea = document.querySelector('#dependencies');
      const timeLoadParagraph = document.querySelector('#timetotal span');
      const timeLoadDepParagraph = document.querySelector('#timedependencies span');
      const totalDependencies = document.querySelector("#total-dependencies")
      const terminal = document.querySelector("#terminal")
      
      var term = new Terminal({
        convertEol: true,
        cursorBlink: false,
        disableStdin: false,
        cols: 140
      });
      term.open(terminal);

      let timer;

      templates.forEach(({ exampleName }) => {
        const opt = document.createElement('option');
        opt.text = exampleName;

        select.appendChild(opt);
      });

      select.value = localStorage['CSB_EMULATOR_PLAYGROUND_OPT'];

      const clean = () => {
        dependenciesArea.innerText = '';
        timeLoadParagraph.innerText = '';
        timeLoadDepParagraph.innerText = '';
        term.clear()
      };

      runButton.addEventListener('click', () => {
        clean();
        localStorage['CSB_EMULATOR_PLAYGROUND_OPT'] = select.value;

        const func = templates.find((item) => item.exampleName === select.value);
        eval(func.content);
        window.runExample(window.emulatorUrl);

        timer = new Date().getTime();
      });

      const onShellProcessAvailable = (shellProcess) => {
        let initialTotalPending
        shellProcess.on('progress', (data) => {
          if (data.state === 'downloaded_module') {
            dependenciesArea.innerText = dependenciesArea.innerText.trim() + `\n${data.totalPending} ${data.name.trim()}@${data.version}`;
            
            if(!initialTotalPending) {
              initialTotalPending = data.totalPending
            }

            if (data.totalPending === 1) {
              timeLoadDepParagraph.innerText = new Date().getTime() - timer + 'ms';
            }
            
            totalDependencies.innerText = `(${initialTotalPending +1 - data.totalPending}/${initialTotalPending})`
          }
        });

        term.onData((data) => {
          shellProcess.stdin.write(data);
        });

        shellProcess.stdout.on('data', (data) => {
          term.write(data);
          
          timeLoadParagraph.innerText = new Date().getTime() - timer + 'ms';
        });
        
        shellProcess.stderr.on("data", (data) => {
          term.write(data);
        })


        exitButton.addEventListener('click', () => {
          shellProcess.kill();
          clean();
        });
      };
    </script>
  </body>
</html>


================================================
FILE: internals/servers/consumer/serve.ts
================================================
import 'dotenv/config';
import { setupApp } from '../utils';

import fastifyStatic from '@fastify/static';
import path from 'path';

const PORT = 5000;

const app = setupApp();

app.register(fastifyStatic, {
  root: path.join(__dirname, './dist'),
  index: ['index.html'],
  setHeaders: (res) => {
    res.setHeader('x-csb-no-sw-proxy', '1');
  },
  decorateReply: false,
});

app.listen({ port: PORT }, function (err, address) {
  if (err) {
    app.log.error(err);
    process.exit(1);
  }

  /* eslint-disable-next-line no-console */
  console.log(`Server is now listening on ${address}`);
});


================================================
FILE: internals/servers/main-server.ts
================================================
import path from 'path';
import 'dotenv/config';
import { setupApp } from './utils';

import fastifyStatic from '@fastify/static';

const PORT = +(process.env.PORT || '4000');

const app = setupApp();

const NODE_EMULATOR_RUNTIME_BUILD_DIR = path.join(__dirname, '../../packages/runtime/build');

app.register(fastifyStatic, {
  root: NODE_EMULATOR_RUNTIME_BUILD_DIR,
  index: ['index.html'],
  setHeaders: (res) => {
    res.setHeader('x-csb-no-sw-proxy', '1');
  },
  decorateReply: false,
});

app.register(fastifyStatic, {
  prefix: '/public/',
  root: path.join(__dirname, '../public'),
  index: ['index.html'],
  setHeaders: (res, filePath) => {
    const parsedPath = path.parse(filePath);
    if (parsedPath.ext === '.gz') {
      res.setHeader('Content-Encoding', 'gzip');
    } else if (parsedPath.ext === '.br') {
      res.setHeader('Content-Encoding', 'br');
    }
  },
  decorateReply: false,
});

// Run the server!
app.listen({ port: PORT }, function (err, address) {
  if (err) {
    app.log.error(err);
    process.exit(1);
  }

  console.log(`Server is now listening on ${address}`);
});


================================================
FILE: internals/servers/preview-server.ts
================================================
import 'dotenv/config';
import { setupApp } from './utils';

import fastifyStatic from '@fastify/static';
import path from 'path';

const PORT = +(process.env.PORT || '3000');

const app = setupApp();

const PREVIEW_BUILD_DIR = path.join(__dirname, '../../packages/runtime/preview');

app.register(fastifyStatic, {
  root: PREVIEW_BUILD_DIR,
  index: ['index.html'],
  setHeaders: (res) => {
    res.setHeader('x-csb-no-sw-proxy', '1');
  },
  decorateReply: false,
});

// Run the server!
app.listen({ port: PORT }, function (err, address) {
  if (err) {
    app.log.error(err);
    process.exit(1);
  }

  console.log(`Server is now listening on ${address}`);
});


================================================
FILE: internals/servers/test/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Test Server</title>
  </head>
  <body>
    <script type="module" src="/nodebox/index.mjs"></script>
    <script type="module">
      import { Nodebox } from '/nodebox/index.mjs';
      window.Nodebox = Nodebox;
    </script>

    <h1>Test server</h1>
    <iframe id="frame" sandbox="allow-scripts allow-same-origin"></iframe>
  </body>
</html>


================================================
FILE: internals/servers/test/test-server.ts
================================================
import 'dotenv/config';
import { setupApp } from '../utils';

import fastifyStatic from '@fastify/static';
import path from 'path';

const PORT = 4007;

const app = setupApp();

app.register(fastifyStatic, {
  root: path.join(__dirname),
  index: ['index.html'],
  decorateReply: false,
});

app.register(fastifyStatic, {
  root: path.join(__dirname, '../../..', 'packages/nodebox/build'),
  prefix: '/nodebox/',
  decorateReply: false,
});

app.listen({ port: PORT }, function (err, address) {
  if (err) {
    app.log.error(err);
    process.exit(1);
  }

  console.log(`Server is now listening on ${address}`);
});


================================================
FILE: internals/servers/utils.ts
================================================
import fastify, { FastifyInstance } from 'fastify';
import fs from 'fs';
import path from 'path';

export function setupApp(): FastifyInstance {
  if (process.env.CSB) {
    return fastify({
      logger: true,
    });
  }

  const app = fastify({
    logger: true,
    https: {
      key: fs.readFileSync(path.join(__dirname, '../../certificates/cert.key')),
      cert: fs.readFileSync(path.join(__dirname, '../../certificates/cert.crt')),
    },
  });

  app.log.level = process.env.NODE_ENV === 'test' ? 'error' : 'debug';

  return app;
}


================================================
FILE: package.json
================================================
{
  "private": true,
  "name": "nodebox",
  "version": "0.0.0",
  "scripts": {
    "build": "turbo run build --no-cache && pnpm build:consumer",
    "build:runtime": "turbo run build --filter runtime --no-cache",
    "build:api": "turbo run build --filter @codesandbox/nodebox --no-cache",
    "build:consumer": "node -r esbuild-register ./internals/servers/consumer/build.ts",
    "---": "---",
    "watch:consumer": "onchange 'tests/**/**.example.js' -- pnpm build:consumer",
    "----": "----",
    "start:preview": "node -r esbuild-register ./internals/servers/preview-server.ts",
    "start:runtime": "node -r esbuild-register ./internals/servers/main-server.ts",
    "start:consumer": "node -r esbuild-register ./internals/servers/consumer/serve.ts",
    "start:test-server": "node -r esbuild-register ./internals/servers/test/test-server.ts",
    "-----": "-----",
    "start": "concurrently \"pnpm start:runtime\" \"pnpm start:consumer\" \"pnpm start:preview\"",
    "cert": "mkdir -p certificates && openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout certificates/cert.key -out certificates/cert.crt -config req.conf -extensions v3_req",
    "cert:trust": "sudo security add-trusted-cert -d -r trustRoot -k \"/Library/Keychains/System.keychain\" ./certificates/cert.crt",
    "test:unit": "turbo run test:unit",
    "test:e2e": "pnpm playwright test",
    "test:e2e:debug": "PWDEBUG=1 pnpm run test:e2e",
    "------": "------",
    "lint": "eslint packages/**/*.{ts,js}",
    "format:check": "prettier --check packages/**/*.{ts,js}",
    "format:write": "prettier --write packages/**/*.{ts,js}"
  },
  "dependencies": {
    "@open-draft/deferred-promise": "^2.1.0",
    "@swc/helpers": "^0.4.2",
    "@typescript-eslint/eslint-plugin": "^5.43.0",
    "@typescript-eslint/parser": "^5.43.0",
    "base-x": "^4.0.0",
    "concurrently": "^7.5.0",
    "cuid": "^2.1.8",
    "dotenv": "^16.0.1",
    "esbuild-plugin-alias": "^0.2.1",
    "esbuild-register": "^3.4.1",
    "eslint": "^8.28.0",
    "node-fetch": "^2.6.7",
    "vite": "^2.9.12"
  },
  "devDependencies": {
    "@fastify/static": "^6.4.0",
    "@msgpack/msgpack": "^2.7.2",
    "@playwright/test": "^1.25.1",
    "@swc/core": "^1.2.204",
    "@swc/register": "^0.1.10",
    "@types/fs-extra": "^9.0.13",
    "@types/glob": "8.0.0",
    "@types/jest": "^29.2.0",
    "@types/node": "^18.0.0",
    "@types/node-fetch": "^2.6.2",
    "esbuild": "^0.14.46",
    "fastify": "^4.1.0",
    "fs-extra": "^10.1.0",
    "glob": "8.0.3",
    "glob-promise": "5.0.0",
    "jest": "^29.2.1",
    "onchange": "7.1.0",
    "outvariant": "^1.4.0",
    "playwright": "^1.25.1",
    "playwright-testing-library": "^4.3.1",
    "prettier": "^2.7.1",
    "rimraf": "^3.0.2",
    "ts-jest": "^29.0.3",
    "turbo": "^1.5.5",
    "typescript": "^4.8.4",
    "wait-for-expect": "^3.0.2"
  }
}


================================================
FILE: packages/nodebox/.npmignore
================================================
src
build.ts
CHANGELOG.md

================================================
FILE: packages/nodebox/CHANGELOG.md
================================================
# Changelog

## [0.1.9](https://github.com/Sandpack/nodebox-internal/compare/nodebox-v0.1.8...nodebox-v0.1.9) (2023-11-29)


### Bug Fixes

* force a new release ([5b50af9](https://github.com/Sandpack/nodebox-internal/commit/5b50af93a58a3ddf6bcc9ce001f92cc7711e4702))

## [0.1.8](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.7...nodebox-v0.1.8) (2023-05-19)


### Bug Fixes

* **package.json:** update outvariant dependency to 1.4.0 in all packages ([#378](https://github.com/codesandbox/nodebox-internal/issues/378)) ([1e2658f](https://github.com/codesandbox/nodebox-internal/commit/1e2658f68764373e95b3ee90973a68886d708139))

## [0.1.7](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.6...nodebox-v0.1.7) (2023-03-30)


### Features

* Add `INTERNAL_NODEBOX_DEV` to improve debugging experience ([#372](https://github.com/codesandbox/nodebox-internal/issues/372)) ([f78ebd3](https://github.com/codesandbox/nodebox-internal/commit/f78ebd377a3d8de35bf3a4fafc12fc4c6c83b255))
* **console:** Implement Console class ([#370](https://github.com/codesandbox/nodebox-internal/issues/370)) ([265e194](https://github.com/codesandbox/nodebox-internal/commit/265e1942ee97a159b1fb3c238f19f0f6725c42f5))

## [0.1.6](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.5...nodebox-v0.1.6) (2023-03-07)


### Features

* **nodebox:** Implement fs.rm api ([#360](https://github.com/codesandbox/nodebox-internal/issues/360)) ([52d7dc3](https://github.com/codesandbox/nodebox-internal/commit/52d7dc3d589dddffb3ca6d0ccd342f9e409022c9))


### Bug Fixes

* **nodebox:** add repo url for npm find the package homepage ([#361](https://github.com/codesandbox/nodebox-internal/issues/361)) ([70057b7](https://github.com/codesandbox/nodebox-internal/commit/70057b7da7d97d6c5409c62fd329ba3f16824515))

## [0.1.5](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.4...nodebox-v0.1.5) (2023-03-05)


### Bug Fixes

* API page link ([#355](https://github.com/codesandbox/nodebox-internal/issues/355)) ([2c6970c](https://github.com/codesandbox/nodebox-internal/commit/2c6970c72d237258e10434c6f0b6f2232891be3d))

## [0.1.4](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.3...nodebox-v0.1.4) (2023-03-02)


### Bug Fixes

* **preview:** increase timeout message ([#349](https://github.com/codesandbox/nodebox-internal/issues/349)) ([3aba917](https://github.com/codesandbox/nodebox-internal/commit/3aba91788df1e5eb44f82f022c5298c11ecb2bf8))

## [0.1.3](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.2...nodebox-v0.1.3) (2023-03-01)


### Features

* **shell:** introduce stdin api on shell ([#338](https://github.com/codesandbox/nodebox-internal/issues/338)) ([7630ca2](https://github.com/codesandbox/nodebox-internal/commit/7630ca295107e3a25cdd0d553f97240b79fa6b10))


### Bug Fixes

* **fs-writeFile:** content can be string or Uint8Array ([#346](https://github.com/codesandbox/nodebox-internal/issues/346)) ([8309deb](https://github.com/codesandbox/nodebox-internal/commit/8309deb35776b1a1dfee786bdf9b534ef08d99ee))

## [0.1.2](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.1.1...nodebox-v0.1.2) (2023-02-23)


### Features

* accept custom "cdnUrl" ([#273](https://github.com/codesandbox/nodebox-internal/issues/273)) ([21cca7a](https://github.com/codesandbox/nodebox-internal/commit/21cca7a298c64d355bc125ff12339e3c82d8e00f))
* **nodebox:** Add more fs methods to the public API ([#332](https://github.com/codesandbox/nodebox-internal/issues/332)) ([38c1abc](https://github.com/codesandbox/nodebox-internal/commit/38c1abc29b25d85665f67414042489131fb8637d))
* **nodebox:** make runtime URL optional and imply the default value ([#299](https://github.com/codesandbox/nodebox-internal/issues/299)) ([bb65224](https://github.com/codesandbox/nodebox-internal/commit/bb6522498fe8529ac74c79ab1bb238727127bdb0))
* remove picomatch for simple glob util ([#236](https://github.com/codesandbox/nodebox-internal/issues/236)) ([0d10685](https://github.com/codesandbox/nodebox-internal/commit/0d10685a5b733155a50fc928872a90eb966e975a))
* **shell:** implement stdout/stderr emitters ([#227](https://github.com/codesandbox/nodebox-internal/issues/227)) ([cd7cd9a](https://github.com/codesandbox/nodebox-internal/commit/cd7cd9a63a1c515a04e4d713c9a324773a2fb72a))
* **shell:** replace ".exit()" with ".kill()" ([#226](https://github.com/codesandbox/nodebox-internal/issues/226)) ([43b6e78](https://github.com/codesandbox/nodebox-internal/commit/43b6e78b67ace366ade9fab96e37e79ee66fa6db))


### Bug Fixes

* improve error handling, support operation rejections ([#251](https://github.com/codesandbox/nodebox-internal/issues/251)) ([78ce271](https://github.com/codesandbox/nodebox-internal/commit/78ce2714e5c29839e93a655e250042aac57ff36d))
* incorrect cdnUrl typings on runtime iframe protocol ([b68abb2](https://github.com/codesandbox/nodebox-internal/commit/b68abb272265b96086ac904f232583e933238b92))
* **nodebox:** check url argument, improve error messages ([#218](https://github.com/codesandbox/nodebox-internal/issues/218)) ([f9ec17c](https://github.com/codesandbox/nodebox-internal/commit/f9ec17c33d674ccb73f1b15dbb4f442ae2b39c15))
* **nodebox:** publish version ([#334](https://github.com/codesandbox/nodebox-internal/issues/334)) ([18ad452](https://github.com/codesandbox/nodebox-internal/commit/18ad452635f0b82d036f3693ec4fd6a202ea6557))
* package export for nodebox ([#321](https://github.com/codesandbox/nodebox-internal/issues/321)) ([a486b44](https://github.com/codesandbox/nodebox-internal/commit/a486b44d0dfc86e10fb54c346cb294f5f3e8c215))
* **progress message:** drop `progress` key in favor of `totalPending` ([#292](https://github.com/codesandbox/nodebox-internal/issues/292)) ([9856a15](https://github.com/codesandbox/nodebox-internal/commit/9856a155e536ae24072c818e8b68986bd27702bc))
* readme links ([#306](https://github.com/codesandbox/nodebox-internal/issues/306)) ([d83bbbc](https://github.com/codesandbox/nodebox-internal/commit/d83bbbcd0e0d33931a7cafd419252bf68d84b093))
* **readme:** remove sentence about VMs ([#312](https://github.com/codesandbox/nodebox-internal/issues/312)) ([6c9260f](https://github.com/codesandbox/nodebox-internal/commit/6c9260f1f6cb806351327a69fef316982b0f94af))
* rename publish script and folder name ([#239](https://github.com/codesandbox/nodebox-internal/issues/239)) ([2dac1db](https://github.com/codesandbox/nodebox-internal/commit/2dac1dba061a1ff42adb29d6265ff88ebc4993ff))
* **shell:** emit "exit" when shell exits ([#287](https://github.com/codesandbox/nodebox-internal/issues/287)) ([3b25008](https://github.com/codesandbox/nodebox-internal/commit/3b25008cb386ef45b58b0672b16a86a86ced2593))
* **shell:** replace "shell.listen()" with "shell.on()" ([#234](https://github.com/codesandbox/nodebox-internal/issues/234)) ([1774241](https://github.com/codesandbox/nodebox-internal/commit/17742414bc938707d9142e1895b64f522c5366a0))
* update configuration steps ([#310](https://github.com/codesandbox/nodebox-internal/issues/310)) ([9d7df79](https://github.com/codesandbox/nodebox-internal/commit/9d7df79ffb90b67632e3e20ba2c2ef5125e0df4d))

## [0.0.41](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.0.40...nodebox-v0.0.41) (2023-02-23)


### Features

* **nodebox:** Add more fs methods to the public API ([#332](https://github.com/codesandbox/nodebox-internal/issues/332)) ([38c1abc](https://github.com/codesandbox/nodebox-internal/commit/38c1abc29b25d85665f67414042489131fb8637d))

## [0.0.40](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.0.39...nodebox-v0.0.40) (2023-02-21)


### Bug Fixes

* package export for nodebox ([#321](https://github.com/codesandbox/nodebox-internal/issues/321)) ([a486b44](https://github.com/codesandbox/nodebox-internal/commit/a486b44d0dfc86e10fb54c346cb294f5f3e8c215))

## [0.0.39](https://github.com/codesandbox/nodebox-internal/compare/nodebox-v0.0.38...nodebox-v0.0.39) (2023-02-16)


### Bug Fixes

* readme links ([#306](https://github.com/codesandbox/nodebox-internal/issues/306)) ([d83bbbc](https://github.com/codesandbox/nodebox-internal/commit/d83bbbcd0e0d33931a7cafd419252bf68d84b093))
* **readme:** remove sentence about VMs ([#312](https://github.com/codesandbox/nodebox-internal/issues/312)) ([6c9260f](https://github.com/codesandbox/nodebox-internal/commit/6c9260f1f6cb806351327a69fef316982b0f94af))
* update configuration steps ([#310](https://github.com/codesandbox/nodebox-internal/issues/310)) ([9d7df79](https://github.com/codesandbox/nodebox-internal/commit/9d7df79ffb90b67632e3e20ba2c2ef5125e0df4d))

## [0.0.38](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.37...nodebox-v0.0.38) (2023-02-15)


### Features

* **nodebox:** make runtime URL optional and imply the default value ([#299](https://github.com/codesandbox/nodebox/issues/299)) ([bb65224](https://github.com/codesandbox/nodebox/commit/bb6522498fe8529ac74c79ab1bb238727127bdb0))

## [0.0.37](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.36...nodebox-v0.0.37) (2023-02-08)


### Bug Fixes

* **progress message:** drop `progress` key in favor of `totalPending` ([#292](https://github.com/codesandbox/nodebox/issues/292)) ([9856a15](https://github.com/codesandbox/nodebox/commit/9856a155e536ae24072c818e8b68986bd27702bc))
* **shell:** emit "exit" when shell exits ([#287](https://github.com/codesandbox/nodebox/issues/287)) ([3b25008](https://github.com/codesandbox/nodebox/commit/3b25008cb386ef45b58b0672b16a86a86ced2593))

## [0.0.36](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.35...nodebox-v0.0.36) (2023-02-02)


### Bug Fixes

* incorrect cdnUrl typings on runtime iframe protocol ([b68abb2](https://github.com/codesandbox/nodebox/commit/b68abb272265b96086ac904f232583e933238b92))

## [0.0.35](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.34...nodebox-v0.0.35) (2023-01-26)


### Features

* accept custom "cdnUrl" ([#273](https://github.com/codesandbox/nodebox/issues/273)) ([21cca7a](https://github.com/codesandbox/nodebox/commit/21cca7a298c64d355bc125ff12339e3c82d8e00f))

## [0.0.34](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.33...nodebox-v0.0.34) (2023-01-17)


### Bug Fixes

* improve error handling, support operation rejections ([#251](https://github.com/codesandbox/nodebox/issues/251)) ([78ce271](https://github.com/codesandbox/nodebox/commit/78ce2714e5c29839e93a655e250042aac57ff36d))

## [0.0.33](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.32...nodebox-v0.0.33) (2023-01-10)


### Bug Fixes

* rename publish script and folder name ([#239](https://github.com/codesandbox/nodebox/issues/239)) ([2dac1db](https://github.com/codesandbox/nodebox/commit/2dac1dba061a1ff42adb29d6265ff88ebc4993ff))

## [0.0.32](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.31...nodebox-v0.0.32) (2023-01-10)


### Features

* remove picomatch for simple glob util ([#236](https://github.com/codesandbox/nodebox/issues/236)) ([0d10685](https://github.com/codesandbox/nodebox/commit/0d10685a5b733155a50fc928872a90eb966e975a))
* **shell:** implement stdout/stderr emitters ([#227](https://github.com/codesandbox/nodebox/issues/227)) ([cd7cd9a](https://github.com/codesandbox/nodebox/commit/cd7cd9a63a1c515a04e4d713c9a324773a2fb72a))


### Bug Fixes

* **shell:** replace "shell.listen()" with "shell.on()" ([#234](https://github.com/codesandbox/nodebox/issues/234)) ([1774241](https://github.com/codesandbox/nodebox/commit/17742414bc938707d9142e1895b64f522c5366a0))

## [0.0.31](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.30...nodebox-v0.0.31) (2022-12-20)


### Features

* **shell:** replace ".exit()" with ".kill()" ([#226](https://github.com/codesandbox/nodebox/issues/226)) ([43b6e78](https://github.com/codesandbox/nodebox/commit/43b6e78b67ace366ade9fab96e37e79ee66fa6db))


### Bug Fixes

* **nodebox:** check url argument, improve error messages ([#218](https://github.com/codesandbox/nodebox/issues/218)) ([f9ec17c](https://github.com/codesandbox/nodebox/commit/f9ec17c33d674ccb73f1b15dbb4f442ae2b39c15))

## [0.0.30](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.29...nodebox-v0.0.30) (2022-12-14)


### Features

* Refactor node worker spawning to use MessageChannel ([#205](https://github.com/codesandbox/nodebox/issues/205)) ([6896135](https://github.com/codesandbox/nodebox/commit/6896135706bf2bd847c34ab9d289eb67de76a2f7))

## [0.0.29](https://github.com/codesandbox/nodebox/compare/nodebox-v0.0.28...nodebox-v0.0.29) (2022-12-08)


### Bug Fixes

* update deferred promises ([#200](https://github.com/codesandbox/nodebox/issues/200)) ([d11066e](https://github.com/codesandbox/nodebox/commit/d11066eb2852b51717f237b918b8eb8f4c878274))

## [0.0.28](https://github.com/codesandbox/browser-node-emulator/compare/nodebox-v0.0.27...nodebox-v0.0.28) (2022-11-29)


### Features

* **bridge:** improve worker handling, use MessageChannel for worker ([#162](https://github.com/codesandbox/browser-node-emulator/issues/162)) ([bbe1e11](https://github.com/codesandbox/browser-node-emulator/commit/bbe1e11679daed2b28ff8eec1d5e6aad39373976))
* fs refactor ([#100](https://github.com/codesandbox/browser-node-emulator/issues/100)) ([5797d19](https://github.com/codesandbox/browser-node-emulator/commit/5797d19528defb2724abbd1d2cf0cb03d05b2b60))
* **fs:** FSWatcher ([#75](https://github.com/codesandbox/browser-node-emulator/issues/75)) ([b378b76](https://github.com/codesandbox/browser-node-emulator/commit/b378b763e85ec24b117a3ac962ee22ef39f22738))
* **fs:** read / write files ([#60](https://github.com/codesandbox/browser-node-emulator/issues/60)) ([05c032d](https://github.com/codesandbox/browser-node-emulator/commit/05c032dbe33916faa563a858c67e464c9b03a9f6))
* **node emulator:** preview interface ([#41](https://github.com/codesandbox/browser-node-emulator/issues/41)) ([e7e66bb](https://github.com/codesandbox/browser-node-emulator/commit/e7e66bbaced7cf5eb20d14b58816e11737f9c3ed))
* **public fs:** implement fs watch ([#90](https://github.com/codesandbox/browser-node-emulator/issues/90)) ([fe9b0b6](https://github.com/codesandbox/browser-node-emulator/commit/fe9b0b68ef61532483a326e3d3ea0b9e565bc273))
* **runtime:** runtime protocols ([#131](https://github.com/codesandbox/browser-node-emulator/issues/131)) ([18a92b9](https://github.com/codesandbox/browser-node-emulator/commit/18a92b993d3d21475a903708ff565bb3cf586583))
* **shell:** Allow custom commands ([#61](https://github.com/codesandbox/browser-node-emulator/issues/61)) ([c90890d](https://github.com/codesandbox/browser-node-emulator/commit/c90890db2e0f1c143221772ab76eacb3cafbe23f))
* **shellProcess:** consume stdout ([#94](https://github.com/codesandbox/browser-node-emulator/issues/94)) ([7e5667e](https://github.com/codesandbox/browser-node-emulator/commit/7e5667ebaecf2afb968a1ceb6cf57a90df1a9575))
* **shellProcess:** on exit ([#108](https://github.com/codesandbox/browser-node-emulator/issues/108)) ([dcbd2c5](https://github.com/codesandbox/browser-node-emulator/commit/dcbd2c59aec2479617a37972507081b90bc88fbb))
* **shell:** ShellProcess interface ([#72](https://github.com/codesandbox/browser-node-emulator/issues/72)) ([cdc0cf7](https://github.com/codesandbox/browser-node-emulator/commit/cdc0cf759f016ac5c923bb957caefd555ccaafab))
* Worker progress messages ([#122](https://github.com/codesandbox/browser-node-emulator/issues/122)) ([084eb2f](https://github.com/codesandbox/browser-node-emulator/commit/084eb2f9cfe63d205894e7dd5f89016a40b0b200))


### Bug Fixes

* **emulator:** get rid of internal dependency ([#173](https://github.com/codesandbox/browser-node-emulator/issues/173)) ([b0db69a](https://github.com/codesandbox/browser-node-emulator/commit/b0db69adb70cb4619169dc6a56c1423f17307217))
* **emulator:** get rid of internal dependency ([#173](https://github.com/codesandbox/browser-node-emulator/issues/173)) ([d4c9b8f](https://github.com/codesandbox/browser-node-emulator/commit/d4c9b8f94bfb310949ed90005bb615b9ecf88f4a))
* **node-emulator:** set build target to es2020 ([#38](https://github.com/codesandbox/browser-node-emulator/issues/38)) ([5ff50fc](https://github.com/codesandbox/browser-node-emulator/commit/5ff50fca586101b6270f5f587900a031466c024a))
* **node-emulator:** trigger a new publish ([4b42c8f](https://github.com/codesandbox/browser-node-emulator/commit/4b42c8f43c8dea0491b48af067b07eb74922848f))
* **node-emulator:** trigger a new publish ([baef111](https://github.com/codesandbox/browser-node-emulator/commit/baef111bc1bd3bd34b5ff82fbeaa0a141372c417))
* **node-emulator:** trigger a new publish ([#171](https://github.com/codesandbox/browser-node-emulator/issues/171)) ([8485b15](https://github.com/codesandbox/browser-node-emulator/commit/8485b151f3cbfd88692183a48a263ef070da08b3))
* **NodeEmulator.ts:** export FilesMap type to consumer ([#57](https://github.com/codesandbox/browser-node-emulator/issues/57)) ([d676be5](https://github.com/codesandbox/browser-node-emulator/commit/d676be50f20f6d88bd7bbd6fa9edf3047e5fa8f2))
* Potential race condition with public api ([#111](https://github.com/codesandbox/browser-node-emulator/issues/111)) ([e5e0492](https://github.com/codesandbox/browser-node-emulator/commit/e5e04929c2f2b1dc28a22970bd1e796ed2119236))
* **preview:** remove conditional over listener ([#53](https://github.com/codesandbox/browser-node-emulator/issues/53)) ([5c6e8c0](https://github.com/codesandbox/browser-node-emulator/commit/5c6e8c0a0600a3b408f734a17b13a8f37ef8e09d))
* public watch api and public message bus refactor ([#117](https://github.com/codesandbox/browser-node-emulator/issues/117)) ([2d23b09](https://github.com/codesandbox/browser-node-emulator/commit/2d23b0969652d9c1ff17a9fac79d512f53c332f8))
* remove handshake timeout log ([49413a6](https://github.com/codesandbox/browser-node-emulator/commit/49413a6dde5d8300e626298553fb09a9ce32cf4c))
* **runtime protocol:** remove promise ([#139](https://github.com/codesandbox/browser-node-emulator/issues/139)) ([51a996e](https://github.com/codesandbox/browser-node-emulator/commit/51a996e64ba105bc2a1164bf09000a13f9076936))
* **runtime-protocol.types.ts:** export `InjectMessage` type ([#133](https://github.com/codesandbox/browser-node-emulator/issues/133)) ([b47387a](https://github.com/codesandbox/browser-node-emulator/commit/b47387adbb303552fdc1dd8f0a3aab93704a7550))
* **shell stdout:** fix types ([#105](https://github.com/codesandbox/browser-node-emulator/issues/105)) ([e77d244](https://github.com/codesandbox/browser-node-emulator/commit/e77d244ce2d9ca45ff6a28d0b60dc51b3c512eb7))
* **ShellProcess:** drop restart ([#88](https://github.com/codesandbox/browser-node-emulator/issues/88)) ([5371e4b](https://github.com/codesandbox/browser-node-emulator/commit/5371e4b681c4806112873e1c58a9fafea418ddb6))
* **shellprocess:** reassign internal state to running after restart ([#77](https://github.com/codesandbox/browser-node-emulator/issues/77)) ([13ae624](https://github.com/codesandbox/browser-node-emulator/commit/13ae6242aded1e8896256bb6a78edeb764aecf81))
* **shellprocess:** returning id on restart ([#78](https://github.com/codesandbox/browser-node-emulator/issues/78)) ([23f1230](https://github.com/codesandbox/browser-node-emulator/commit/23f1230c33b8c84911eede9d03d3b9e9bb2ac62f))
* UI tweak on fallback page and improve conditional on FS module ([#102](https://github.com/codesandbox/browser-node-emulator/issues/102)) ([bdfb9cc](https://github.com/codesandbox/browser-node-emulator/commit/bdfb9cc7e89992017bf257133500261fbe7eb933))
* Use picomatch-browser and fix build script ([#125](https://github.com/codesandbox/browser-node-emulator/issues/125)) ([521a432](https://github.com/codesandbox/browser-node-emulator/commit/521a432e22f6b11cc119af19c06ed29fdaad218f))
* **worker controller:** fix exit/restart worker ([#114](https://github.com/codesandbox/browser-node-emulator/issues/114)) ([fbb9ad5](https://github.com/codesandbox/browser-node-emulator/commit/fbb9ad5f890c8e188f9cd7c3b39f71de0e9a3c7e))

## [0.0.27](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.26...node-emulator-v0.0.27) (2022-11-24)


### Features

* **bridge:** improve worker handling, use MessageChannel for worker ([#162](https://github.com/codesandbox/browser-node-emulator/issues/162)) ([bbe1e11](https://github.com/codesandbox/browser-node-emulator/commit/bbe1e11679daed2b28ff8eec1d5e6aad39373976))

## [0.0.26](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.25...node-emulator-v0.0.26) (2022-11-22)


### Bug Fixes

* **emulator:** get rid of internal dependency ([#173](https://github.com/codesandbox/browser-node-emulator/issues/173)) ([d4c9b8f](https://github.com/codesandbox/browser-node-emulator/commit/d4c9b8f94bfb310949ed90005bb615b9ecf88f4a))

## [0.0.25](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.24...node-emulator-v0.0.25) (2022-11-22)


### Bug Fixes

* **node-emulator:** trigger a new publish ([#171](https://github.com/codesandbox/browser-node-emulator/issues/171)) ([8485b15](https://github.com/codesandbox/browser-node-emulator/commit/8485b151f3cbfd88692183a48a263ef070da08b3))

## [0.0.24](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.23...node-emulator-v0.0.24) (2022-11-10)


### Bug Fixes

* **runtime protocol:** remove promise ([#139](https://github.com/codesandbox/browser-node-emulator/issues/139)) ([51a996e](https://github.com/codesandbox/browser-node-emulator/commit/51a996e64ba105bc2a1164bf09000a13f9076936))

## [0.0.23](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.22...node-emulator-v0.0.23) (2022-11-10)


### Bug Fixes

* **runtime-protocol.types.ts:** export `InjectMessage` type ([#133](https://github.com/codesandbox/browser-node-emulator/issues/133)) ([b47387a](https://github.com/codesandbox/browser-node-emulator/commit/b47387adbb303552fdc1dd8f0a3aab93704a7550))

## [0.0.22](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.21...node-emulator-v0.0.22) (2022-11-10)


### Features

* **runtime:** runtime protocols ([#131](https://github.com/codesandbox/browser-node-emulator/issues/131)) ([18a92b9](https://github.com/codesandbox/browser-node-emulator/commit/18a92b993d3d21475a903708ff565bb3cf586583))

## [0.0.21](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.20...node-emulator-v0.0.21) (2022-11-01)


### Bug Fixes

* Use picomatch-browser and fix build script ([#125](https://github.com/codesandbox/browser-node-emulator/issues/125)) ([521a432](https://github.com/codesandbox/browser-node-emulator/commit/521a432e22f6b11cc119af19c06ed29fdaad218f))

## [0.0.20](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.19...node-emulator-v0.0.20) (2022-11-01)


### Features

* Worker progress messages ([#122](https://github.com/codesandbox/browser-node-emulator/issues/122)) ([084eb2f](https://github.com/codesandbox/browser-node-emulator/commit/084eb2f9cfe63d205894e7dd5f89016a40b0b200))

## [0.0.19](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.18...node-emulator-v0.0.19) (2022-10-31)


### Bug Fixes

* public watch api and public message bus refactor ([#117](https://github.com/codesandbox/browser-node-emulator/issues/117)) ([2d23b09](https://github.com/codesandbox/browser-node-emulator/commit/2d23b0969652d9c1ff17a9fac79d512f53c332f8))

## [0.0.18](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.17...node-emulator-v0.0.18) (2022-10-28)


### Bug Fixes

* **worker controller:** fix exit/restart worker ([#114](https://github.com/codesandbox/browser-node-emulator/issues/114)) ([fbb9ad5](https://github.com/codesandbox/browser-node-emulator/commit/fbb9ad5f890c8e188f9cd7c3b39f71de0e9a3c7e))

## [0.0.17](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.16...node-emulator-v0.0.17) (2022-10-28)


### Features

* **shellProcess:** on exit ([#108](https://github.com/codesandbox/browser-node-emulator/issues/108)) ([dcbd2c5](https://github.com/codesandbox/browser-node-emulator/commit/dcbd2c59aec2479617a37972507081b90bc88fbb))


### Bug Fixes

* Potential race condition with public api ([#111](https://github.com/codesandbox/browser-node-emulator/issues/111)) ([e5e0492](https://github.com/codesandbox/browser-node-emulator/commit/e5e04929c2f2b1dc28a22970bd1e796ed2119236))

## [0.0.16](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.15...node-emulator-v0.0.16) (2022-10-28)


### Features

* fs refactor ([#100](https://github.com/codesandbox/browser-node-emulator/issues/100)) ([5797d19](https://github.com/codesandbox/browser-node-emulator/commit/5797d19528defb2724abbd1d2cf0cb03d05b2b60))


### Bug Fixes

* **shell stdout:** fix types ([#105](https://github.com/codesandbox/browser-node-emulator/issues/105)) ([e77d244](https://github.com/codesandbox/browser-node-emulator/commit/e77d244ce2d9ca45ff6a28d0b60dc51b3c512eb7))

## [0.0.15](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.14...node-emulator-v0.0.15) (2022-10-28)


### Features

* **shellProcess:** consume stdout ([#94](https://github.com/codesandbox/browser-node-emulator/issues/94)) ([7e5667e](https://github.com/codesandbox/browser-node-emulator/commit/7e5667ebaecf2afb968a1ceb6cf57a90df1a9575))

## [0.0.14](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.13...node-emulator-v0.0.14) (2022-10-27)


### Bug Fixes

* UI tweak on fallback page and improve conditional on FS module ([#102](https://github.com/codesandbox/browser-node-emulator/issues/102)) ([bdfb9cc](https://github.com/codesandbox/browser-node-emulator/commit/bdfb9cc7e89992017bf257133500261fbe7eb933))

## [0.0.13](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.12...node-emulator-v0.0.13) (2022-10-27)


### Features

* **public fs:** implement fs watch ([#90](https://github.com/codesandbox/browser-node-emulator/issues/90)) ([fe9b0b6](https://github.com/codesandbox/browser-node-emulator/commit/fe9b0b68ef61532483a326e3d3ea0b9e565bc273))

## [0.0.12](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.11...node-emulator-v0.0.12) (2022-10-25)


### Features

* **fs:** FSWatcher ([#75](https://github.com/codesandbox/browser-node-emulator/issues/75)) ([b378b76](https://github.com/codesandbox/browser-node-emulator/commit/b378b763e85ec24b117a3ac962ee22ef39f22738))


### Bug Fixes

* **ShellProcess:** drop restart ([#88](https://github.com/codesandbox/browser-node-emulator/issues/88)) ([5371e4b](https://github.com/codesandbox/browser-node-emulator/commit/5371e4b681c4806112873e1c58a9fafea418ddb6))
* **shellprocess:** reassign internal state to running after restart ([#77](https://github.com/codesandbox/browser-node-emulator/issues/77)) ([13ae624](https://github.com/codesandbox/browser-node-emulator/commit/13ae6242aded1e8896256bb6a78edeb764aecf81))

## [0.0.11](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.10...node-emulator-v0.0.11) (2022-10-21)


### Bug Fixes

* **shellprocess:** returning id on restart ([#78](https://github.com/codesandbox/browser-node-emulator/issues/78)) ([23f1230](https://github.com/codesandbox/browser-node-emulator/commit/23f1230c33b8c84911eede9d03d3b9e9bb2ac62f))

## [0.0.10](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.9...node-emulator-v0.0.10) (2022-10-20)


### Features

* **shell:** ShellProcess interface ([#72](https://github.com/codesandbox/browser-node-emulator/issues/72)) ([cdc0cf7](https://github.com/codesandbox/browser-node-emulator/commit/cdc0cf759f016ac5c923bb957caefd555ccaafab))

## [0.0.9](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.8...node-emulator-v0.0.9) (2022-10-18)


### Features

* **fs:** read / write files ([#60](https://github.com/codesandbox/browser-node-emulator/issues/60)) ([05c032d](https://github.com/codesandbox/browser-node-emulator/commit/05c032dbe33916faa563a858c67e464c9b03a9f6))
* **shell:** Allow custom commands ([#61](https://github.com/codesandbox/browser-node-emulator/issues/61)) ([c90890d](https://github.com/codesandbox/browser-node-emulator/commit/c90890db2e0f1c143221772ab76eacb3cafbe23f))

## [0.0.8](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.7...node-emulator-v0.0.8) (2022-10-17)


### Bug Fixes

* **NodeEmulator.ts:** export FilesMap type to consumer ([#57](https://github.com/codesandbox/browser-node-emulator/issues/57)) ([d676be5](https://github.com/codesandbox/browser-node-emulator/commit/d676be50f20f6d88bd7bbd6fa9edf3047e5fa8f2))

## [0.0.7](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.6...node-emulator-v0.0.7) (2022-10-14)


### Bug Fixes

* **preview:** remove conditional over listener ([#53](https://github.com/codesandbox/browser-node-emulator/issues/53)) ([5c6e8c0](https://github.com/codesandbox/browser-node-emulator/commit/5c6e8c0a0600a3b408f734a17b13a8f37ef8e09d))

## [0.0.6](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.5...node-emulator-v0.0.6) (2022-10-14)


### Bug Fixes

* **node-emulator:** trigger a new publish ([4b42c8f](https://github.com/codesandbox/browser-node-emulator/commit/4b42c8f43c8dea0491b48af067b07eb74922848f))

## [0.0.5](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.4...node-emulator-v0.0.5) (2022-10-14)


### Features

* **node emulator:** preview interface ([#41](https://github.com/codesandbox/browser-node-emulator/issues/41)) ([e7e66bb](https://github.com/codesandbox/browser-node-emulator/commit/e7e66bbaced7cf5eb20d14b58816e11737f9c3ed))

## [0.0.4](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.3...node-emulator-v0.0.4) (2022-10-11)


### Bug Fixes

* **node-emulator:** set build target to es2020 ([#38](https://github.com/codesandbox/browser-node-emulator/issues/38)) ([5ff50fc](https://github.com/codesandbox/browser-node-emulator/commit/5ff50fca586101b6270f5f587900a031466c024a))

## [0.0.3](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.2...node-emulator-v0.0.3) (2022-10-11)


### Bug Fixes

* **node-emulator:** trigger a new publish ([baef111](https://github.com/codesandbox/browser-node-emulator/commit/baef111bc1bd3bd34b5ff82fbeaa0a141372c417))

## [0.0.2](https://github.com/codesandbox/browser-node-emulator/compare/node-emulator-v0.0.1...node-emulator-v0.0.2) (2022-10-10)


### Bug Fixes

* remove handshake timeout log ([49413a6](https://github.com/codesandbox/browser-node-emulator/commit/49413a6dde5d8300e626298553fb09a9ce32cf4c))


================================================
FILE: packages/nodebox/LICENSE
================================================
Sustainable Use License

Version 1.0

Acceptance

By using the software, you agree to all of the terms and conditions below.

Copyright License

The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations below.

Limitations

You may use or modify the software only for your own internal business purposes or for non-commercial or personal use. You may distribute the software or provide it to others only if you do so free of charge for non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensor's trademarks is subject to applicable law.

Patents

The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.

Notices

You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms. If you modify the software, you must include in any modified copies of the software a prominent notice stating that you have modified the software.

No Other Rights

These terms do not imply any licenses other than those expressly granted in these terms.

Termination

If you use the software in violation of these terms, such use is not licensed, and your license will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your license will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your license to terminate automatically and permanently.

No Liability

As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.

Definitions

The "licensor" is CodeSandBox B.V.

The "software" is the software the licensor makes available under these terms, including any portion of it.

"You" refers to the individual or entity agreeing to these terms.

"Your company" is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.

"Your license" is the license granted to you for the software under these terms.

"Use" means anything you do with the software requiring your license.

"Trademark" means trademarks, service marks, and similar rights.

================================================
FILE: packages/nodebox/README.md
================================================
# Nodebox

Nodebox is a runtime for executing Node.js modules in the browser.

## Why we built Nodebox

With `sandpack-bundler`, we allowed any developer anywhere to instantly create a fast, local, shareable playground inside their browser, without having to wait forever to install dependencies and fight with devtools. This improves the learning, experimentation and sharing experience of client-side JavaScript code.

However, server-side JavaScript remained a challenge. At CodeSandbox we have solved this by using [Firecracker VMs](https://codesandbox.io/blog/how-we-clone-a-running-vm-in-2-seconds), allowing us to bring your entire development environment to the cloud regardless of the programming language or tooling you might be using. Unfortunately, as VMs live in the cloud, they require infrastructure and a network connection, resulting in a higher cost compared to our client-side sandboxes.

To solve this problem, we built Nodebox, a runtime that runs entirely in the browser, eliminating the need for a network connection and infrastructure.

Nodebox gives you the same user experience you have come to expect from Sandpack, which means a near-instant server-side JavaScript environment at the click of a button—built for experimentation, examples and documentation.

## The differences between a VM and Nodebox

As mentioned in the previous section, we solved server-side sandboxes in CodeSandbox by using Firecracker VMs. In this section, we'll explain the advantages and disadvantages of each approach.

### Advantages of VMs over Nodebox

- You get dedicated resources, with no resource limits enforced by the browser
- You have an entire Unix OS available
- You can run any language, database, command
- You can use network sockets
- You can run large and complex projects
- A perfect 1:1 environment as compared to your local setup (at least, if you're using a Unix-based system)
- No emulation, so Node.js would run exactly the same way as locally

### Advantages of Nodebox

- No need for any infrastructure
- No need for a network connection
- Instant feedback to any change
- Easy to get started
- Easy and instant reset - simply refresh the page/iframe
- Every page visitor gets their own Nodebox instance automatically

## What makes it different

Nodebox is currently the only cross-browser Node.js runtime supporting all the latest browsers:

- Chrome;
- Firefox;
- Safari \*

> - Support for iOS Safari is in beta

Nodebox does not emulate Node.js but is, instead, a Node.js-compatible runtime. This means that it implements as much of the Node.js API as possible while keeping a minimal performance imprint, using browser API where applicable and, in some cases, leaving out certain parts of Node.js due to browser [limitations](#Limitations) or complexity.

Nodebox uses an internal dependency manager that is fine-tuned to deliver optimal initial load time by utilizing dependency caching via [Sandpack CDN](https://github.com/codesandbox/sandpack-cdn). That CDN is an open-source Rust package manager that runs in the cloud and can be self-hosted pretty easily as well.

While there are alternatives to Nodebox, they are closer to mimicking a container-based environment, running commands step-by-step, or even the entire Linux distributive in your browser. That makes them slower and harder to use compared to Nodebox, which is optimized to run sandboxes fast and with as little friction as possible.

## Limitations

Unfortunately, any type of runtime that does not have access to operating system-level APIs will come with certain limitations. For Nodebox, those are the following:

- N-API modules
- net#Sockets pointing to external IPs
- Synchronous exec/spawn
- async_hooks (planned for implementation)
- Automatic process exiting - users now need to manually call `process.exit` before the process is exited (planned for implementation)

As we implement every module manually one by one, it is possible that some will not behave correctly. If this happens, feel free to open an issue here on GitHub and we'll make sure to fix it.

## Documentation

- [**Getting started**](#getting-started)
- [API documentation](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md)

---

## Getting started

Nodebox is meant for usage in your client-side applications, granting them the capability of running actual Node.js code directly in the browser. Here are a couple of examples of when Nodebox can be used:

- Building interactive examples for server-side code in your documentation;
- Showcasing a UI component library in the actual framework it's built for;
- Generally any evaluation of Node.js code and previewing it in the browser.

In the context of this tutorial, we will be working on a documentation website that illustrates different examples of using a Next.js application. Bear in mind that our documentation itself can be written in any framework of our choosing.

### Install

Nodebox can be installed from NPM just like any other dependency:

```sh
npm install @codesandbox/nodebox
```

### Setup

Nodebox consists of two main parts:

- A runtime environment evaluating the code;
- A preview environment serving the result of the evaluation.

Corresponding to these two parts, let's create two iframes in our application:

```html
<!--
  The "nodebox" iframe will mount the Nodebox runtime,
  allowing it to communicate with the rest of the application.
-->
<iframe id="nodebox-iframe"></iframe>

<!--
  The "preview" iframe will contain the result of running
  the Next.js example we will configure in a moment.
-->
<iframe id="preview-iframe"></iframe>
```

Although the runtime environment can be self-hosted, we will use the default one pointing to the deployed Nodebox instance on CodeSandbox servers. We do need, however, to specify an `iframe` reference in our application where Nodebox should render its preview.

```js
import { Nodebox } from '@codesandbox/nodebox';

const runtime = new Nodebox({
  // Provide a reference to the <iframe> element in the DOM
  // where Nodebox should render the preview.
  iframe: document.getElementById('nodebox-iframe'),
});

// Establish a connection with the runtime environment.
await runtime.connect();
```

> Learn more about the [Nodebox API](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md).

You want to establish **a single Nodebox instance** across your entire application. Bear that in mind during the setup phase and consult your framework's documentation and best practices regarding the most efficient way of achieving this.

Previews correspond to _commands_ executed in Nodebox, meaning that at this stage there will be no previews mounted at the given iframe because we haven't run any commands yet. Let's change that.

### Initialize file system

Much like your own project, the project you create in Nodebox needs files to work with. It can be a single JavaScript file or the entire project, like Astro or Next.js.

Let's describe a Next.js project that we need.

```js
// Populate the in-memory file system of Nodebox
// with a Next.js project files.
await runtime.fs.init({
  'package.json': JSON.stringify({
    name: 'nextjs-preview',
    dependencies: {
      '@next/swc-wasm-nodejs': '12.1.6',
      next: '12.1.6',
      react: '18.2.0',
      'react-dom': '18.2.0',
    },
  }),
  // On the index page, let's illustrate how server-side props
  // propagate to your page component in Next.js.
  'pages/index.jsx': `
export default function Homepage({ name }) {
  return (
    <div>
      <h1>Hello, {name}</h1>
      <p>The name "{name}" has been received from server-side props.</p>
    </div>
  )
}

export function getServerSideProps() {
  return {
    props: {
      name: 'John'
    }
  }
}
    `,
});
```

> You can reference standard Node.js modules, as well as external dependencies while writing your project files. Note that you **don't have to install** those dependencies as Nodebox will manage dependency installation, caching, and resolution automatically.

What we did above was outline a file system state of an actual Next.js project for Nodebox to run. The last step remaining is to run Next.js.

### Run project

To run the project, we will run the `npm dev` command using the Shell API provided by Nodebox.

```js
// First, create a new shell instance.
// You can use the same instance to spawn commands,
// observe stdio, restart and kill the process.
const shell = runtime.shell.create();

// Then, let's run the "dev" script that we've defined
// in "package.json" during the previous step.
const nextProcess = await shell.runCommand('npm', ['dev']);

// Find the preview by the process and mount it
// on the preview iframe on the page.
const previewInfo = await runtime.preview.getByShellId(nextProcess.id);
const previewIframe = document.getElementById('preview-iframe');
previewIframe.setAttribute('src', previewInfo.url);
```

> Note that you can treat `shell.runCommand` similar to `spawn` in Node.js. Learn more about the Shell API in the [documentation](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/api.md).

Once this command runs, it will return a shell reference we can use to retrieve the preview URL. By mounting that preview URL on our preview iframe from the setup, we can see the Next.js project running:

![](https://github.com/codesandbox/nodebox-runtime/blob/main/packages/nodebox/nextjs-preview.png)

That's it! 🎉 **Not a single server was spawned while running this Next.js application**. Everything was managed by Nodebox directly in your browser.

👉 Check out the [Sandbox for this tutorial](https://codesandbox.io/p/sandbox/nodebox-next-js-example-ji27x8).

================================================
FILE: packages/nodebox/api.md
================================================
# API

- [Class: `Nodebox`](#class-nodebox)
  - [`new Nodebox(options)`](#new-nodeboxurl-options)
  - [`nodebox.connect()`](#nodeboxconnect)
  - [`nodebox.fs`](#nodeboxfs)
  - [`nodebox.shell`](#nodeboxshell)
- [File system API](#file-system-api)
  - [`fs.init()`](#nodeboxfsinitfiles)
  - [`fs.readFile(path[, encoding])`](#nodeboxfsreadfilepath-encoding)
  - [`fs.writeFile(path[, content[, options]])`](#nodeboxfswritefilepath-content-options)
  - [`fs.mkdir(path[, options])`](#nodeboxfsmkdirpath-options)
  - [`fs.readdir(path)`](#nodeboxfsreaddirpath)
  - [`fs.stat(path)`](#nodeboxfsstatpath)
  - [`fs.rm(path[, options])`](#nodeboxfsrmpath-options)
  - [`fs.watch(glob, listener)`](#nodeboxfswatchglob-listener)
- [Shell API](#shell-api)
  - [`shell.create()`](#nodeboxshellcreate)
- [Class: `Shell`](#class-shell)
  - [`shell.runCommand(binary, args[, options])`](#shellruncommandbinary-args-options)
  - [`shell.on(event, listener)`](#shellonevent-listener)
  - [`shell.stdout.on(event, listener)`](#shellstdoutonevent-listener)
  - [`shell.stderr.on(event, listener)`](#shellstderronevent-listener)
  - [`shell.stdin.write(data)`](#shellstdinwritedata)
  - [`shell.kill()`](#shellkill)
- [Preview API](#preview-api)
  - [`preview.getByShellId(shellId[, timeout])`](#previewgetbyshellidshellid-timeout)
  - [`preview.waitForPort(port[, timeout])`](#previewwaitforportport-timeout)

## Class: `Nodebox`

A `Nodebox` is an interface to create and interact with a runtime evaluation context. It's responsible for attaching a _bridge frame_ and orchestrating events between the bridge and the _preview_ frames.

Nodebox connects to the provided deployed Nodebox runtime.

The `Nodebox` interface is available directly from the `@codesandbox/nodebox` package:

```js
import { Nodebox } from '@codesandbox/nodebox';
```

### `new Nodebox(options)`

- `options` `<Object>`
  - `runtimeUrl` `<string>` An absolute URL to the deployed Nodebox runtime.
  - `frame` `<HTMLFrameElement>` Reference to the `<iframe>` element on the page where the Nodebox should be mounted.

```js
import { Nodebox } from '@codesandbox/nodebox';

const nodebox = new Nodebox({
  iframe: document.getElementById('preview'),
});
```

### `nodebox.connect()`

Returns a Promise that resolves when a connection to the deployed Nodebox instance is established.

The connection must be awaited before operating with the Nodebox instance (e.g. writing files or creating shells).

```js
nodebox.connect().then(() => {
  console.log('Nodebox is ready!');
});
```

### `nodebox.fs`

A reference to the [File system API](#file-system-api).

```js
await nodebox.fs.init({
  'file.js': `console.log('Hello world')`,
});
```

### `nodebox.shell`

A reference to the [Shell API](#shell-api).

```js
const shell = nodebox.shell.create();
```

## File system API

### `nodebox.fs.init(files)`

- `files` `<Object>` A record of files and their content to write.
- Returns: `<Promise>` Fulfills when all the specified files are successfully written.

Writes given files to the in-memory file system managed by Nodebox.

```js
await nodebox.fs.init({
  'index.js': `
import { greet } from './greet'

greet('Hello world')
  `,

  'greet.js': `
export function greet(message) {
  console.log(message)
}
  `,
});
```

### `nodebox.fs.readFile(path[, encoding])`

- `path` `<string>`
- `encoding` `<string | BufferEncoding>`
- Returns: `<Promise>` Fulfills to either a `string` or `Uint8Array` depending on the `encoding` provided.

```js
const content = await nodebox.fs.readFile('./index.js', 'utf8');
// "console.log('Hello world')
```

### `nodebox.fs.writeFile(path[, content[, options]])`

- `path` `<string>`
- `content` `<string | Uint8Array>`
- `options` `<string | { encoding?: string, recursive?: boolean }>`
- Returns: `<Promise>` Fulfills when the file content is successfully written.

```js
await nodebox.fs.writeFile('./util.js', '');
```

### `nodebox.fs.mkdir(path[, options])`

- `path` `<string>`
- `options` `<{ recursive?: boolean }>`
- Returns: `<Promise>` Fulfills when the directory is successfully created.

```js
await nodebox.fs.mkdir('./a/b/c', { recursive: true });
```

### `nodebox.fs.readdir(path)`

- `path` `<string>`
- Returns: `<Promise<string[]>>` Fulfills with a list of files in the directory.

```js
await nodebox.fs.readdir('./a/b/c');
```

### `nodebox.fs.stat(path)`

- `path` `<string>`
- Returns: `<Promise<FileStats>>` Fulfills with the stats of the provided file.

```js
await nodebox.fs.stat('./index.js');
```

### `nodebox.fs.rm(path[, options])`

- `path` `<string>`
- `options` `<Object | undefined>`
  - `recursive` `<boolean | undefined>` remove all nested files/directories as well
  - `force` `<boolean | undefined>` don't throw if file/directory does not exist
- Returns: `<Promise<void>>` Fulfills with the stats of the provided file.

```js
await nodebox.fs.rm('./index.js', { recursive: true, force: true });
```

### `nodebox.fs.watch(glob, listener)`

- `glob` `<string>` A glob pattern of the files to watch.
- `listener` `<Function>` A listener to react to file watch events.
  - `event` `<FileWatchEvent>`
- Returns: `<Promise>` Fulfills to the control object with the following properties:
  - `dispose()` Removes the glob listener and stops watching the files.

Using the `listener` function, you can handle the following file watch events:

- `create`
  - `path` `<string>`
- `change`
  - `path` `<string>`
- `rename`
  - `newPath` `<string>`
  - `oldPath` `<string>`
- `remove`
  - `path` `<string>`

```js
// Watch all JavaScript files in the project.
const watcher = nodebox.fs.watch('**/*.js', (event) => {
  if (event.type === 'create') {
    console.log('A new file created!', event.path);
  }
});

// Stop watching the files.
watcher.dispose();
```

## Shell API

### `nodebox.shell.create()`

- Returns: `<Object>` A [Shell](#class-shell) instance.

Creates a new shell instance. Shell is used to run commands and control their execution.

```js
const shell = nodebox.shell.create();
```

## Class: `Shell`

### `shell.runCommand(binary, args[, options])`

- `binary` `<string>` Global name or a path to the binary.
- `args` `<Array>` List of arguments to pass to the commands.
- `options` `<Object>`
  - `cwd` `<string>` Path to use as the current working directory.
  - `env` `<Object>`

```js
await nodebox.fs.init({
  'index.js': `console.log(process.env.DB_URL)`,
});

const shell = nodebox.shell.create();
await shell.runCommand('node', ['index.js'], {
  env: {
    DB_URL: 'https://example.com',
  },
});
```

### `shell.on(event, listener)`

- `event` `<string>` Event type to listen to.
- `listener` `Function`

You can listen to the following events:

- `progress`
  - `status` `<WorkerStatusUpdate>`
- `exit`
  - `exitCode` `<number>`

```js
shell.on('exit', (exitCode) => {
  console.log(exitCode);
});
```

### `shell.stdout.on(event, listener)`

- `event` `<string>`
- `listener` `<Function>`

```js
shell.stdout.on('data', (data) => {
  console.log('Output:', data);
});
```

### `shell.stderr.on(event, listener)`

- `event` `<string>`
- `listener` `<Function>`

```js
shell.stderr.on('data', (data) => {
  console.log('Error:', data);
});
```

### `shell.stdin.write(data)`

- `data` `<string | Uint8Array>`

```js
shellProcess.stdin.write(data);
```

### `shell.kill()`

- Returns: `<Promise>` Fulfills when the shell successfully exits.

## Preview API

### `preview.getByShellId(shellId[, timeout])`

- `shellId` `<string>`
- `timeout` `<number>` Duration of the timeout window. _Default:_ `10_000` milliseconds.
- Returns: `<PreviewInfo>`

Get a preview info object for the preview opened by the given shell. If there's no preview found by the given shell within the `timeout` period, the function throws.

```ts
const previewInfo = await nodebox.preview.getByShellId('cjld2cjxh0000qzrmn831i7rn');
// {
//   "url": "https://t3rmni-3000.preview.csb.app/",
//   "sourceShellId": "cjld2cjxh0000qzrmn831i7rn",
//   "port": 3000
// }
```

### `preview.waitForPort(port[, timeout])`

- `port` `<number>`
- `timeout` `<number>` Duration of the timeout window. _Default:_ `10_000` milliseconds.
- Returns: `<Promise>` Fulfills with the preview info object.

Get a preview info object for the preview at the given port. If there's no preview found open at the given port within the `timeout` window, the function throws.

```js
const shell = await nodebox.shell.create();
await shell.runCommand('node', ['start:docs']);

// Await a preview at the specific port.
const previewInfo = await nodebox.preview.waitForPort(3004);
console.log(previewInfo);
// {
//   "url": "https://t3rmni-3004.preview.csb.app/",
//   "sourceShellId": "cjld2cjxh0000qzrmn831i7rn",
//   "port": 3004
// }
```


================================================
FILE: packages/nodebox/build.ts
================================================
import path from 'path';
import esbuild from 'esbuild';
import { spawnSync } from 'node:child_process';

const EXIT_TS_ERROR = Boolean(process.env.IS_PROD_BUILD || process.env.CI);

async function build() {
  const tscScriptOutput = spawnSync('tsc', ['-p', require.resolve('./tsconfig.build.json')], {
    stdio: 'inherit',
  });

  if (EXIT_TS_ERROR && tscScriptOutput?.status && tscScriptOutput.status > 0) {
    process.exit(tscScriptOutput.status);
  }

  await esbuild.build({
    entryPoints: [require.resolve('./src/index')],
    outdir: path.resolve(process.cwd(), './build'),
    format: 'cjs',
    target: 'es2020',
    platform: 'browser',
    bundle: true,
    minify: false,
  });

  await esbuild.build({
    entryPoints: [require.resolve('./src/index')],
    outdir: path.resolve(process.cwd(), './build'),
    format: 'esm',
    platform: 'browser',
    outExtension: { '.js': '.mjs' },
    bundle: true,
    minify: false,
  });
}

build();


================================================
FILE: packages/nodebox/package.json
================================================
{
  "name": "@codesandbox/nodebox",
  "version": "0.1.9",
  "description": "Public API of Nodebox",
  "main": "./build/index.js",
  "module": "./build/index.mjs",
  "typings": "./build/index.d.ts",
  "license": "SEE LICENSE IN ./LICENSE",
  "repository": {
    "type": "git",
    "url": "https://github.com/codesandbox/nodebox-runtime"
  },
  "exports": {
    ".": {
      "import": "./build/index.mjs",
      "require": "./build/index.js",
      "types": "./build/index.d.ts"
    }
  },
  "files": [
    "./build"
  ],
  "scripts": {
    "dev": "NODE_ENV=development pnpm build",
    "prebuild": "rimraf ./build",
    "build": "node -r esbuild-register ./build.ts"
  },
  "dependencies": {
    "outvariant": "^1.4.0",
    "strict-event-emitter": "^0.4.3"
  }
}


================================================
FILE: packages/nodebox/src/Nodebox.ts
================================================
import { invariant } from 'outvariant';
import { DeferredPromise } from '@open-draft/deferred-promise';
import { createDebug } from './logger';

import { MessageSender } from './messages';
import { FileSystemApi, FilesMap } from './modules/fs';
import type { FileWatchEvent } from './modules/fs';
import { ShellApi, ShellInfo, ShellProcess } from './modules/shell';
import { PreviewApi, PreviewInfo } from './modules/preview';

export type { ShellInfo, PreviewInfo, FilesMap, ShellProcess, FileWatchEvent };

const DEFAULT_RUNTIME_URL = 'https://nodebox-runtime.codesandbox.io';

export interface ChannelOptions {
  iframe: HTMLIFrameElement;

  /**
   * A custom Nodebox runtime URL
   */
  runtimeUrl?: string;

  /**
   * A custom Sandpack CDN URL.
   */
  cdnUrl?: string;
}

const debug = createDebug('emulator');

/**
 * Create a new Node emulator instance
 */
export class Nodebox {
  private channel: MessageSender = null as any;
  private isConnected: boolean;
  private url: string;

  /* API */
  private fileSystemApi: FileSystemApi = null as any;
  private shellApi: ShellApi = null as any;
  private previewApi: PreviewApi = null as any;

  constructor(private readonly options: ChannelOptions) {
    invariant(
      this.options.iframe,
      'Failed to create a Nodebox: expected "iframe" argument to be a reference to an <iframe> element but got %j',
      this.options.iframe
    );

    this.url = this.options.runtimeUrl || DEFAULT_RUNTIME_URL;

    this.isConnected = false;
  }

  /**
   * Connect to the deployed Node Emulator instance.
   */
  public async connect(): Promise<void> {
    const { iframe, cdnUrl } = this.options;

    debug('[message-sender]: Connecting to node emulator...');

    const connectionPromise = new DeferredPromise<void>();

    if (!this.url) {
      connectionPromise.reject(
        new Error('Nodebox URL is missing. Did you forget to provide it when creating this Nodebox instance?')
      );
    }

    invariant(
      iframe.contentWindow,
      'Failed to create a MessageChannel with the Nodebox iframe: no content window found'
    );

    // Establish a message channel with the worker frame
    // to communicate with the worker instance.
    this.channel = new MessageSender(iframe.contentWindow);

    // Connect to the emulator.
    const frameLoadPromise = new DeferredPromise<void>();
    iframe.setAttribute('src', this.url);
    iframe.addEventListener(
      'load',
      () => {
        frameLoadPromise.resolve();
      },
      { once: true }
    );
    iframe.addEventListener(
      'error',
      (event) => {
        frameLoadPromise.reject(event.error);
      },
      { once: true }
    );

    // Wait until the Emulator iframe is ready
    // before communicating with it.
    await frameLoadPromise;

    debug('[message-sender]: IFrame loaded...');

    // Await the worker frame to establish the receiver channel
    // and confirm the functioning message port via handshake.
    await this.channel.handshake();

    debug('[message-sender]: Handshake completed...');

    // Prompt a connection to the worker.
    this.channel.send('connect', {
      cdnUrl,
    });

    this.channel.on('runtime/ready', () => {
      connectionPromise.resolve();
    });

    return connectionPromise.then(() => {
      debug('[message-sender]: Connected to runtime...');
      this.isConnected = true;
    });
  }

  get fs(): FileSystemApi {
    invariant(
      this.isConnected,
      'Failed to access the File System API: consumer is not connected. Did you forget to run "connect()"?'
    );

    if (this.fileSystemApi) {
      return this.fileSystemApi;
    }

    this.fileSystemApi = new FileSystemApi(this.channel);
    return this.fileSystemApi;
  }

  get shell(): ShellApi {
    invariant(
      this.isConnected,
      'Failed to access the Shell API: consumer is not connected. Did you forget to run "connect()"?'
    );

    if (this.shellApi) {
      return this.shellApi;
    }

    this.shellApi = new ShellApi(this.channel);
    return this.shellApi;
  }

  get preview(): PreviewApi {
    invariant(
      this.isConnected,
      'Failed to access the Preview API: consumer is not connected. Did you forget to run "connect()"?'
    );

    if (this.previewApi) {
      return this.previewApi;
    }

    this.previewApi = new PreviewApi(this.channel);
    return this.previewApi;
  }
}


================================================
FILE: packages/nodebox/src/index.ts
================================================
export * from './messages';
export * from './Nodebox';
export * from './runtime-protocol.types';

export type { IFileStats } from './modules/fs';


================================================
FILE: packages/nodebox/src/logger.ts
================================================
/* eslint-disable no-console */
const FLAG = window.localStorage['CSB_EMULATOR_DEBUG'];

/**
 * Colors
 */
const DEFAULT = '\u001b[0m';
// Status
const GREEN = '\u001b[32;1m';
const RED = '\u001b[31m';
// Scopes
const BLUE = '\u001b[34m';
const YELLOW = '\u001b[33;1m';
const MAGENTA = '\u001b[35;1m';
const CYAN = '\u001b[36;1m';

type Scope = 'preview' | 'emulator' | 'runtime' | 'bridge' | 'runtime:worker';
const COLOR_SCOPE: Record<Scope, string> = {
  preview: YELLOW,
  emulator: MAGENTA,
  runtime: CYAN,
  bridge: BLUE,
  'runtime:worker': CYAN,
};

export function createDebug(scope: Scope) {
  return function debug(message: string, ...data: any[]) {
    if (FLAG === 'true') {
      const direction = () => {
        if (message.includes('sender')) return `${GREEN}sender`;
        if (message.includes('receiver')) return `${RED}receiver`;
        return '';
      };
      const cleanMessage = message.replace(/\[.+\]:/, '');
      console.debug(`${COLOR_SCOPE[scope]}${scope}:${direction()}${DEFAULT}:${cleanMessage}`, ...data);
    }
  };
}


================================================
FILE: packages/nodebox/src/messages.ts
================================================
/**
 * This is a message contract between the Consumer and the Worker (Emulator).
 * @see "consumer-worker-messages.md" in the documentation.
 */
import cuid from 'cuid';
import { invariant } from 'outvariant';
import { DeferredPromise } from '@open-draft/deferred-promise';
import type { FileSystemEvents } from './modules/fs';
import type { ShellEvents } from './modules/shell';
import type { PreviewInfo } from './modules/preview';
import type { PreviewEvents } from './modules/preview';
import { createDebug } from './logger';

const debug = createDebug('emulator');

export interface ConsumerEvents extends FileSystemEvents, ShellEvents, PreviewEvents {
  connect: {
    cdnUrl?: string | null;
  };
}

type WatcherEvent =
  | {
      type: 'create';
      path: string;
    }
  | {
      type: 'remove';
      path: string;
    }
  | {
      type: 'change';
      path: string;
    }
  | {
      type: 'rename';
      oldPath: string;
      newPath: string;
    }
  | {
      type: 'close';
    };

export type FSWatchEvent = WatcherEvent & {
  watcherId: string;
};

export type WorkerStatusUpdate =
  | {
      state: 'downloading_manifest';
    }
  | {
      state: 'downloaded_module';
      name: string;
      version: string;
      totalPending: number;
    }
  | {
      state: 'starting_command';
    }
  | {
      state: 'command_running';
    };

export interface WorkerEvents {
  'internal/handshake/done': void;
  'internal/operation/done': {
    operationId: string;
    listenerPayload: unknown;
  };
  'internal/operation/failed': {
    operationId: string;
    error: Error;
  };
  'runtime/ready': void;
  'worker/progress': {
    workerId?: string;
    status: WorkerStatusUpdate;
  };
  'worker/tty': {
    workerId: string;
    payload: {
      data: string;
      type: 'out' | 'err';
    };
  };
  'worker/exit': {
    workerId: string;
    exitCode: number;
    error?: {
      message: string;
    };
  };
  'preview/port/ready': PreviewInfo;
  'fs/watch-event': FSWatchEvent;
}

type OperationEvent<Payload> = Payload & {
  operationId: string;
};

type MaybePromise<T> = T | Promise<T>;

export class MessageReceiver {
  private emitter: EventTarget;
  private senderPort: MessagePort = null as any;

  constructor() {
    this.emitter = new EventTarget();
    this.waitForHandshake();
  }

  private waitForHandshake() {
    const handshakePromise = new DeferredPromise();

    const handshakeListener = (message: MessageEvent) => {
      const { data } = message;

      debug('[message-receiver]: incoming', message);

      if (data.type === 'internal/handshake') {
        invariant(
          message.ports.length > 0,
          'Failed to confirm a MessageReceiver handshake: received event has no ports'
        );

        this.senderPort = message.ports[0];
        this.addMessageListener();

        debug('[message-receiver]: handshake received!', this.senderPort);

        this.send('internal/handshake/done');
        debug('[message-receiver]: finish handshake');
      }
    };

    window.addEventListener('message', handshakeListener);
    handshakePromise.then(() => {
      window.removeEventListener('message', handshakeListener);
    });

    window.parent.postMessage({ type: 'internal/ready' }, '*');

    return handshakePromise;
  }

  private addMessageListener(): void {
    invariant(
      this.senderPort,
      '[MessageReceiver] Failed to add a message listener: sender port is not defined. Did you forget to await a handshake?'
    );

    this.senderPort.onmessage = (evt) => {
      const data = evt.data;
      if (data.type == null) {
        return;
      }

      this.emitter.dispatchEvent(
        new MessageEvent(data.type, {
          data: data.payload,
        })
      );
    };
  }

  public on<Event extends keyof ConsumerEvents & string>(
    event: Event,
    listener: (
      message: ConsumerEvents[Event] extends [infer PayloadType, infer _] ? PayloadType : ConsumerEvents[Event]
    ) => MaybePromise<ConsumerEvents[Event] extends [infer _, infer ReturnType] ? ReturnType | undefined : void>,
    options?: AddEventListenerOptions
  ): void {
    this.emitter.addEventListener(
      event,
      async (message) => {
        if (!(message instanceof MessageEvent)) {
          return;
        }

        // Send back the confirmation about the operation completion.
        const { operationId, payload } = message.data;

        try {
          const listenerPayload = await listener(payload);
          this.send('internal/operation/done', { operationId, listenerPayload });
        } catch (error) {
          if (error instanceof Error) {
            this.send('internal/operation/failed', { operationId, error });
          }
        }
      },
      options
    );
  }

  public send<Event extends keyof WorkerEvents & string>(
    event: Event,
    ...data: WorkerEvents[Event] extends Record<string, unknown> ? [WorkerEvents[Event]] : [undefined?]
  ): void {
    invariant(
      this.senderPort,
      '[MessageReceiver] Failed to send a message "%j": sender port is not defined. Did you forget to await a handshake?',
      event
    );

    const payload = data[0] || {};
    debug('[message-receiver]: send "%s"', event, payload);

    this.senderPort.postMessage({ type: event, payload });
  }
}

export class MessageSender {
  private emitter: EventTarget;
  private channel: MessageChannel;
  private receiverPort: MessagePort;
  private receiverReadyPromise: DeferredPromise<void>;

  constructor(private readonly target: Window) {
    this.emitter = new EventTarget();
    this.channel = new MessageChannel();
    this.receiverPort = this.channel.port1;

    const receiverReadyPromise = new DeferredPromise<void>();
    const handshakeListener = (message: MessageEvent) => {
      if (message.data.type === 'internal/ready') {
        debug('[message-sender]: runtime is ready');
        receiverReadyPromise.resolve();
      }
    };
    window.addEventListener('message', handshakeListener);
    receiverReadyPromise.then(() => {
      window.removeEventListener('message', handshakeListener);
    });
    this.receiverReadyPromise = receiverReadyPromise;

    // Attach a message listener once.
    this.receiverPort.onmessage = (evt) => {
      const data = evt.data;
      if (data.type != null) {
        debug('[message-sender]: emitting "%s" event...', data.type, data.payload);
        this.emitter.dispatchEvent(new MessageEvent(data.type, { data: data.payload }));
      }
    };
  }

  public async handshake(): Promise<void> {
    const handshakePromise = new DeferredPromise<void>();

    await this.receiverReadyPromise;

    debug('[message-sender]: sending handshake');
    this.target.postMessage(
      {
        type: 'internal/handshake',
      },
      '*',
      [this.channel.port2]
    );

    this.on('internal/handshake/done', () => {
      handshakePromise.resolve();
      clearTimeout(rejectionTimeout);
    });

    const rejectionTimeout = setTimeout(() => {
      handshakePromise.reject(new Error('MessageSender: Handshake timeout'));
    }, 5000);

    return handshakePromise;
  }

  public on<Event extends keyof WorkerEvents & string>(
    event: Event,
    listener: (message: MessageEvent<WorkerEvents[Event]>) => void,
    options?: AddEventListenerOptions
  ): void {
    debug('[message-sender]: add listener "%s"', event);

    this.emitter.addEventListener(
      event,
      (message) => {
        if (message instanceof MessageEvent) {
          listener(message);
        }
      },
      options
    );
  }

  public off<Event extends keyof WorkerEvents & string>(
    event: Event,
    listener: (message: MessageEvent<WorkerEvents[Event]>) => void,
    options?: AddEventListenerOptions
  ): void {
    this.emitter.removeEventListener(event, listener as EventListener, options);
  }

  public async send<Event extends keyof ConsumerEvents & string>(
    event: Event,
    ...data: ConsumerEvents[Event] extends [infer PayloadType, infer _]
      ? [PayloadType]
      : ConsumerEvents[Event] extends Record<string, unknown>
      ? [ConsumerEvents[Event]]
      : [undefined?]
  ): Promise<
    ConsumerEvents[Event] extends [infer _, infer ReturnType] ? OperationEvent<ReturnType> | undefined : void
  > {
    const operationPromise = new DeferredPromise<
      ConsumerEvents[Event] extends [infer _, infer ReturnType] ? OperationEvent<ReturnType> : void
    >();
    const operationId = cuid();

    const payload = data[0] || {};
    debug('[message-sender]: send "%s" (%s)', event, operationId, payload);

    this.receiverPort.postMessage({ type: event, payload: { operationId, payload } });

    // Await this operation to be confirmed as done by the receiver.
    debug('[message-sender]: adding done listener for "%s" (%s)', event, operationId);

    const handleOperationDone = (doneEvent: MessageEvent<WorkerEvents['internal/operation/done']>) => {
      const { data } = doneEvent;

      if (data.operationId === operationId) {
        const listenerPayload = (data.listenerPayload || {}) as ConsumerEvents[Event] extends [
          infer _,
          infer ReturnType
        ]
          ? OperationEvent<ReturnType>
          : void;

        debug('[message-sender]: resolving "%s (%s) promise!', event, operationId);

        operationPromise.resolve({
          ...listenerPayload,
          operationId: data.operationId,
        });
      }
    };

    const handleOperationFailed = (failEvent: MessageEvent<WorkerEvents['internal/operation/failed']>) => {
      const { data } = failEvent;

      if (data.operationId === operationId) {
        debug('[message-sender]: rejecting "%s (%s) promise!', event, operationId);

        operationPromise.reject(data.error);
      }
    };

    this.on('internal/operation/done', handleOperationDone);

    // Handle exceptions from the receiver.
    this.on('internal/operation/failed', handleOperationFailed);

    return operationPromise.finally(() => {
      // Clean up all the listeners for this particular operation.
      // Each operation has its own unique ID, so we can safely remove all the listeners for this operation.
      this.emitter.removeEventListener('internal/operation/done', handleOperationDone as EventListener);
      this.emitter.removeEventListener('internal/operation/failed', handleOperationFailed as EventListener);
    });
  }
}


================================================
FILE: packages/nodebox/src/modules/fs.ts
================================================
import cuid from 'cuid';
import { format } from 'outvariant';
import type { MessageSender, FSWatchEvent } from '../messages';

type FSEncoding = BufferEncoding | 'buffer';

export type FileContent = Uint8Array | string;

export interface FilesMap {
  [filePath: string]: FileContent;
}

export interface FileWatchOptions {
  recursive?: boolean;
}

export type FileWatchEvent = Omit<FSWatchEvent, 'watcherId'>;

export interface IFileStats {
  type: 'dir' | 'file' | 'link';
  size: number;
  ino: number;
  atimeMs: number;
  mtimeMs: number;
  ctimeMs: number;
  blocks: number;
  mode: number;
}

export interface FileSystemEvents {
  'fs/init': {
    files: FilesMap;
  };

  'fs/readFile':
    | [{ path: string; encoding?: undefined }, { data: Uint8Array }]
    | [{ path: string; encoding?: 'buffer' }, { data: Uint8Array }]
    | [{ path: string; encoding?: FSEncoding }, { data: string | FileContent }];

  'fs/writeFile': {
    path: string;
    content: FileContent;
    encoding?: BufferEncoding;
    recursive?: boolean;
  };

  'fs/readdir': [
    {
      path: string;
    },
    { data: string[] }
  ];

  'fs/stat': [
    {
      path: string;
    },
    { data: IFileStats }
  ];

  'fs/mkdir': {
    path: string;
    recursive?: boolean;
  };

  'fs/rm': {
    path: string;
    force?: boolean;
    recursive?: boolean;
  };

  'fs/watch': {
    watcherId: string;
    includes: string[];
    excludes: string[];
  };

  'fs/unwatch': {
    watcherId: string;
  };
}

type WriteFileOptions = BufferEncoding | { encoding?: BufferEncoding; recursive?: boolean };

export class FileSystemApi {
  constructor(private readonly channel: MessageSender) {}

  /**
   * Initialize the File System worker with the files.
   */
  public async init(files: FilesMap): Promise<void> {
    // Await the sent event to know when the worker
    // is done writing the files.
    await this.channel.send('fs/init', { files });
  }

  /**
   * Read a file at the given path.
   */
  public async readFile(path: string, encoding?: undefined): Promise<Uint8Array>;
  public async readFile(path: string, encoding: 'buffer'): Promise<Uint8Array>;
  public async readFile(path: string, encoding: BufferEncoding): Promise<string>;

  public async readFile(path: string, encoding?: FSEncoding): Promise<FileContent> {
    const response = await this.channel.send('fs/readFile', { path, encoding }).catch((error) => {
      throw new Error(format('Failed to read file at path "%s"', path), { cause: error });
    });
    if (!response) {
      throw new Error('File not found');
    }
    return response.data;
  }

  /**
   * Write a file at the given path.
   * Replaces the file content if the file already exists.
   */
  public async writeFile(path: string, content: FileContent): Promise<void>;
  public async writeFile(path: string, content: FileContent, options: WriteFileOptions): Promise<void>;

  public async writeFile(path: string, content: FileContent, options?: WriteFileOptions): Promise<void> {
    let encoding = undefined;
    let recursive = false;

    if (typeof options === 'object') {
      encoding = options.encoding;
      recursive = !!options.recursive;
    } else if (typeof options === 'string') {
      encoding = options;
    }

    await this.channel.send('fs/writeFile', { path, content, encoding, recursive }).catch((error) => {
      throw new Error(format('Failed to write file at path "%s"', path), { cause: error });
    });
  }

  public async readdir(path: string): Promise<string[]> {
    const response = await this.channel.send('fs/readdir', { path }).catch((error) => {
      throw new Error(format('Failed to read directory at path "%s"', path), { cause: error });
    });
    if (!response) {
      throw new Error('Directory not found');
    }
    return response.data;
  }

  public async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {
    const recursive = !!options?.recursive;
    await this.channel.send('fs/mkdir', { path, recursive }).catch((error) => {
      throw new Error(format('Failed to make directory at path "%s"', path), { cause: error });
    });
  }

  public async stat(path: string): Promise<IFileStats> {
    const response = await this.channel.send('fs/stat', { path }).catch((error) => {
      throw new Error(format('Failed to stat file at path "%s"', path), { cause: error });
    });
    if (!response) {
      throw new Error('File not found');
    }
    return response.data;
  }

  public async rm(path: string, options?: { force?: boolean; recursive?: boolean }): Promise<void> {
    const { force, recursive } = options || {};
    await this.channel.send('fs/rm', { path, force, recursive }).catch((error) => {
      throw new Error(format('Failed to remove file at path "%s"', path), { cause: error });
    });
  }

  /**
   * Subscribe to changes at the given file or directory.
   */
  public async watch(
    includes: string[],
    excludes: string[],
    listener?: (evt?: FileWatchEvent) => void
  ): Promise<{ dispose: () => Promise<void> }> {
    const watcherId = cuid();

    await this.channel.send('fs/watch', { watcherId, includes, excludes });

    this.channel.on('fs/watch-event', ({ data }) => {
      if (data.watcherId === watcherId && listener) {
        const evt = { ...data } as FSWatchEvent;
        // @ts-ignore
        delete evt.watcherId;
        listener(evt);
      }
    });

    return {
      dispose: () => this.channel.send('fs/unwatch', { watcherId }),
    };
  }
}


================================================
FILE: packages/nodebox/src/modules/preview.ts
================================================
import { format } from 'outvariant';
import { DeferredPromise } from '@open-draft/deferred-promise';
import type { MessageSender } from '../messages';

export interface PreviewEvents {
  'preview/get/info': [
    {
      port?: number;
      sourceShellId?: string;
    },
    PreviewInfo
  ];
}

const TIMEOUT = 20_000;

export type PreviewInfo = {
  url: string;
  sourceShellId: string;
  port: number;
};

export class PreviewApi {
  constructor(private readonly channel: MessageSender) {}

  private async waitFor(
    payload: { sourceShellId?: string; port?: number },
    predicate: (data: PreviewInfo) => boolean,
    timeout = TIMEOUT
  ): Promise<PreviewInfo> {
    const readyPromise = new DeferredPromise<PreviewInfo>();

    const rejectTimeout = setTimeout(() => {
      readyPromise.reject();
    }, timeout);

    // Look up for the informaton on PreviewManager
    const previewInformation = await this.channel.send('preview/get/info', payload).catch((error) => {
      readyPromise.reject(
        new Error(
          format(
            'Failed to look up preview information for shell ID "%s" (port: %d)',
            payload.sourceShellId,
            payload.port
          )
        )
      );
    });

    const foundPreview = previewInformation && predicate(previewInformation);

    if (foundPreview) {
      readyPromise.resolve({
        url: previewInformation.url,
        port: previewInformation.port,
        sourceShellId: previewInformation.sourceShellId,
      });
    }

    // Response from PreviewManager
    this.channel.on('preview/port/ready', ({ data }) => {
      // Avoid resolve the promise once again
      if (!foundPreview && predicate(data)) {
        readyPromise.resolve({
          url: data.url,
          port: data.port,
          sourceShellId: data.sourceShellId,
        });
      }
    });

    return readyPromise.finally(() => {
      clearTimeout(rejectTimeout);
    });
  }

  public async getByShellId(sourceShellId: string, timeout?: number): Promise<PreviewInfo> {
    return this.waitFor({ sourceShellId }, (data) => data.sourceShellId === sourceShellId, timeout).catch((error) => {
      throw new Error(format('Failed to get shell by ID "%s"', sourceShellId), { cause: error });
    });
  }

  public async waitForPort(port: number, timeout?: number): Promise<PreviewInfo> {
    return this.waitFor({ port }, (data) => data.port === port, timeout).catch((error) => {
      throw new Error(format('Failed to await port %d', port), { cause: error });
    });
  }
}


================================================
FILE: packages/nodebox/src/modules/shell.ts
================================================
import { format, invariant } from 'outvariant';
import { Emitter } from 'strict-event-emitter';
import type { MessageSender, WorkerStatusUpdate } from '../messages';

export interface ShellEvents {
  'shell/runCommand': [
    {
      command: string;
      args: Array<string>;
      options: ShellCommandOptions;
    },
    ShellInfo
  ];
  'shell/exit': ShellInfo;
  'shell/stdin': { data: string | Uint8Array; workerId: string };
}

export interface ShellCommandOptions {
  cwd?: string;
  env?: Record<string, string>;
}

export type ShellInfo = {
  id: string;
};

export class ShellApi {
  constructor(private readonly channel: MessageSender) {}

  public create(): ShellProcess {
    return new ShellProcess(this.channel);
  }
}

export class ShellProcess {
  public id?: string;
  public state: 'running' | 'idle';

  public stdout: Emitter<{
    data: [string];
  }>;
  public stderr: Emitter<{
    data: [string];
  }>;
  public stdin: {
    write: (data: string | Uint8Array) => Promise<void>;
  };

  constructor(private readonly channel: MessageSender) {
    this.state = 'running';
    this.stdout = new Emitter();
    this.stderr = new Emitter();
    this.stdin = {
      write: (data: string | Uint8Array): Promise<void> => {
        if (!this.id) {
          throw new Error('Failed to write to stdin, no process is currently running');
        }

        return this.channel.send('shell/stdin', { data: data, workerId: this.id });
      },
    };

    this.forwardStdEvents();
  }

  private forwardStdEvents(): void {
    this.channel.on('worker/tty', (message) => {
      const { data } = message;

      if (data.workerId !== this.id) {
        return;
      }

      switch (data.payload.type) {
        case 'out': {
          this.stdout.emit('data', data.payload.data);
          break;
        }

        case 'err': {
          this.stderr.emit('data', data.payload.data);
          break;
        }
      }
    });
  }

  /**
   * Evaluates a given module in the File
   */
  public async runCommand(command: string, args: Array<string>, options: ShellCommandOptions = {}): Promise<ShellInfo> {
    invariant(!this.id, 'Failed to run "runCommand" on a ShellProcess: there is already a process running.');

    const shellInfo = await this.channel.send('shell/runCommand', { command, args, options });

    invariant(shellInfo, 'Failed to run "runCommand" on a ShellProcess: was not able to retrieve a running process.');

    this.id = shellInfo.id;
    this.state = 'running';

    return shellInfo;
  }

  public async on(message: 'exit', listener: (exitCode: number, error?: { message: string }) => void): Promise<void>;
  public async on(message: 'progress', listener: (status: WorkerStatusUpdate) => void): Promise<void>;

  public async on(message: 'exit' | 'progress' | 'error', listener: any): Promise<void> {
    switch (message) {
      case 'progress': {
        this.channel.on('worker/progress', ({ data }) => {
          listener(data.status);
        });
        return;
      }

      case 'exit': {
        this.channel.on('worker/exit', ({ data }) => {
          if (data.workerId === this.id) {
            listener(data.exitCode, data.error);
          }
        });
        return;
      }
    }
  }

  /**
   * Terminates the shell process.
   */
  public async kill(): Promise<void> {
    invariant(
      this.id,
      'Failed to run "kill" on a ShellProcess: there is no process running. Did you forget to run it?'
    );

    /**
     * @note Optimistically (and eagerly) transition the shell to the next state.
     * Shell exit only fails on protocol mismatch or when it's already been killed.
     */
    this.state = 'idle';

    /**
     * @todo I wonder if we should support a custom "exitCode" here
     * or a signal.
     */
    await this.channel.send('shell/exit', { id: this.id }).catch((error) => {
      throw new Error(format('Failed to kill shell with ID "%s"', this.id), { cause: error });
    });

    this.id = undefined;
  }
}


================================================
FILE: packages/nodebox/src/runtime-protocol.types.ts
================================================
export const INJECT_MESSAGE_TYPE = 'INJECT_AND_INVOKE';
export const PREVIEW_LOADED_MESSAGE_TYPE = 'PREVIEW_LOADED';

export interface Message {
  type: string;
}

type BaseScope = Record<string, unknown>;

export interface InjectMessage<Scope = BaseScope> {
  uid: string;

  type: typeof INJECT_MESSAGE_TYPE;
  /* A stringified function that will be called inside the iFrame. */
  code: string;
  /* The scope that will be passed to the injected code, as `options.scope`. */
  scope: Scope;
}


================================================
FILE: packages/nodebox/tsconfig.build.json
================================================
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "rootDir": "./src",
    "emitDeclarationOnly": true,
    "declaration": true,
    "declarationDir": "./build"
  },
  "include": ["src"]
}


================================================
FILE: packages/nodebox/tsconfig.json
================================================
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "noEmit": true
  },
  "include": ["../../internals", "**/*.ts"]
}


================================================
FILE: packages/utils/jest.config.js
================================================
module.exports = {
  preset: 'ts-jest',
};


================================================
FILE: packages/utils/package.json
================================================
{
  "name": "internal-utils",
  "version": "0.0.0",
  "scripts": {
    "test:unit": "jest"
  }
}


================================================
FILE: packages/utils/withTimeout.test.ts
================================================
import { DeferredPromise } from '@open-draft/deferred-promise';
import { withTimeout } from './withTimeout';

it('rejects a pending promise if it exceeds the timeout', async () => {
  const promise = new DeferredPromise<void>();
  withTimeout(promise, 200);

  const rejectionError = new Error(`DeferredPromise hasn't settled within 200ms`);

  await expect(promise).rejects.toThrowError(rejectionError);
  expect(promise.state).toBe('rejected');
  expect(promise.rejectionReason).toEqual(rejectionError);
});

it('rejects a pending promise that resolves post-timeout', async () => {
  const promise = new DeferredPromise<number>();
  withTimeout(promise, 200);
  setTimeout(() => promise.resolve(123), 510);

  const rejectionError = new Error(`DeferredPromise hasn't settled within 200ms`);

  await expect(promise).rejects.toThrowError(rejectionError);
  expect(promise.state).toBe('rejected');
  expect(promise.rejectionReason).toEqual(rejectionError);
});

it('rejects a pending promise that rejects post-timeout', async () => {
  const promise = new DeferredPromise<void>();
  withTimeout(promise, 200);
  setTimeout(() => promise.reject('reason'), 250);

  const rejectionError = new Error(`DeferredPromise hasn't settled within 200ms`);

  await expect(promise).rejects.toThrowError(rejectionError);
  expect(promise.state).toBe('rejected');
  expect(promise.rejectionReason).toEqual(rejectionError);
});

it('does not reject a promise that resolves within the timeout', async () => {
  const promise = new DeferredPromise<number>();
  withTimeout(promise, 200);
  setTimeout(() => promise.resolve(123), 100);

  expect(await promise).toBe(123);
  expect(promise.state).toBe('fulfilled');

  expect(await promise).toBe(123);
  expect(promise.state).toBe('fulfilled');
  expect(promise.rejectionReason).toBeUndefined();
});

it('does not reject a promise that rejects within the timeout', async () => {
  const promise = new DeferredPromise<number>();
  withTimeout(promise, 200);
  setTimeout(() => promise.reject('reason'), 100);

  await expect(promise).rejects.toBe('reason');
  expect(promise.state).toBe('rejected');
  expect(promise.rejectionReason).toBe('reason');
});


================================================
FILE: packages/utils/withTimeout.ts
================================================
import { DeferredPromise } from '@open-draft/deferred-promise';

/**
 * Rejects a given `DeferredPromise` if it doesn't settle within
 * the timeout duration.
 */
export function withTimeout(promise: DeferredPromise<any>, duration: number): void {
  const timeout = setTimeout(() => {
    // Prevent the timeout rejection if the Promise has already been settled.
    // Rejecting a Promise multiple times is also a no-op, and it'd throw.
    if (promise.state === 'pending') {
      promise.reject(new Error(`DeferredPromise hasn't settled within ${duration}ms`));
    }
  }, duration);

  const cancelTimeout = () => clearTimeout(timeout);
  promise.then(cancelTimeout, cancelTimeout);
}


================================================
FILE: playwright.config.ts
================================================
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';

const config: PlaywrightTestConfig = {
  testDir: './tests',
  globalSetup: require.resolve('./tests/setup/globalSetup'),
  workers: 1,
  reporter: process.env.CI ? 'github' : undefined,
  use: {
    browserName: 'chromium',
    channel: 'chrome',
    ignoreHTTPSErrors: true,
    launchOptions: {
      args: [
        '--allow-insecure-localhost',
        '--ignore-certificate-errors',
        /**
         * @note Setting this feature flag prevents "SharedArrayBuffer is not defined"
         * for insecure hosts.
         */
        '--enable-features=SharedArrayBuffer',
        '--unsafely-treat-insecure-origin-as-secure=https://localhost',
      ],
      devtools: true,
    },
    screenshot: 'only-on-failure',
  },
  projects: process.env.CI
    ? [
        { name: 'chromium', use: devices['Desktop Chrome'] },
        { name: 'firefox', use: devices['Desktop Firefox'] },
        { name: 'webkit', use: devices['Desktop Safari'] },
      ]
    : [],
  forbidOnly: !!process.env.CI,
};

export default config;


================================================
FILE: pnpm-workspace.yaml
================================================
packages:
  - ./packages/*


================================================
FILE: release-please-config.json
================================================
{
  "packages": {
    "packages/nodebox": {
      "release-type": "node",
      "bump-minor-pre-major": true,
      "bump-patch-for-minor-pre-major": true
    }
  }
}


================================================
FILE: req.conf
================================================
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
# C = US
# ST = California
# L = Los Angeles
# O = Internet Corporation for Assigned Names and Numbers
# OU = IT Operations
CN = csb.test

[v3_req]
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = csb.test
DNS.2 = *.csb.test
IP.1 = 127.0.0.1


================================================
FILE: sync-repo.js
================================================
const fs = require("fs");
const path = require("path");

console.log('Syncing private repo to this public repo...');

const publicEntries = fs.readdirSync(__dirname);
for (const entry of publicEntries) {
  // Skip git content
  if (entry === ".git" || entry === ".github" || entry === "sync-repo.js") {
    continue;
  }
  
  console.log('Cleaning up public repo:', entry);
  fs.rmSync(path.join(__dirname, entry), {
    recursive: true,
  });
}

const privateNodeboxRoot = path.join(__dirname, "../nodebox");
const privateEntries = fs.readdirSync(privateNodeboxRoot);
for (const entry of privateEntries) {
  // Skip git content
  if (entry === ".git" || entry === ".github" || entry === "sync-repo.js" || entry === "node_modules") {
    continue;
  }

  console.log('Copying to public repo:', entry);
  fs.cpSync(path.join(privateNodeboxRoot, entry), path.join(__dirname, entry), {
    recursive: true,
    force: true,
  });
}

console.log('Removing internal/closed-source code...');
const INTERNAL_ENTRIES = ['packages/runtime', 'documentation'];
for (const entry of INTERNAL_ENTRIES) {
  fs.rmSync(path.join(__dirname, entry), {
    recursive: true,
  });
}

console.log('Sync completed! :D');


================================================
FILE: tests/cdn-proxy/v2/deps/ZXNidWlsZC13YXNtQDAuMTcuMTI7dml0ZUA0LjIuMA==
================================================
esbuild-wasm@00.17.12esbuild@00.17.9function-bind@11.1.1has@11.0.3is-core-module@22.9.0nanoid@33.3.4path-parse@11.0.7picocolors@11.0.0postcss@88.4.21resolve@11.22.1rollup@33.20.0source-map-js@11.0.2!supports-preserve-symlinks-flag@11.0.0vite@44.2.0

================================================
FILE: tests/cdn-proxy/v2/deps/bm9kZS1mZXRjaEAzLjMuMA==
================================================
data-uri-to-buffer@44.0.1fetch-blob@33.2.0formdata-polyfill@44.0.10node-domexception@11.0.0node-fetch@33.3.0web-streams-polyfill@33.2.1

================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi10aXRsZUAwLjExLjI=
================================================
/dist/index.cjs'use strict';

const shared = require('@mdit-vue/shared');

const titlePlugin = (md) => {
  const render = md.renderer.render.bind(md.renderer);
  md.renderer.render = (tokens, options, env) => {
    const tokenIdx = tokens.findIndex((token) => token.tag === "h1");
    env.title = tokenIdx > -1 ? shared.resolveTitleFromToken(tokens[tokenIdx + 1], {
      shouldAllowHtml: false,
      shouldEscapeText: false
    }) : "";
    return render(tokens, options, env);
  };
};

exports.titlePlugin = titlePlugin;
/README.mdC# @mdit-vue/plugin-title

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-title)](https://www.npmjs.com/package/@mdit-vue/plugin-title)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to get page title.

- Extracts title (the content of the first level-1 heading) into markdown-it `env.title`.

## Install

```sh
npm i @mdit-vue/plugin-title
```

## Usage

```ts
import MarkdownIt from 'markdown-it';
import { titlePlugin } from '@mdit-vue/plugin-title';
import type { MarkdownItEnv } from '@mdit-vue/types';

const md = MarkdownIt({ html: true }).use(titlePlugin);
const env: MarkdownItEnv = {};

const rendered = md.render(
  `\
# h1
## h2
### h3
`,
  env,
);

console.log(env.title);
```
/dist/index.mjsimport { resolveTitleFromToken } from '@mdit-vue/shared';

const titlePlugin = (md) => {
  const render = md.renderer.render.bind(md.renderer);
  md.renderer.render = (tokens, options, env) => {
    const tokenIdx = tokens.findIndex((token) => token.tag === "h1");
    env.title = tokenIdx > -1 ? resolveTitleFromToken(tokens[tokenIdx + 1], {
      shouldAllowHtml: false,
      shouldEscapeText: false
    }) : "";
    return render(tokens, options, env);
  };
};

export { titlePlugin };
/package.json{
  "name": "@mdit-vue/plugin-title",
  "version": "0.11.2",
  "description": "A markdown-it plugin to get markdown page title",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "title"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@mdit-vue/shared": "0.11.2",
    "@mdit-vue/types": "0.11.0",
    "@types/markdown-it": "^12.2.3",
    "markdown-it": "^13.0.1"
  },
  "devDependencies": {
    "@types/markdown-it-emoji": "^2.0.2",
    "markdown-it-emoji": "^2.0.2"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "676ec4ca8704d709e7a47f7f6d41ff3f70dc2356"
}
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/dist/index.d.tspimport MarkdownIt from 'markdown-it';

/**
 * Get markdown page title info
 *
 * Extract it into env
 */
declare const titlePlugin: MarkdownIt.PluginSimple;

declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The title that extracted by `@mdit-vue/plugin-title`
         */
        title?: string;
    }
}

export { titlePlugin };


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi10b2NAMC4xMS4y
================================================
/dist/index.cjs'use strict';

const shared = require('@mdit-vue/shared');

const createRenderHeaders = ({
  listTag,
  listClass,
  itemClass,
  linkTag,
  linkClass
}) => {
  const listTagString = shared.htmlEscape(listTag);
  const listClassString = listClass ? ` class="${shared.htmlEscape(listClass)}"` : "";
  const itemTagString = "li";
  const itemClassString = itemClass ? ` class="${shared.htmlEscape(itemClass)}"` : "";
  const linkTagString = shared.htmlEscape(linkTag);
  const linkClassString = linkClass ? ` class="${shared.htmlEscape(linkClass)}"` : "";
  const linkTo = (link) => linkTag === "router-link" ? ` to="${link}"` : ` href="${link}"`;
  const renderHeaders = (headers) => `<${listTagString}${listClassString}>${headers.map(
    (header) => `<${itemTagString}${itemClassString}${itemClassString}><${linkTagString}${linkClassString}${linkTo(header.link)}>${header.title}</${linkTagString}>${header.children.length > 0 ? renderHeaders(header.children) : ""}</${itemTagString}>`
  ).join("")}</${listTagString}>`;
  return renderHeaders;
};

const createTocBlockRule = ({
  pattern,
  containerTag,
  containerClass
}) => {
  return (state, startLine, endLine, silent) => {
    if (state.sCount[startLine] - state.blkIndent >= 4) {
      return false;
    }
    const pos = state.bMarks[startLine] + state.tShift[startLine];
    const max = state.eMarks[startLine];
    const lineFirstToken = state.src.slice(pos, max).split(" ")[0];
    if (!pattern.test(lineFirstToken))
      return false;
    if (silent)
      return true;
    state.line = startLine + 1;
    const tokenOpen = state.push("toc_open", containerTag, 1);
    tokenOpen.markup = "";
    tokenOpen.map = [startLine, state.line];
    if (containerClass) {
      tokenOpen.attrSet("class", containerClass);
    }
    const tokenBody = state.push("toc_body", "", 0);
    tokenBody.markup = lineFirstToken;
    tokenBody.map = [startLine, state.line];
    tokenBody.hidden = true;
    const tokenClose = state.push("toc_close", containerTag, -1);
    tokenClose.markup = "";
    tokenBody.map = [startLine, state.line];
    return true;
  };
};

const tocPlugin = (md, {
  pattern = /^\[\[toc\]\]$/i,
  slugify = shared.slugify,
  format,
  level = [2, 3],
  containerTag = "nav",
  containerClass = "table-of-contents",
  listTag = "ul",
  listClass = "",
  itemClass = "",
  linkTag = "a",
  linkClass = ""
} = {}) => {
  md.block.ruler.before(
    "heading",
    "toc",
    createTocBlockRule({
      pattern,
      containerTag,
      containerClass
    }),
    {
      alt: ["paragraph", "reference", "blockquote"]
    }
  );
  const renderHeaders = createRenderHeaders({
    listTag,
    listClass,
    itemClass,
    linkTag,
    linkClass
  });
  md.renderer.rules.toc_body = (tokens) => renderHeaders(
    shared.resolveHeadersFromTokens(tokens, {
      level,
      shouldAllowHtml: true,
      shouldEscapeText: true,
      slugify,
      format
    })
  );
};

exports.createRenderHeaders = createRenderHeaders;
exports.createTocBlockRule = createTocBlockRule;
exports.tocPlugin = tocPlugin;
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/dist/index.mjsimport { htmlEscape, resolveHeadersFromTokens, slugify } from '@mdit-vue/shared';

const createRenderHeaders = ({
  listTag,
  listClass,
  itemClass,
  linkTag,
  linkClass
}) => {
  const listTagString = htmlEscape(listTag);
  const listClassString = listClass ? ` class="${htmlEscape(listClass)}"` : "";
  const itemTagString = "li";
  const itemClassString = itemClass ? ` class="${htmlEscape(itemClass)}"` : "";
  const linkTagString = htmlEscape(linkTag);
  const linkClassString = linkClass ? ` class="${htmlEscape(linkClass)}"` : "";
  const linkTo = (link) => linkTag === "router-link" ? ` to="${link}"` : ` href="${link}"`;
  const renderHeaders = (headers) => `<${listTagString}${listClassString}>${headers.map(
    (header) => `<${itemTagString}${itemClassString}${itemClassString}><${linkTagString}${linkClassString}${linkTo(header.link)}>${header.title}</${linkTagString}>${header.children.length > 0 ? renderHeaders(header.children) : ""}</${itemTagString}>`
  ).join("")}</${listTagString}>`;
  return renderHeaders;
};

const createTocBlockRule = ({
  pattern,
  containerTag,
  containerClass
}) => {
  return (state, startLine, endLine, silent) => {
    if (state.sCount[startLine] - state.blkIndent >= 4) {
      return false;
    }
    const pos = state.bMarks[startLine] + state.tShift[startLine];
    const max = state.eMarks[startLine];
    const lineFirstToken = state.src.slice(pos, max).split(" ")[0];
    if (!pattern.test(lineFirstToken))
      return false;
    if (silent)
      return true;
    state.line = startLine + 1;
    const tokenOpen = state.push("toc_open", containerTag, 1);
    tokenOpen.markup = "";
    tokenOpen.map = [startLine, state.line];
    if (containerClass) {
      tokenOpen.attrSet("class", containerClass);
    }
    const tokenBody = state.push("toc_body", "", 0);
    tokenBody.markup = lineFirstToken;
    tokenBody.map = [startLine, state.line];
    tokenBody.hidden = true;
    const tokenClose = state.push("toc_close", containerTag, -1);
    tokenClose.markup = "";
    tokenBody.map = [startLine, state.line];
    return true;
  };
};

const tocPlugin = (md, {
  pattern = /^\[\[toc\]\]$/i,
  slugify: slugify$1 = slugify,
  format,
  level = [2, 3],
  containerTag = "nav",
  containerClass = "table-of-contents",
  listTag = "ul",
  listClass = "",
  itemClass = "",
  linkTag = "a",
  linkClass = ""
} = {}) => {
  md.block.ruler.before(
    "heading",
    "toc",
    createTocBlockRule({
      pattern,
      containerTag,
      containerClass
    }),
    {
      alt: ["paragraph", "reference", "blockquote"]
    }
  );
  const renderHeaders = createRenderHeaders({
    listTag,
    listClass,
    itemClass,
    linkTag,
    linkClass
  });
  md.renderer.rules.toc_body = (tokens) => renderHeaders(
    resolveHeadersFromTokens(tokens, {
      level,
      shouldAllowHtml: true,
      shouldEscapeText: true,
      slugify: slugify$1,
      format
    })
  );
};

export { createRenderHeaders, createTocBlockRule, tocPlugin };
/dist/index.d.ts
import { MarkdownItHeader } from '@mdit-vue/types';
import ParserBlock from 'markdown-it/lib/parser_block.js';
import MarkdownIt from 'markdown-it';

/**
 * Options of @mdit-vue/plugin-toc
 */
interface TocPluginOptions {
    /**
     * The pattern serving as the TOC placeholder in your markdown
     *
     * @default /^\[\[toc\]\]$/i
     */
    pattern?: RegExp;
    /**
     * A custom slugification function
     *
     * Should use the same slugify function with markdown-it-anchor
     * to ensure the link is matched
     */
    slugify?: (str: string) => string;
    /**
     * A function for formatting headings
     */
    format?: (str: string) => string;
    /**
     * Heading level that going to be included in the TOC
     *
     * Should be a subset of markdown-it-anchor's `level` option
     * to ensure the link is existed
     *
     * @default [2,3]
     */
    level?: number[];
    /**
     * HTML tag of the TOC container
     *
     * @default 'nav'
     */
    containerTag?: string;
    /**
     * The class for the TOC container
     *
     * @default 'table-of-contents'
     */
    containerClass?: string;
    /**
     * HTML tag of the TOC list
     *
     * @default 'ul'
     */
    listTag?: 'ul' | 'ol';
    /**
     * The class for the TOC list
     *
     * @default ''
     */
    listClass?: string;
    /**
     * The class for the `<li>` tag
     *
     * @default ''
     */
    itemClass?: string;
    /**
     * The tag of the link inside `<li>` tag
     *
     * @default 'a'
     */
    linkTag?: 'a' | 'router-link';
    /**
     * The class for the link inside the `<li>` tag
     *
     * @default ''
     */
    linkClass?: string;
}

type RenderHeadersFn = (headers: MarkdownItHeader[]) => string;
declare const createRenderHeaders: ({ listTag, listClass, itemClass, linkTag, linkClass, }: Pick<Required<TocPluginOptions>, 'listTag' | 'listClass' | 'itemClass' | 'linkTag' | 'linkClass'>) => RenderHeadersFn;

/**
 * Forked and modified from markdown-it-toc-done-right
 *
 * - remove the `inlineOptions` support
 * - use markdown-it default renderer to render token whenever possible
 *
 * @see https://github.com/nagaozen/markdown-it-toc-done-right
 */
declare const createTocBlockRule: ({ pattern, containerTag, containerClass, }: Pick<Required<TocPluginOptions>, 'pattern' | 'containerTag' | 'containerClass'>) => ParserBlock.RuleBlock;

/**
 * Generate table of contents
 *
 * Forked and modified from markdown-it-toc-done-right:
 *
 * @see https://github.com/nagaozen/markdown-it-toc-done-right
 */
declare const tocPlugin: MarkdownIt.PluginWithOptions<TocPluginOptions>;

export { TocPluginOptions, createRenderHeaders, createTocBlockRule, tocPlugin };
/package.json{
  "name": "@mdit-vue/plugin-toc",
  "version": "0.11.2",
  "description": "A markdown-it plugin to generate table-of-contents that compatible with Vue.js",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "toc",
    "table-of-contents"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@mdit-vue/shared": "0.11.2",
    "@mdit-vue/types": "0.11.0",
    "@types/markdown-it": "^12.2.3",
    "markdown-it": "^13.0.1"
  },
  "devDependencies": {
    "markdown-it-anchor": "^8.6.6"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "676ec4ca8704d709e7a47f7f6d41ff3f70dc2356"
}
/README.md# @mdit-vue/plugin-toc

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-toc)](https://www.npmjs.com/package/@mdit-vue/plugin-toc)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to generate table-of-contents (TOC) that compatible with [Vue.js](https://vuejs.org).

This plugin is basically a fork of [markdown-it-toc-done-right](https://github.com/nagaozen/markdown-it-toc-done-right), with following enhancement:

- Allows `html_inline` tags in headings to support vue components.
- Supports [containerTag](#containertag), [listTag](#listtag) and [linkTag](#linktag).
- Only allows array in [level](#level) option.
- Code refactor and optimizations.

## Install

```sh
npm i @mdit-vue/plugin-toc
```

## Usage

```ts
import MarkdownIt from 'markdown-it';
import { tocPlugin } from '@mdit-vue/plugin-toc';

const md = MarkdownIt({ html: true }).use(tocPlugin, {
  // options
});
```

## Options

### pattern

- Type: `RegExp`

- Default: `/^\[\[toc\]\]$/i`

- Details:

  The pattern serving as the TOC placeholder in your markdown.

### slugify

- Type: `(str: string) => string`

- Default: `slugify` from `@mdit-vue/shared`

- Details:

  A custom slugification function.

  The default slugify function comes from [@mdit-vue/shared](https://github.com/mdit-vue/mdit-vue/tree/main/packages/shared) package.

  When using this plugin with [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) (recommended), this option will be ignored because the `id` of the headings have already been determined by markdown-it-anchor's `slugify` option.

### format

- Type: `(str: string) => string`

- Details:

  A function for formatting headings.

### level

- Type: `number[]`

- Default: `[2, 3]`

- Details:

  Heading level that going to be included in the TOC.

  When using this plugin with [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) (recommended), this option should be a subset of markdown-it-anchor's `level` option to ensure the target links are existed.

### containerTag

- Type: `string`

- Default: `'nav'`

- Details:

  HTML tag of the TOC container.

### containerClass

- Type: `string`

- Default: `'table-of-contents'`

- Details:

  The class for the TOC container.

### listTag

- Type: `'ul' | 'ol'`

- Default: `'ul'`

- Details:

  HTML tag of the TOC list.

### listClass

- Type: `string`

- Default: `''`

- Details:

  The class for the TOC list.

### itemClass

- Type: `string`

- Default: `''`

- Details:

  The class for the `<li>` tag.

### linkTag

- Type: `'a' | 'router-link'`

- Default: `'a'`

- Details:

  The tag of the link inside the `<li>` tag.

  You can set this option to render to links as [vue-router's router-link](https://router.vuejs.org/guide/#html).

### linkClass

- Type: `string`

- Default: `''`

- Details:

  The class for the link inside the `<li>` tag.


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1jb21wb25lbnRAMC4xMS4y
================================================
/dist/index.d.tsimport MarkdownIt from 'markdown-it';
import ParserBlock from 'markdown-it/lib/parser_block.js';
import ParserInline from 'markdown-it/lib/parser_inline.js';

/**
 * Options of @mdit-vue/plugin-component
 */
interface ComponentPluginOptions {
    /**
     * Extra tags to be treated as block tags.
     *
     * @default []
     */
    blockTags?: string[];
    /**
     * Extra tags to be treated as inline tags.
     *
     * @default []
     */
    inlineTags?: string[];
}

/**
 * Allows better use of Vue components in Markdown
 */
declare const componentPlugin: MarkdownIt.PluginWithOptions<ComponentPluginOptions>;

declare const createHtmlBlockRule: (options: Required<ComponentPluginOptions>) => ParserBlock.RuleBlock;

declare const htmlInlineRule: ParserInline.RuleInline;

declare const HTML_TAG_RE: RegExp;
declare const HTML_OPEN_CLOSE_TAG_RE: RegExp;
declare const HTML_SELF_CLOSING_TAG_RE: RegExp;
declare const HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE: RegExp;

/**
 * List of block tags
 *
 * @see https://spec.commonmark.org/0.30/#html-blocks
 */
declare const TAGS_BLOCK: string[];
/**
 * According to markdown spec, all non-block html tags are treated as "inline"
 * tags (wrapped with <p></p>), including those "unknown" tags
 *
 * Therefore, markdown-it processes "inline" tags and "unknown" tags in the same
 * way, and does not care if a tag is "inline" or "unknown"
 *
 * As we want to take those "unknown" tags as custom components, we should
 * treat them as "block" tags
 *
 * So we have to distinguish between "inline" and "unknown" tags ourselves
 *
 * The inline tags list comes from MDN
 *
 * @see https://spec.commonmark.org/0.30/#raw-html
 * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements
 */
declare const TAGS_INLINE: string[];
/**
 * Tags of Vue built-in components
 *
 * @see https://vuejs.org/api/built-in-components.html
 * @see https://vuejs.org/api/built-in-special-elements.html
 */
declare const TAGS_VUE_RESERVED: string[];

export { ComponentPluginOptions, HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE, HTML_OPEN_CLOSE_TAG_RE, HTML_SELF_CLOSING_TAG_RE, HTML_TAG_RE, TAGS_BLOCK, TAGS_INLINE, TAGS_VUE_RESERVED, componentPlugin, createHtmlBlockRule, htmlInlineRule };
/package.jsonn{
  "name": "@mdit-vue/plugin-component",
  "version": "0.11.2",
  "description": "A markdown-it plugin to allow vue components in markdown",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "component"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@types/markdown-it": "^12.2.3",
    "markdown-it": "^13.0.1"
  },
  "devDependencies": {
    "@vue/shared": "^3.2.45"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "676ec4ca8704d709e7a47f7f6d41ff3f70dc2356"
}
/dist/index.mjsimport blockNames from 'markdown-it/lib/common/html_blocks.js';

const attr_name = "[a-zA-Z_:@][a-zA-Z0-9:._-]*";
const unquoted = "[^\"'=<>`\\x00-\\x20]+";
const single_quoted = "'[^']*'";
const double_quoted = '"[^"]*"';
const attr_value = "(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")";
const attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)";
const open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>";
const close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>";
const comment = "<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->";
const processing = "<[?][\\s\\S]*?[?]>";
const declaration = "<![A-Z]+\\s+[^>]*>";
const cdata = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>";
const HTML_TAG_RE = new RegExp(
  "^(?:" + open_tag + "|" + close_tag + "|" + comment + "|" + processing + "|" + declaration + "|" + cdata + ")"
);
const HTML_OPEN_CLOSE_TAG_RE = new RegExp(
  "^(?:" + open_tag + "|" + close_tag + ")"
);
const HTML_SELF_CLOSING_TAG_RE = new RegExp(
  "^<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/>"
);
const HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE = new RegExp(
  "^<([A-Za-z][A-Za-z0-9\\-]*)" + attribute + "*\\s*>.*<\\/\\1\\s*>"
);

const TAGS_BLOCK = blockNames;
const TAGS_INLINE = [
  "a",
  "abbr",
  "acronym",
  "audio",
  "b",
  "bdi",
  "bdo",
  "big",
  "br",
  "button",
  "canvas",
  "cite",
  "code",
  "data",
  "datalist",
  "del",
  "dfn",
  "em",
  "embed",
  "i",
  "iframe",
  "img",
  "input",
  "ins",
  "kbd",
  "label",
  "map",
  "mark",
  "meter",
  "noscript",
  "object",
  "output",
  "picture",
  "progress",
  "q",
  "ruby",
  "s",
  "samp",
  "script",
  "select",
  "slot",
  "small",
  "span",
  "strong",
  "sub",
  "sup",
  "svg",
  "template",
  "textarea",
  "time",
  "u",
  "tt",
  "var",
  "video",
  "wbr"
];
const TAGS_VUE_RESERVED = [
  "template",
  "component",
  "transition",
  "transition-group",
  "keep-alive",
  "slot",
  "teleport"
];

const createHtmlSequences = ({
  blockTags,
  inlineTags
}) => {
  const forceBlockTags = [...blockTags, ...TAGS_BLOCK];
  const forceInlineTags = [
    ...inlineTags,
    ...TAGS_INLINE.filter((item) => !TAGS_VUE_RESERVED.includes(item))
  ];
  const HTML_SEQUENCES = [
    [/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
    [/^<!--/, /-->/, true],
    [/^<\?/, /\?>/, true],
    [/^<![A-Z]/, />/, true],
    [/^<!\[CDATA\[/, /\]\]>/, true],
    [
      new RegExp("^</?(" + forceBlockTags.join("|") + ")(?=(\\s|/?>|$))", "i"),
      /^$/,
      true
    ],
    [
      new RegExp(
        "^</?(?!(" + forceInlineTags.join("|") + ")(?![\\w-]))[A-Za-z][A-Za-z0-9\\-]*(?=(\\s|/?>|$))"
      ),
      /^$/,
      true
    ],
    [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + "\\s*$"), /^$/, false]
  ];
  return HTML_SEQUENCES;
};
const createHtmlBlockRule = (options) => {
  const HTML_SEQUENCES = createHtmlSequences(options);
  return (state, startLine, endLine, silent) => {
    let i;
    let nextLine;
    let lineText;
    let pos = state.bMarks[startLine] + state.tShift[startLine];
    let max = state.eMarks[startLine];
    if (state.sCount[startLine] - state.blkIndent >= 4) {
      return false;
    }
    if (!state.md.options.html) {
      return false;
    }
    if (state.src.charCodeAt(pos) !== 60) {
      return false;
    }
    lineText = state.src.slice(pos, max);
    for (i = 0; i < HTML_SEQUENCES.length; i++) {
      if (HTML_SEQUENCES[i][0].test(lineText)) {
        break;
      }
    }
    if (i === HTML_SEQUENCES.length) {
      return false;
    }
    if (silent) {
      return HTML_SEQUENCES[i][2];
    }
    if (i === 6) {
      const match = lineText.match(HTML_SELF_CLOSING_TAG_RE) ?? lineText.match(HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE);
      if (match) {
        state.line = startLine + 1;
        let token2 = state.push("html_inline", "", 0);
        token2.content = match[0];
        token2.map = [startLine, state.line];
        token2 = state.push("inline", "", 0);
        token2.content = lineText.slice(match[0].length);
        token2.map = [startLine, state.line];
        token2.children = [];
        return true;
      }
    }
    nextLine = startLine + 1;
    if (!HTML_SEQUENCES[i][1].test(lineText)) {
      for (; nextLine < endLine; nextLine++) {
        if (state.sCount[nextLine] < state.blkIndent) {
          break;
        }
        pos = state.bMarks[nextLine] + state.tShift[nextLine];
        max = state.eMarks[nextLine];
        lineText = state.src.slice(pos, max);
        if (HTML_SEQUENCES[i][1].test(lineText)) {
          if (lineText.length !== 0) {
            nextLine++;
          }
          break;
        }
      }
    }
    state.line = nextLine;
    const token = state.push("html_block", "", 0);
    token.map = [startLine, nextLine];
    token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
    return true;
  };
};

const isLetter = (ch) => {
  const lc = ch | 32;
  return lc >= 97 && lc <= 122;
};
const htmlInlineRule = (state, silent) => {
  const { pos } = state;
  if (!state.md.options.html) {
    return false;
  }
  const max = state.posMax;
  if (state.src.charCodeAt(pos) !== 60 || pos + 2 >= max) {
    return false;
  }
  const ch = state.src.charCodeAt(pos + 1);
  if (ch !== 33 && ch !== 63 && ch !== 47 && !isLetter(ch)) {
    return false;
  }
  const match = state.src.slice(pos).match(HTML_TAG_RE);
  if (!match) {
    return false;
  }
  if (!silent) {
    const token = state.push("html_inline", "", 0);
    token.content = state.src.slice(pos, pos + match[0].length);
  }
  state.pos += match[0].length;
  return true;
};

const componentPlugin = (md, { blockTags = [], inlineTags = [] } = {}) => {
  const htmlBlockRule = createHtmlBlockRule({
    blockTags,
    inlineTags
  });
  md.block.ruler.at("html_block", htmlBlockRule, {
    alt: ["paragraph", "reference", "blockquote"]
  });
  md.inline.ruler.at("html_inline", htmlInlineRule);
};

export { HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE, HTML_OPEN_CLOSE_TAG_RE, HTML_SELF_CLOSING_TAG_RE, HTML_TAG_RE, TAGS_BLOCK, TAGS_INLINE, TAGS_VUE_RESERVED, componentPlugin, createHtmlBlockRule, htmlInlineRule };
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/dist/index.cjs@'use strict';

const blockNames = require('markdown-it/lib/common/html_blocks.js');

const attr_name = "[a-zA-Z_:@][a-zA-Z0-9:._-]*";
const unquoted = "[^\"'=<>`\\x00-\\x20]+";
const single_quoted = "'[^']*'";
const double_quoted = '"[^"]*"';
const attr_value = "(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")";
const attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)";
const open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>";
const close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>";
const comment = "<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->";
const processing = "<[?][\\s\\S]*?[?]>";
const declaration = "<![A-Z]+\\s+[^>]*>";
const cdata = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>";
const HTML_TAG_RE = new RegExp(
  "^(?:" + open_tag + "|" + close_tag + "|" + comment + "|" + processing + "|" + declaration + "|" + cdata + ")"
);
const HTML_OPEN_CLOSE_TAG_RE = new RegExp(
  "^(?:" + open_tag + "|" + close_tag + ")"
);
const HTML_SELF_CLOSING_TAG_RE = new RegExp(
  "^<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/>"
);
const HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE = new RegExp(
  "^<([A-Za-z][A-Za-z0-9\\-]*)" + attribute + "*\\s*>.*<\\/\\1\\s*>"
);

const TAGS_BLOCK = blockNames;
const TAGS_INLINE = [
  "a",
  "abbr",
  "acronym",
  "audio",
  "b",
  "bdi",
  "bdo",
  "big",
  "br",
  "button",
  "canvas",
  "cite",
  "code",
  "data",
  "datalist",
  "del",
  "dfn",
  "em",
  "embed",
  "i",
  "iframe",
  "img",
  "input",
  "ins",
  "kbd",
  "label",
  "map",
  "mark",
  "meter",
  "noscript",
  "object",
  "output",
  "picture",
  "progress",
  "q",
  "ruby",
  "s",
  "samp",
  "script",
  "select",
  "slot",
  "small",
  "span",
  "strong",
  "sub",
  "sup",
  "svg",
  "template",
  "textarea",
  "time",
  "u",
  "tt",
  "var",
  "video",
  "wbr"
];
const TAGS_VUE_RESERVED = [
  "template",
  "component",
  "transition",
  "transition-group",
  "keep-alive",
  "slot",
  "teleport"
];

const createHtmlSequences = ({
  blockTags,
  inlineTags
}) => {
  const forceBlockTags = [...blockTags, ...TAGS_BLOCK];
  const forceInlineTags = [
    ...inlineTags,
    ...TAGS_INLINE.filter((item) => !TAGS_VUE_RESERVED.includes(item))
  ];
  const HTML_SEQUENCES = [
    [/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
    [/^<!--/, /-->/, true],
    [/^<\?/, /\?>/, true],
    [/^<![A-Z]/, />/, true],
    [/^<!\[CDATA\[/, /\]\]>/, true],
    [
      new RegExp("^</?(" + forceBlockTags.join("|") + ")(?=(\\s|/?>|$))", "i"),
      /^$/,
      true
    ],
    [
      new RegExp(
        "^</?(?!(" + forceInlineTags.join("|") + ")(?![\\w-]))[A-Za-z][A-Za-z0-9\\-]*(?=(\\s|/?>|$))"
      ),
      /^$/,
      true
    ],
    [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + "\\s*$"), /^$/, false]
  ];
  return HTML_SEQUENCES;
};
const createHtmlBlockRule = (options) => {
  const HTML_SEQUENCES = createHtmlSequences(options);
  return (state, startLine, endLine, silent) => {
    let i;
    let nextLine;
    let lineText;
    let pos = state.bMarks[startLine] + state.tShift[startLine];
    let max = state.eMarks[startLine];
    if (state.sCount[startLine] - state.blkIndent >= 4) {
      return false;
    }
    if (!state.md.options.html) {
      return false;
    }
    if (state.src.charCodeAt(pos) !== 60) {
      return false;
    }
    lineText = state.src.slice(pos, max);
    for (i = 0; i < HTML_SEQUENCES.length; i++) {
      if (HTML_SEQUENCES[i][0].test(lineText)) {
        break;
      }
    }
    if (i === HTML_SEQUENCES.length) {
      return false;
    }
    if (silent) {
      return HTML_SEQUENCES[i][2];
    }
    if (i === 6) {
      const match = lineText.match(HTML_SELF_CLOSING_TAG_RE) ?? lineText.match(HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE);
      if (match) {
        state.line = startLine + 1;
        let token2 = state.push("html_inline", "", 0);
        token2.content = match[0];
        token2.map = [startLine, state.line];
        token2 = state.push("inline", "", 0);
        token2.content = lineText.slice(match[0].length);
        token2.map = [startLine, state.line];
        token2.children = [];
        return true;
      }
    }
    nextLine = startLine + 1;
    if (!HTML_SEQUENCES[i][1].test(lineText)) {
      for (; nextLine < endLine; nextLine++) {
        if (state.sCount[nextLine] < state.blkIndent) {
          break;
        }
        pos = state.bMarks[nextLine] + state.tShift[nextLine];
        max = state.eMarks[nextLine];
        lineText = state.src.slice(pos, max);
        if (HTML_SEQUENCES[i][1].test(lineText)) {
          if (lineText.length !== 0) {
            nextLine++;
          }
          break;
        }
      }
    }
    state.line = nextLine;
    const token = state.push("html_block", "", 0);
    token.map = [startLine, nextLine];
    token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
    return true;
  };
};

const isLetter = (ch) => {
  const lc = ch | 32;
  return lc >= 97 && lc <= 122;
};
const htmlInlineRule = (state, silent) => {
  const { pos } = state;
  if (!state.md.options.html) {
    return false;
  }
  const max = state.posMax;
  if (state.src.charCodeAt(pos) !== 60 || pos + 2 >= max) {
    return false;
  }
  const ch = state.src.charCodeAt(pos + 1);
  if (ch !== 33 && ch !== 63 && ch !== 47 && !isLetter(ch)) {
    return false;
  }
  const match = state.src.slice(pos).match(HTML_TAG_RE);
  if (!match) {
    return false;
  }
  if (!silent) {
    const token = state.push("html_inline", "", 0);
    token.content = state.src.slice(pos, pos + match[0].length);
  }
  state.pos += match[0].length;
  return true;
};

const componentPlugin = (md, { blockTags = [], inlineTags = [] } = {}) => {
  const htmlBlockRule = createHtmlBlockRule({
    blockTags,
    inlineTags
  });
  md.block.ruler.at("html_block", htmlBlockRule, {
    alt: ["paragraph", "reference", "blockquote"]
  });
  md.inline.ruler.at("html_inline", htmlInlineRule);
};

exports.HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE = HTML_OPEN_AND_CLOSE_TAG_IN_THE_SAME_LINE_RE;
exports.HTML_OPEN_CLOSE_TAG_RE = HTML_OPEN_CLOSE_TAG_RE;
exports.HTML_SELF_CLOSING_TAG_RE = HTML_SELF_CLOSING_TAG_RE;
exports.HTML_TAG_RE = HTML_TAG_RE;
exports.TAGS_BLOCK = TAGS_BLOCK;
exports.TAGS_INLINE = TAGS_INLINE;
exports.TAGS_VUE_RESERVED = TAGS_VUE_RESERVED;
exports.componentPlugin = componentPlugin;
exports.createHtmlBlockRule = createHtmlBlockRule;
exports.htmlInlineRule = htmlInlineRule;
/README.md
# @mdit-vue/plugin-component

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-component)](https://www.npmjs.com/package/@mdit-vue/plugin-component)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to allow Vue components in markdown.

- Treats [vue built-in components](https://vuejs.org/api/built-in-components.html) and unknown HTML tags as vue components (markdown-it would treat them as inline tags by default).
- Allows vue [`@` directive](https://vuejs.org/api/built-in-directives.html#v-on) on native HTML tags.

## Install

```sh
npm i @mdit-vue/plugin-component
```

## Usage

This plugin will only take effects when the `html` option of markdown-it is enabled:

```ts
import MarkdownIt from 'markdown-it';
import { componentPlugin } from '@mdit-vue/plugin-component';

const md = MarkdownIt({ html: true }).use(componentPlugin, {
  // options
});

const rendered = md.render(
  `\
<!-- @ shorthand is supported -->
<Foo @click="onClick" />

<!-- multi-line syntax won't be wrapped with <p> -->
<Foo
  class="foo"
  :bar="bar"
/>
`,
);
```

## Options

### blockTags

- Type: `string[]`

- Default: `[]`

- Details:

  Extra tags to be treated as block tags.

  By default, all standard [HTML inline elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements) will be treated as inline tags (excluding [Vue built-in special elements](https://vuejs.org/api/built-in-special-elements.html)). All unknown elements will be assumed as Vue components, and will be treated as block tags (with slight differences).

  In some cases (should be rare though) you might want to force some tags to behave like block tags, then you can use this option to specify the tag names.

  Notice that this option is case-sensitive, and has higher priority than the [inlineTags](#inlinetags) option.

### inlineTags

- Type: `string[]`

- Default: `[]`

- Details:

  Extra tags to be treated as inline tags.

  By default, only standard [HTML inline elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements) will be treated as inline tags (excluding [Vue built-in special elements](https://vuejs.org/api/built-in-special-elements.html)). All unknown elements will be assumed as Vue components, and will be treated as block tags (with slight differences).

  Treating Vue components like block tags would work as expected in most cases. However, in some cases you might want to force some tags to behave like inline tags, then you can use this option to specify the tag names.

  Notice that this option is case-sensitive, and has lower priority than the [blockTags](#blocktags) option.


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1mcm9udG1hdHRlckAwLjExLjE=
================================================
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/dist/index.d.ts=import MarkdownIt from 'markdown-it';
import matter from 'gray-matter';

declare type GrayMatterOptions = matter.GrayMatterOption<string, GrayMatterOptions>;
/**
 * Options of @mdit-vue/plugin-frontmatter
 */
interface FrontmatterPluginOptions {
    /**
     * Options of gray-matter
     *
     * @see https://github.com/jonschlinkert/gray-matter#options
     */
    grayMatterOptions?: GrayMatterOptions;
    /**
     * Render the excerpt or not
     *
     * @default true
     */
    renderExcerpt?: boolean;
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The raw Markdown content without frontmatter
         */
        content?: string;
        /**
         * The excerpt that extracted by `@mdit-vue/plugin-frontmatter`
         *
         * - Would be the rendered HTML when `renderExcerpt` is enabled
         * - Would be the raw Markdown when `renderExcerpt` is disabled
         */
        excerpt?: string;
        /**
         * The frontmatter that extracted by `@mdit-vue/plugin-frontmatter`
         */
        frontmatter?: Record<string, unknown>;
    }
}

/**
 * Get markdown frontmatter and excerpt
 *
 * Extract them into env
 */
declare const frontmatterPlugin: MarkdownIt.PluginWithOptions<FrontmatterPluginOptions>;

export { FrontmatterPluginOptions, frontmatterPlugin };
/README.md# @mdit-vue/plugin-frontmatter

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-frontmatter)](https://www.npmjs.com/package/@mdit-vue/plugin-frontmatter)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to get markdown frontmatter with [gray-matter](https://github.com/jonschlinkert/gray-matter).

- Extracts frontmatter into markdown-it `env.frontmatter`.
- Allows providing default frontmatter via markdown-it `env.frontmatter`.
- Extracts markdown content without frontmatter into markdown-it `env.content`.
- Supports extracting rendered excerpt into markdown-it `env.excerpt`.

## Install

```sh
npm i @mdit-vue/plugin-frontmatter
```

## Usage

```ts
import MarkdownIt from 'markdown-it';
import { frontmatterPlugin } from '@mdit-vue/plugin-frontmatter';
import type { MarkdownItEnv } from '@mdit-vue/types';

const md = MarkdownIt({ html: true }).use(frontmatterPlugin, {
  // options
  grayMatterOptions: {
    excerpt: true,
    excerpt_separator: '<!-- more -->',
  },
});
const env: MarkdownItEnv = {};

const rendered = md.render(
  `\
---
title: foobar
---

Everything above **more** comment will be extracted as excerpt.

<!-- more -->

Things below **more** comment will not be included in the excerpt.
`,
  env,
);

console.log(env.frontmatter);
console.log(env.content);
console.log(env.excerpt);
```

## Options

### grayMatterOptions

- Type: `GrayMatterOptions`

- Details:

  Options of [gray-matter](https://github.com/jonschlinkert/gray-matter).

### renderExcerpt

- Type: `boolean`

- Default: `true`

  Render the [excerpt](https://github.com/jonschlinkert/gray-matter#optionsexcerpt) with markdown-it or not.

  This option will only take effects when `grayMatterOptions.excerpt` is enabled (disabled by default) or `grayMatterOptions.excerpt_separator` is set (undefined by default).
/dist/index.mjsimport grayMatter from 'gray-matter';

const frontmatterPlugin = (md, { grayMatterOptions, renderExcerpt = true } = {}) => {
  const render = md.render.bind(md);
  md.render = (src, env = {}) => {
    const { data, content, excerpt = "" } = grayMatter(src, grayMatterOptions);
    env.content = content;
    env.frontmatter = {
      ...env.frontmatter,
      ...data
    };
    env.excerpt = renderExcerpt && excerpt ? render(excerpt, { ...env }) : excerpt;
    return render(content, env);
  };
};

export { frontmatterPlugin };
/dist/index.cjs>'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const grayMatter = require('gray-matter');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }

const grayMatter__default = /*#__PURE__*/_interopDefaultLegacy(grayMatter);

const frontmatterPlugin = (md, { grayMatterOptions, renderExcerpt = true } = {}) => {
  const render = md.render.bind(md);
  md.render = (src, env = {}) => {
    const { data, content, excerpt = "" } = grayMatter__default(src, grayMatterOptions);
    env.content = content;
    env.frontmatter = {
      ...env.frontmatter,
      ...data
    };
    env.excerpt = renderExcerpt && excerpt ? render(excerpt, { ...env }) : excerpt;
    return render(content, env);
  };
};

exports.frontmatterPlugin = frontmatterPlugin;
/package.json~{
  "name": "@mdit-vue/plugin-frontmatter",
  "version": "0.11.1",
  "description": "A markdown-it plugin to get markdown frontmatter",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "frontmatter",
    "excerpt"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@mdit-vue/types": "0.11.0",
    "@types/markdown-it": "^12.2.3",
    "gray-matter": "^4.0.3",
    "markdown-it": "^13.0.1"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "98828479d07c7bc52d178a00cdb92c166eff09ee"
}


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1oZWFkZXJzQDAuMTEuMg==
================================================
/dist/index.mjs
import { resolveHeadersFromTokens, slugify } from '@mdit-vue/shared';

const headersPlugin = (md, { level = [2, 3], slugify: slugify$1 = slugify, format } = {}) => {
  const render = md.renderer.render.bind(md.renderer);
  md.renderer.render = (tokens, options, env) => {
    env.headers = resolveHeadersFromTokens(tokens, {
      level,
      shouldAllowHtml: false,
      shouldEscapeText: false,
      slugify: slugify$1,
      format
    });
    return render(tokens, options, env);
  };
};

export { headersPlugin };
/package.json{
  "name": "@mdit-vue/plugin-headers",
  "version": "0.11.2",
  "description": "A markdown-it plugin to get markdown headers",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "header",
    "heading"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@mdit-vue/shared": "0.11.2",
    "@mdit-vue/types": "0.11.0",
    "@types/markdown-it": "^12.2.3",
    "markdown-it": "^13.0.1"
  },
  "devDependencies": {
    "markdown-it-anchor": "^8.6.6"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "676ec4ca8704d709e7a47f7f6d41ff3f70dc2356"
}
/dist/index.cjs'use strict';

const shared = require('@mdit-vue/shared');

const headersPlugin = (md, { level = [2, 3], slugify = shared.slugify, format } = {}) => {
  const render = md.renderer.render.bind(md.renderer);
  md.renderer.render = (tokens, options, env) => {
    env.headers = shared.resolveHeadersFromTokens(tokens, {
      level,
      shouldAllowHtml: false,
      shouldEscapeText: false,
      slugify,
      format
    });
    return render(tokens, options, env);
  };
};

exports.headersPlugin = headersPlugin;
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/README.md'# @mdit-vue/plugin-headers

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-headers)](https://www.npmjs.com/package/@mdit-vue/plugin-headers)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to get markdown headers.

- Extracts all headers info into markdown-it `env.headers`.

## Install

```sh
npm i @mdit-vue/plugin-headers
```

## Usage

```ts
import MarkdownIt from 'markdown-it';
import { headersPlugin } from '@mdit-vue/plugin-headers';
import type { MarkdownItEnv } from '@mdit-vue/types';

const md = MarkdownIt({ html: true }).use(headersPlugin, {
  // options
});
const env: MarkdownItEnv = {};

const rendered = md.render(
  `\
# h1
## h2
### h3
`,
  env,
);

console.log(env.headers);
```

## Options

### format

- Type: `(str: string) => string`

- Details:

  A function for formatting header title.

### level

- Type: `number[]`

- Default: `[2, 3]`

- Details:

  Heading level that going to be extracted.

  When using this plugin with [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) (recommended), this option should be a subset of markdown-it-anchor's `level` option to ensure the header slugs are existed.

### slugify

- Type: `(str: string) => string`

- Default: `slugify` from `@mdit-vue/shared`

- Details:

  A custom slugification function.

  The default slugify function comes from [@mdit-vue/shared](https://github.com/mdit-vue/mdit-vue/tree/main/packages/shared) package.

  When using this plugin with [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) (recommended), this option will be ignored because the `id` of the headings have already been determined by markdown-it-anchor's `slugify` option.
/dist/index.d.tsimport MarkdownIt from 'markdown-it';
import { MarkdownItHeader } from '@mdit-vue/types';
export { MarkdownItHeader } from '@mdit-vue/types';

/**
 * Options of @mdit-vue/plugin-headers
 */
interface HeadersPluginOptions {
    /**
     * A custom slugification function
     *
     * Should use the same slugify function with markdown-it-anchor
     * to ensure the link is matched
     */
    slugify?: (str: string) => string;
    /**
     * A function for formatting header title
     */
    format?: (str: string) => string;
    /**
     * Heading level that going to be extracted
     *
     * Should be a subset of markdown-it-anchor's `level` option
     * to ensure the slug is existed
     *
     * @default [2,3]
     */
    level?: number[];
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * The headers that extracted by `@mdit-vue/plugin-headers`
         */
        headers?: MarkdownItHeader[];
    }
}

/**
 * Get markdown headers info
 *
 * Extract them into env
 */
declare const headersPlugin: MarkdownIt.PluginWithOptions<HeadersPluginOptions>;

export { HeadersPluginOptions, headersPlugin };


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1zZmNAMC4xMS4x
================================================
/package.jsonO{
  "name": "@mdit-vue/plugin-sfc",
  "version": "0.11.1",
  "description": "A markdown-it plugin to help transforming markdown tu vue sfc",
  "keywords": [
    "markdown-it",
    "markdown-it-plugin",
    "vue",
    "sfc"
  ],
  "homepage": "https://github.com/mdit-vue",
  "bugs": {
    "url": "https://github.com/mdit-vue/mdit-vue/issues"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/mdit-vue/mdit-vue.git"
  },
  "license": "MIT",
  "author": "meteorlxy <meteor.lxy@foxmail.com>",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "files": [
    "./dist"
  ],
  "scripts": {
    "build": "unbuild",
    "test": "vitest"
  },
  "dependencies": {
    "@mdit-vue/types": "0.11.0",
    "@types/markdown-it": "^12.2.3",
    "markdown-it": "^13.0.1"
  },
  "publishConfig": {
    "access": "public"
  },
  "gitHead": "98828479d07c7bc52d178a00cdb92c166eff09ee"
}
/dist/index.d.ts	import MarkdownIt from 'markdown-it';

declare const TAG_NAME_SCRIPT = "script";
declare const TAG_NAME_STYLE = "style";
declare const TAG_NAME_TEMPLATE = "template";

/**
 * Options of @mdit-vue/plugin-sfc
 */
interface SfcPluginOptions {
    /**
     * Custom blocks to be extracted
     *
     * @default []
     */
    customBlocks?: string[];
}
/**
 * SFC block that extracted from markdown
 */
interface SfcBlock {
    /**
     * The type of the block
     */
    type: string;
    /**
     * The content, including open-tag and close-tag
     */
    content: string;
    /**
     * The content that stripped open-tag and close-tag off
     */
    contentStripped: string;
    /**
     * The open-tag
     */
    tagOpen: string;
    /**
     * The close-tag
     */
    tagClose: string;
}
interface MarkdownSfcBlocks {
    /**
     * The `<template>` block
     */
    template: SfcBlock | null;
    /**
     * The common `<script>` block
     */
    script: SfcBlock | null;
    /**
     * The `<script setup>` block
     */
    scriptSetup: SfcBlock | null;
    /**
     * All `<script>` blocks.
     *
     * By default, SFC only allows one `<script>` block and one `<script setup>` block.
     * However, some tools may support different types of `<script>`s, so we keep all of them here.
     */
    scripts: SfcBlock[];
    /**
     * All `<style>` blocks.
     */
    styles: SfcBlock[];
    /**
     * All custom blocks.
     */
    customBlocks: SfcBlock[];
}
declare module '@mdit-vue/types' {
    interface MarkdownItEnv {
        /**
         * SFC blocks that extracted by `@mdit-vue/plugin-sfc`
         */
        sfcBlocks?: MarkdownSfcBlocks;
    }
}

/**
 * Get Vue SFC blocks
 *
 * Extract them into env and avoid rendering them
 */
declare const sfcPlugin: MarkdownIt.PluginWithOptions<SfcPluginOptions>;

declare const SCRIPT_SETUP_TAG_OPEN_REGEXP: RegExp;
interface SfcRegExpMatchArray extends Omit<RegExpMatchArray, 'groups'> {
    groups: SfcBlock;
}
/**
 * Generate RegExp for sfc blocks
 */
declare const createSfcRegexp: ({ customBlocks, }: Required<Pick<SfcPluginOptions, 'customBlocks'>>) => RegExp;

export { MarkdownSfcBlocks, SCRIPT_SETUP_TAG_OPEN_REGEXP, SfcBlock, SfcPluginOptions, SfcRegExpMatchArray, TAG_NAME_SCRIPT, TAG_NAME_STYLE, TAG_NAME_TEMPLATE, createSfcRegexp, sfcPlugin };
/dist/index.mjsconst TAG_NAME_SCRIPT = "script";
const TAG_NAME_STYLE = "style";
const TAG_NAME_TEMPLATE = "template";

const SCRIPT_SETUP_TAG_OPEN_REGEXP = /^<script\s+.*?\bsetup\b.*?>$/is;
const createSfcRegexp = ({
  customBlocks
}) => {
  const sfcTags = Array.from(
    /* @__PURE__ */ new Set([TAG_NAME_SCRIPT, TAG_NAME_STYLE, ...customBlocks])
  ).join("|");
  return new RegExp(
    `^\\s*(?<content>(?<tagOpen><(?<type>${sfcTags})\\s?.*?>)(?<contentStripped>.*)(?<tagClose><\\/\\k<type>\\s*>))\\s*$`,
    "is"
  );
};

const sfcPlugin = (md, { customBlocks = [] } = {}) => {
  const sfcRegexp = createSfcRegexp({ customBlocks });
  const render = md.render.bind(md);
  md.render = (src, env = {}) => {
    env.sfcBlocks = {
      template: null,
      script: null,
      scriptSetup: null,
      scripts: [],
      styles: [],
      customBlocks: []
    };
    const rendered = render(src, env);
    env.sfcBlocks.template = {
      type: TAG_NAME_TEMPLATE,
      content: `<${TAG_NAME_TEMPLATE}>${rendered}</${TAG_NAME_TEMPLATE}>`,
      contentStripped: rendered,
      tagOpen: `<${TAG_NAME_TEMPLATE}>`,
      tagClose: `</${TAG_NAME_TEMPLATE}>`
    };
    return rendered;
  };
  const htmlBlockRule = md.renderer.rules.html_block;
  md.renderer.rules.html_block = (tokens, idx, options, env, self) => {
    if (!env.sfcBlocks) {
      return htmlBlockRule(tokens, idx, options, env, self);
    }
    const token = tokens[idx];
    const content = token.content;
    const match = content.match(sfcRegexp);
    if (!match) {
      return htmlBlockRule(tokens, idx, options, env, self);
    }
    const sfcBlock = match.groups;
    if (sfcBlock.type === TAG_NAME_SCRIPT) {
      env.sfcBlocks.scripts.push(sfcBlock);
      if (SCRIPT_SETUP_TAG_OPEN_REGEXP.test(sfcBlock.tagOpen)) {
        env.sfcBlocks.scriptSetup = sfcBlock;
      } else {
        env.sfcBlocks.script = sfcBlock;
      }
    } else if (sfcBlock.type === TAG_NAME_STYLE) {
      env.sfcBlocks.styles.push(sfcBlock);
    } else {
      env.sfcBlocks.customBlocks.push(sfcBlock);
    }
    return "";
  };
};

export { SCRIPT_SETUP_TAG_OPEN_REGEXP, TAG_NAME_SCRIPT, TAG_NAME_STYLE, TAG_NAME_TEMPLATE, createSfcRegexp, sfcPlugin };
/LICENSEIThe MIT License (MIT)

Copyright (c) 2022-present, mdit-vue Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/README.md # @mdit-vue/plugin-sfc

[![npm](https://badgen.net/npm/v/@mdit-vue/plugin-sfc)](https://www.npmjs.com/package/@mdit-vue/plugin-sfc)
[![license](https://badgen.net/github/license/mdit-vue/mdit-vue)](https://github.com/mdit-vue/mdit-vue/blob/main/LICENSE)

A [markdown-it](https://github.com/markdown-it/markdown-it) plugin to help transforming markdown to [Vue SFC](https://vuejs.org/guide/scaling-up/sfc.html).

- Avoids rendering `<script>` and `<style>` tags and extract them into to markdown-it `env.sfcBlocks`.
- Supports extracting custom blocks.
- Provides `env.sfcBlocks.template` for convenience.

## Install

```sh
npm i @mdit-vue/plugin-sfc
```

## Usage

This plugin will only take effects when the `html` option of markdown-it is enabled:

```ts
import MarkdownIt from 'markdown-it';
import { sfcPlugin } from '@mdit-vue/plugin-sfc';
import type { MarkdownItEnv } from '@mdit-vue/types';

const md = MarkdownIt({ html: true }).use(sfcPlugin, {
  // options
});
const env: MarkdownItEnv = {};

const rendered = md.render(
  `\
# foo

<script>
console.log('bar')
</script>
`,
  env,
);

console.log(env.sfcBlocks);
```

## Options

### customBlocks

- Type: `string[]`

- Default: `[]`

- Details:

  SFC custom blocks to be extracted.

  By default, only `<script>` and `<style>` tags will be extracted. You can set this option to support SFC custom blocks in markdown.

  For example, if you set this option to `['i18n']`, the `<i18n>` tag in your markdown content will be extracted to `env.sfcBlocks.customBlocks` and won't appear in the rendered result.
/dist/index.cjs	}'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const TAG_NAME_SCRIPT = "script";
const TAG_NAME_STYLE = "style";
const TAG_NAME_TEMPLATE = "template";

const SCRIPT_SETUP_TAG_OPEN_REGEXP = /^<script\s+.*?\bsetup\b.*?>$/is;
const createSfcRegexp = ({
  customBlocks
}) => {
  const sfcTags = Array.from(
    /* @__PURE__ */ new Set([TAG_NAME_SCRIPT, TAG_NAME_STYLE, ...customBlocks])
  ).join("|");
  return new RegExp(
    `^\\s*(?<content>(?<tagOpen><(?<type>${sfcTags})\\s?.*?>)(?<contentStripped>.*)(?<tagClose><\\/\\k<type>\\s*>))\\s*$`,
    "is"
  );
};

const sfcPlugin = (md, { customBlocks = [] } = {}) => {
  const sfcRegexp = createSfcRegexp({ customBlocks });
  const render = md.render.bind(md);
  md.render = (src, env = {}) => {
    env.sfcBlocks = {
      template: null,
      script: null,
      scriptSetup: null,
      scripts: [],
      styles: [],
      customBlocks: []
    };
    const rendered = render(src, env);
    env.sfcBlocks.template = {
      type: TAG_NAME_TEMPLATE,
      content: `<${TAG_NAME_TEMPLATE}>${rendered}</${TAG_NAME_TEMPLATE}>`,
      contentStripped: rendered,
      tagOpen: `<${TAG_NAME_TEMPLATE}>`,
      tagClose: `</${TAG_NAME_TEMPLATE}>`
    };
    return rendered;
  };
  const htmlBlockRule = md.renderer.rules.html_block;
  md.renderer.rules.html_block = (tokens, idx, options, env, self) => {
    if (!env.sfcBlocks) {
      return htmlBlockRule(tokens, idx, options, env, self);
    }
    const token = tokens[idx];
    const content = token.content;
    const match = content.match(sfcRegexp);
    if (!match) {
      return htmlBlockRule(tokens, idx, options, env, self);
    }
    const sfcBlock = match.groups;
    if (sfcBlock.type === TAG_NAME_SCRIPT) {
      env.sfcBlocks.scripts.push(sfcBlock);
      if (SCRIPT_SETUP_TAG_OPEN_REGEXP.test(sfcBlock.tagOpen)) {
        env.sfcBlocks.scriptSetup = sfcBlock;
      } else {
        env.sfcBlocks.script = sfcBlock;
      }
    } else if (sfcBlock.type === TAG_NAME_STYLE) {
      env.sfcBlocks.styles.push(sfcBlock);
    } else {
      env.sfcBlocks.customBlocks.push(sfcBlock);
    }
    return "";
  };
};

exports.SCRIPT_SETUP_TAG_OPEN_REGEXP = SCRIPT_SETUP_TAG_OPEN_REGEXP;
exports.TAG_NAME_SCRIPT = TAG_NAME_SCRIPT;
exports.TAG_NAME_STYLE = TAG_NAME_STYLE;
exports.TAG_NAME_TEMPLATE = TAG_NAME_TEMPLATE;
exports.createSfcRegexp = createSfcRegexp;
exports.sfcPlugin = sfcPlugin;


================================================
FILE: tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3NoYXJlZEAwLjExLjI=
================================================
/README.md# @mdit-vue/shared

[![npm](https://badgen.net/npm/v/@mdit-vue/shared)](https://www.npmjs.com/package/@mdit-vue/shared)

Shared utils of mdit-vue.

## Install

```sh
npm i @mdit-vue/shared
```
/dist/index.d.ts_import { MarkdownItHeader } from '@mdit-vue/types';
import Token from 'markdown-it/lib/token.js';

/**
 * Escape html chars
 */
declare const htmlEscape: (str: string) => string;

/**
 * Unescape html chars
 */
declare const htmlUnescape: (str: string) => string;

interface ResolveTitleOptions {
    /**
     * Should allow inline HTML tags or not.
     *
     * If the result is going to be used as Vue template, it should allow inline
     * HTML tags so that Vue custom components would be kept.
     */
    shouldAllowHtml: boolean;
    /**
     * Should escape the text content or not.
     *
     * If the result is going to be used in HTML directly, it should be escaped
     * so that the text content won't be wrongly treated as HTML tags.
     */
    shouldEscapeText: boolean;
}
/**
 * Resolve header title from markdown-it token
 *
 * Typically using the next token of `heading_open` token
 */
declare const resolveTitleFromToken: (token: Token, { shouldAllowHtml, shouldEscapeText }: ResolveTitleOptions) => string;

interface ResolveHeadersOptions extends ResolveTitleOptions {
    /**
     * Heading level that going to be resolved
     */
    level: number[];
    /**
     * A custom slugification function
     *
     * Would be ignored if the `id` attr of the token is set.
     */
    slugify: (str: string) => string;
    /**
     * A function for formatting headings
     */
    format?: (str: string) => string;
}
/**
 * Resolve headers from markdown-it tokens
 */
declare const resolveHeadersFromTokens: (tokens: Token[], { level, shouldAllowHtml, shouldEscapeText, slugify, format, }: ResolveHeadersOptions) => MarkdownItHeader[];

/**
 * Default slugification function
 */
declare const slugify: (str: string) => string;

export { ResolveHeadersOptions, ResolveTitleOptions, htmlEscape, htmlUnescape, resolveHeadersFromTokens, resolveTitleFromToken, slugify };
/dist/index.mjs-const htmlEscapeMap = {
  "&": "&amp;",
  "<": "&lt;",
  ">": "&gt;",
  "'": "&#39;",
  '"': "&quot;"
};
const htmlEscapeRegexp = /[&<>'"]/g;
const htmlEscape = (str) => str.replace(
  htmlEscapeRegexp,
  (char) => htmlEscapeMap[char]
);

const htmlUnescapeMap = {
  "&amp;": "&",
  "&#38;": "&",
  "&lt;": "<",
  "&#60;": "<",
  "&gt;": ">",
  "&#62;": ">",
  "&apos;": "'",
  "&#39;": "'",
  "&quot;": '"',
  "&#34;": '"'
};
const htmlUnescapeRegexp = /&(amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g;
const htmlUnescape = (str) => str.replace(
  htmlUnescapeRegexp,
  (char) => htmlUnescapeMap[char]
);

const resolveTitleFromToken = (token, { shouldAllowHtml, shouldEscapeText }) => {
  const children = token.children ?? [];
  const titleTokenTypes = ["text", "emoji", "code_inline"];
  if (shouldAllowHtml) {
    titleTokenTypes.push("html_inline");
  }
  const titleTokens = children.filter(
    (item) => titleTokenTypes.includes(item.type) && !item.meta?.isPermalinkSymbol
  );
  return titleTokens.reduce((result, item) => {
    if (shouldEscapeText) {
      if (item.type === "code_inline" || item.type === "text") {
        return `${result}${htmlEscape(item.content)}`;
      }
    }
    return `${result}${item.content}`;
  }, "").trim();
};

con
Download .txt
gitextract_k7rtrazz/

├── .codesandbox/
│   └── tasks.json
├── .editorconfig
├── .env.example
├── .env.test
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .release-please-manifest.json
├── ATTRIBUTIONS.md
├── LICENSE
├── README.md
├── dnsmasq.conf
├── internals/
│   ├── esbuild-plugins/
│   │   ├── inline-file.ts
│   │   └── inline-worker.ts
│   └── servers/
│       ├── consumer/
│       │   ├── build.ts
│       │   ├── dist/
│       │   │   └── index.html
│       │   └── serve.ts
│       ├── main-server.ts
│       ├── preview-server.ts
│       ├── test/
│       │   ├── index.html
│       │   └── test-server.ts
│       └── utils.ts
├── package.json
├── packages/
│   ├── nodebox/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── api.md
│   │   ├── build.ts
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── Nodebox.ts
│   │   │   ├── index.ts
│   │   │   ├── logger.ts
│   │   │   ├── messages.ts
│   │   │   ├── modules/
│   │   │   │   ├── fs.ts
│   │   │   │   ├── preview.ts
│   │   │   │   └── shell.ts
│   │   │   └── runtime-protocol.types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   └── utils/
│       ├── jest.config.js
│       ├── package.json
│       ├── withTimeout.test.ts
│       └── withTimeout.ts
├── playwright.config.ts
├── pnpm-workspace.yaml
├── public/
│   └── ws-test.pack
├── release-please-config.json
├── req.conf
├── sync-repo.js
├── tests/
│   ├── cdn-proxy/
│   │   └── v2/
│   │       ├── deps/
│   │       │   ├── QGFwb2xsby9zZXJ2ZXJANC4xLjE7Z3JhcGhxbEAxNi42LjA=
│   │       │   ├── QHN2ZWx0ZWpzL3ZpdGUtcGx1Z2luLXN2ZWx0ZUAyLjAuMztlc2J1aWxkLXdhc21AMC4xNy4xMjtzdmVsdGVAMy41Ny4wO3ZpdGVANC4yLjA=
│   │       │   ├── QHZpdGVqcy9wbHVnaW4tcmVhY3RAMy4xLjA7ZXNidWlsZC13YXNtQDAuMTcuMTI7cmVhY3QtZG9tQF4xOC4yLjA7cmVhY3RAXjE4LjIuMDt2aXRlQDQuMi4w
│   │       │   ├── QHZpdGVqcy9wbHVnaW4tdnVlQDQuMS4wO2VzYnVpbGQtd2FzbUAwLjE3LjEyO3ZpdGVANC4yLjA7dnVlQGxhdGVzdA==
│   │       │   ├── ZXNidWlsZC13YXNtQDAuMTUuMTI7dnVlcHJlc3NAMi4wLjAtYmV0YS41Mw==
│   │       │   ├── ZXNidWlsZC13YXNtQDAuMTcuMTI7dml0ZUA0LjIuMA==
│   │       │   ├── ZXNsaW50QF44LjAuMQ==
│   │       │   ├── ZXhwcmVzc0A0LjE4LjI=
│   │       │   ├── ZmFzdGlmeUBsYXRlc3Q=
│   │       │   └── bm9kZS1mZXRjaEAzLjMuMA==
│   │       └── mod/
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi10aXRsZUAwLjExLjI=
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi10b2NAMC4xMS4y
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1jb21wb25lbnRAMC4xMS4y
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1mcm9udG1hdHRlckAwLjExLjE=
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1oZWFkZXJzQDAuMTEuMg==
│   │           ├── QG1kaXQtdnVlL3BsdWdpbi1zZmNAMC4xMS4x
│   │           ├── QG1kaXQtdnVlL3NoYXJlZEAwLjExLjI=
│   │           ├── QG1kaXQtdnVlL3R5cGVzQDAuMTEuMA==
│   │           ├── QG5vZGVsaWIvZnMuc2NhbmRpckAyLjEuNQ==
│   │           ├── QG5vZGVsaWIvZnMuc3RhdEAyLjAuNQ==
│   │           ├── QG5vZGVsaWIvZnMud2Fsa0AxLjIuOA==
│   │           ├── QGFtcHByb2plY3QvcmVtYXBwaW5nQDIuMi4w
│   │           ├── QGFwb2xsby91c2FnZS1yZXBvcnRpbmctcHJvdG9idWZANC4xLjA=
│   │           ├── QGFwb2xsby91dGlscy51c2FnZXJlcG9ydGluZ0AxLjAuMQ==
│   │           ├── QGFwb2xsby91dGlscy53aXRocmVxdWlyZWRAMS4wLjE=
│   │           ├── QGFwb2xsby91dGlscy5jcmVhdGVoYXNoQDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5kcm9wdW51c2VkZGVmaW5pdGlvbnNAMS4xLjA=
│   │           ├── QGFwb2xsby91dGlscy5mZXRjaGVyQDEuMS4x
│   │           ├── QGFwb2xsby91dGlscy5mZXRjaGVyQDIuMC4w
│   │           ├── QGFwb2xsby91dGlscy5pc25vZGVsaWtlQDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5rZXl2YWx1ZWNhY2hlQDEuMC4y
│   │           ├── QGFwb2xsby91dGlscy5rZXl2YWx1ZWNhY2hlQDIuMS4w
│   │           ├── QGFwb2xsby91dGlscy5sb2dnZXJAMS4wLjE=
│   │           ├── QGFwb2xsby91dGlscy5sb2dnZXJAMi4wLjA=
│   │           ├── QGFwb2xsby91dGlscy5wcmludHdpdGhyZWR1Y2Vkd2hpdGVzcGFjZUAxLjEuMA==
│   │           ├── QGFwb2xsby91dGlscy5yZW1vdmVhbGlhc2VzQDEuMC4w
│   │           ├── QGFwb2xsby91dGlscy5zb3J0YXN0QDEuMS4w
│   │           ├── QGFwb2xsby91dGlscy5zdHJpcHNlbnNpdGl2ZWxpdGVyYWxzQDEuMi4w
│   │           ├── QGFwb2xsby9jYWNoZS1jb250cm9sLXR5cGVzQDEuMC4y
│   │           ├── QGFwb2xsby9wcm90b2J1ZmpzQDEuMi43
│   │           ├── QGFwb2xsby9zZXJ2ZXItZ2F0ZXdheS1pbnRlcmZhY2VAMS4xLjA=
│   │           ├── QGFwb2xsby9zZXJ2ZXJANC4xLjE=
│   │           ├── QGJhYmVsL2NvZGUtZnJhbWVANy4xOC42
│   │           ├── QGJhYmVsL2NvbXBhdC1kYXRhQDcuMjEuMA==
│   │           ├── QGJhYmVsL2NvcmVANy4yMS4z
│   │           ├── QGJhYmVsL2dlbmVyYXRvckA3LjIxLjM=
│   │           ├── QGJhYmVsL2hlbHBlci12YWxpZGF0b3ItaWRlbnRpZmllckA3LjE5LjE=
│   │           ├── QGJhYmVsL2hlbHBlci12YWxpZGF0b3Itb3B0aW9uQDcuMjEuMA==
│   │           ├── QGJhYmVsL2hlbHBlci1jb21waWxhdGlvbi10YXJnZXRzQDcuMjAuNw==
│   │           ├── QGJhYmVsL2hlbHBlci1lbnZpcm9ubWVudC12aXNpdG9yQDcuMTguOQ==
│   │           ├── QGJhYmVsL2hlbHBlci1mdW5jdGlvbi1uYW1lQDcuMjEuMA==
│   │           ├── QGJhYmVsL2hlbHBlci1ob2lzdC12YXJpYWJsZXNANy4xOC42
│   │           ├── QGJhYmVsL2hlbHBlci1tb2R1bGUtaW1wb3J0c0A3LjE4LjY=
│   │           ├── QGJhYmVsL2hlbHBlci1tb2R1bGUtdHJhbnNmb3Jtc0A3LjIxLjI=
│   │           ├── QGJhYmVsL2hlbHBlci1wbHVnaW4tdXRpbHNANy4yMC4y
│   │           ├── QGJhYmVsL2hlbHBlci1zaW1wbGUtYWNjZXNzQDcuMjAuMg==
│   │           ├── QGJhYmVsL2hlbHBlci1zcGxpdC1leHBvcnQtZGVjbGFyYXRpb25ANy4xOC42
│   │           ├── QGJhYmVsL2hlbHBlci1zdHJpbmctcGFyc2VyQDcuMTkuNA==
│   │           ├── QGJhYmVsL2hlbHBlcnNANy4yMS4w
│   │           ├── QGJhYmVsL2hpZ2hsaWdodEA3LjE4LjY=
│   │           ├── QGJhYmVsL3BhcnNlckA3LjIxLjM=
│   │           ├── QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNlbGZANy4yMS4w
│   │           ├── QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNvdXJjZUA3LjE5LjY=
│   │           ├── QGJhYmVsL3R5cGVzQDcuMjEuMw==
│   │           ├── QGJhYmVsL3RlbXBsYXRlQDcuMjAuNw==
│   │           ├── QGJhYmVsL3RyYXZlcnNlQDcuMjEuMw==
│   │           ├── QGVzbGludC9lc2xpbnRyY0AxLjQuMQ==
│   │           ├── QGZhc3RpZnkvYWp2LWNvbXBpbGVyQDMuNS4w
│   │           ├── QGZhc3RpZnkvZGVlcG1lcmdlQDEuMy4w
│   │           ├── QGZhc3RpZnkvZXJyb3JAMy4yLjA=
│   │           ├── QGZhc3RpZnkvZmFzdC1qc29uLXN0cmluZ2lmeS1jb21waWxlckA0LjIuMA==
│   │           ├── QGdyYXBocWwtdG9vbHMvbWVyZ2VAOC4zLjEx
│   │           ├── QGdyYXBocWwtdG9vbHMvc2NoZW1hQDkuMC45
│   │           ├── QGdyYXBocWwtdG9vbHMvdXRpbHNAOS4xLjA=
│   │           ├── QGh1bWFud2hvY29kZXMvY29uZmlnLWFycmF5QDAuOS41
│   │           ├── QGh1bWFud2hvY29kZXMvb2JqZWN0LXNjaGVtYUAxLjIuMQ==
│   │           ├── QGpvc2VwaGcvcmVzb2x2YWJsZUAxLjAuMQ==
│   │           ├── QGpyaWRnZXdlbGwvZ2VuLW1hcHBpbmdAMC4zLjI=
│   │           ├── QGpyaWRnZXdlbGwvc291cmNlbWFwLWNvZGVjQDEuNC4xNA==
│   │           ├── QGpyaWRnZXdlbGwvc2V0LWFycmF5QDEuMS4y
│   │           ├── QGpyaWRnZXdlbGwvcmVzb2x2ZS11cmlAMy4xLjA=
│   │           ├── QGpyaWRnZXdlbGwvdHJhY2UtbWFwcGluZ0AwLjMuMTc=
│   │           ├── QHByb3RvYnVmanMvY29kZWdlbkAyLjAuNA==
│   │           ├── QHByb3RvYnVmanMvYXNwcm9taXNlQDEuMS4y
│   │           ├── QHByb3RvYnVmanMvYmFzZTY0QDEuMS4y
│   │           ├── QHByb3RvYnVmanMvZXZlbnRlbWl0dGVyQDEuMS4w
│   │           ├── QHByb3RvYnVmanMvZmV0Y2hAMS4xLjA=
│   │           ├── QHByb3RvYnVmanMvZmxvYXRAMS4wLjI=
│   │           ├── QHByb3RvYnVmanMvaW5xdWlyZUAxLjEuMA==
│   │           ├── QHByb3RvYnVmanMvcG9vbEAxLjEuMA==
│   │           ├── QHByb3RvYnVmanMvcGF0aEAxLjEuMg==
│   │           ├── QHByb3RvYnVmanMvdXRmOEAxLjEuMA==
│   │           ├── QHN2ZWx0ZWpzL3ZpdGUtcGx1Z2luLXN2ZWx0ZUAyLjAuMw==
│   │           ├── QHR5cGVzL21hcmtkb3duLWl0LWVtb2ppQDIuMC4y
│   │           ├── QHR5cGVzL21hcmtkb3duLWl0QDEyLjIuMw==
│   │           ├── QHR5cGVzL21kdXJsQDEuMC4y
│   │           ├── QHR5cGVzL21pbWVAMy4wLjE=
│   │           ├── QHR5cGVzL21zQDAuNy4zMQ==
│   │           ├── QHR5cGVzL25vZGUtZmV0Y2hAMi42LjI=
│   │           ├── QHR5cGVzL25vZGVAOS42Ljk=
│   │           ├── QHR5cGVzL2JvZHktcGFyc2VyQDEuMTkuMg==
│   │           ├── QHR5cGVzL2Nvbm5lY3RAMy40LjM1
│   │           ├── QHR5cGVzL2RlYnVnQDQuMS43
│   │           ├── QHR5cGVzL2V4cHJlc3Mtc2VydmUtc3RhdGljLWNvcmVANC4xNy4zMw==
│   │           ├── QHR5cGVzL2V4cHJlc3NANC4xNy4xNw==
│   │           ├── QHR5cGVzL2ZzLWV4dHJhQDkuMC4xMw==
│   │           ├── QHR5cGVzL2hhc2gtc3VtQDEuMC4w
│   │           ├── QHR5cGVzL2xpbmtpZnktaXRAMy4wLjI=
│   │           ├── QHR5cGVzL2xvbmdANC4wLjI=
│   │           ├── QHR5cGVzL3FzQDYuOS43
│   │           ├── QHR5cGVzL3JhbmdlLXBhcnNlckAxLjIuNA==
│   │           ├── QHR5cGVzL3NlcnZlLXN0YXRpY0AxLjcuMzI=
│   │           ├── QHR5cGVzL3dlYi1ibHVldG9vdGhAMC4wLjE2
│   │           ├── QHZ1ZS9jb21waWxlci1jb3JlQDMuMi40Nw==
│   │           ├── QHZ1ZS9jb21waWxlci1kb21AMy4yLjQ3
│   │           ├── QHZ1ZS9jb21waWxlci1zZmNAMy4yLjQ3
│   │           ├── QHZ1ZS9jb21waWxlci1zc3JAMy4yLjQ3
│   │           ├── QHZ1ZS9kZXZ0b29scy1hcGlANi41LjA=
│   │           ├── QHZ1ZS9yZWFjdGl2aXR5LXRyYW5zZm9ybUAzLjIuNDc=
│   │           ├── QHZ1ZS9yZWFjdGl2aXR5QDMuMi40Nw==
│   │           ├── QHZ1ZS9ydW50aW1lLWNvcmVAMy4yLjQ3
│   │           ├── QHZ1ZS9ydW50aW1lLWRvbUAzLjIuNDc=
│   │           ├── QHZ1ZS9zZXJ2ZXItcmVuZGVyZXJAMy4yLjQ3
│   │           ├── QHZ1ZS9zaGFyZWRAMy4yLjQ3
│   │           ├── QHZ1ZXByZXNzL21hcmtkb3duQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL2J1bmRsZXItdml0ZUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NsaUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NsaWVudEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL2NvcmVAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi10aGVtZS1kYXRhQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1hY3RpdmUtaGVhZGVyLWxpbmtzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1iYWNrLXRvLXRvcEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1jb250YWluZXJAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1leHRlcm5hbC1saW5rLWljb25AMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1naXRAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1tZWRpdW0tem9vbUAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1ucHJvZ3Jlc3NAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1wYWxldHRlQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3BsdWdpbi1wcmlzbWpzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXByZXNzL3NoYXJlZEAyLjAuMC1iZXRhLjUz
│   │           ├── QHZ1ZXByZXNzL3RoZW1lLWRlZmF1bHRAMi4wLjAtYmV0YS41Mw==
│   │           ├── QHZ1ZXByZXNzL3V0aWxzQDIuMC4wLWJldGEuNTM=
│   │           ├── QHZ1ZXVzZS9jb3JlQDkuOS4w
│   │           ├── QHZ1ZXVzZS9tZXRhZGF0YUA5LjkuMA==
│   │           ├── QHZ1ZXVzZS9zaGFyZWRAOS45LjA=
│   │           ├── QHZpdGVqcy9wbHVnaW4tcmVhY3RAMy4xLjA=
│   │           ├── QHZpdGVqcy9wbHVnaW4tdnVlQDMuMi4w
│   │           ├── QHZpdGVqcy9wbHVnaW4tdnVlQDQuMS4w
│   │           ├── Y29sb3ItY29udmVydEAxLjkuMw==
│   │           ├── Y29sb3ItY29udmVydEAyLjAuMQ==
│   │           ├── Y29sb3ItbmFtZUAxLjEuMw==
│   │           ├── Y29sb3ItbmFtZUAxLjEuNA==
│   │           ├── Y29tYmluZWQtc3RyZWFtQDEuMC44
│   │           ├── Y29uY2F0LW1hcEAwLjAuMQ==
│   │           ├── Y29ubmVjdC1oaXN0b3J5LWFwaS1mYWxsYmFja0AyLjAuMA==
│   │           ├── Y29udGVudC10eXBlQDEuMC41
│   │           ├── Y29udGVudC1kaXNwb3NpdGlvbkAwLjUuNA==
│   │           ├── Y29udmVydC1zb3VyY2UtbWFwQDEuOS4w
│   │           ├── Y29va2llLXNpZ25hdHVyZUAxLjAuNg==
│   │           ├── Y29va2llQDAuNS4w
│   │           ├── Y29yc0AyLjguNQ==
│   │           ├── Y2FjQDYuNy4xNA==
│   │           ├── Y2FsbC1iaW5kQDEuMC4y
│   │           ├── Y2FsbHNpdGVzQDMuMS4w
│   │           ├── Y2FuaXVzZS1saXRlQDEuMC4zMDAwMTQ2OA==
│   │           ├── Y2hhbGtAMi40LjI=
│   │           ├── Y2hhbGtANC4xLjI=
│   │           ├── Y2hhbGtANS4yLjA=
│   │           ├── Y2hva2lkYXJAMy41LjM=
│   │           ├── Y2xpLWN1cnNvckA0LjAuMA==
│   │           ├── Y2xpLXNwaW5uZXJzQDIuNy4w
│   │           ├── Y2xvbmVAMS4wLjQ=
│   │           ├── Y3Jvc3Mtc3Bhd25ANy4wLjM=
│   │           ├── Y3NzdHlwZUAyLjYuOQ==
│   │           ├── YW55bWF0Y2hAMy4xLjM=
│   │           ├── YW5zaS1yZWdleEA1LjAuMQ==
│   │           ├── YW5zaS1yZWdleEA2LjAuMQ==
│   │           ├── YW5zaS1zdHlsZXNAMy4yLjE=
│   │           ├── YW5zaS1zdHlsZXNANC4zLjA=
│   │           ├── YWJvcnQtY29udHJvbGxlckAzLjAuMA==
│   │           ├── YWJzdHJhY3QtbG9nZ2luZ0AyLjAuMQ==
│   │           ├── YWNjZXB0c0AxLjMuOA==
│   │           ├── YWNvcm4tanN4QDUuMy4y
│   │           ├── YWNvcm5AOC44LjI=
│   │           ├── YWp2LWZvcm1hdHNAMi4xLjE=
│   │           ├── YWp2QDYuMTIuNg==
│   │           ├── YWp2QDguMTIuMA==
│   │           ├── YXJjaHlAMS4wLjA=
│   │           ├── YXJncGFyc2VAMS4wLjk=
│   │           ├── YXJncGFyc2VAMi4wLjE=
│   │           ├── YXJyYXktZmxhdHRlbkAxLjEuMQ==
│   │           ├── YXN5bmMtcmV0cnlAMS4zLjM=
│   │           ├── YXN5bmNraXRAMC40LjA=
│   │           ├── YXRvbWljLXNsZWVwQDEuMC4w
│   │           ├── YXV0b3ByZWZpeGVyQDEwLjQuMTQ=
│   │           ├── YXZ2aW9AOC4yLjE=
│   │           ├── Ym9keS1wYXJzZXJAMS4yMC4x
│   │           ├── Ym9keS1wYXJzZXJAMS4yMC4y
│   │           ├── YmFsYW5jZWQtbWF0Y2hAMS4wLjI=
│   │           ├── YmFzZTY0LWpzQDEuNS4x
│   │           ├── YmluYXJ5LWV4dGVuc2lvbnNAMi4yLjA=
│   │           ├── YmxANS4xLjA=
│   │           ├── YnJhY2UtZXhwYW5zaW9uQDEuMS45
│   │           ├── YnJhY2VzQDMuMC4y
│   │           ├── YnJvd3NlcnNsaXN0QDQuMjEuNQ==
│   │           ├── YnVmZmVyQDYuMC4z
│   │           ├── Ynl0ZXNAMy4xLjI=
│   │           ├── Z2V0LWludHJpbnNpY0AxLjIuMA==
│   │           ├── Z2V0LXN0cmVhbUA2LjAuMQ==
│   │           ├── Z2Vuc3luY0AxLjAuMC1iZXRhLjI=
│   │           ├── Z2xvYi1wYXJlbnRANS4xLjI=
│   │           ├── Z2xvYi1wYXJlbnRANi4wLjI=
│   │           ├── Z2xvYkA3LjIuMw==
│   │           ├── Z2xvYmFsc0AxMS45LjA=
│   │           ├── Z2xvYmFsc0AxMy4yMC4w
│   │           ├── Z2xvYmJ5QDEzLjEuMw==
│   │           ├── Z3JhY2VmdWwtZnNANC4yLjk=
│   │           ├── Z3JhcGhxbEAxNi42LjA=
│   │           ├── Z3JheS1tYXR0ZXJANC4wLjM=
│   │           ├── ZG9jdHJpbmVAMy4wLjA=
│   │           ├── ZGF0YS11cmktdG8tYnVmZmVyQDQuMC4x
│   │           ├── ZGVidWdAMi42Ljk=
│   │           ├── ZGVidWdANC4zLjQ=
│   │           ├── ZGVlcC1pc0AwLjEuNA==
│   │           ├── ZGVlcG1lcmdlQDQuMy4x
│   │           ├── ZGVmYXVsdHNAMS4wLjQ=
│   │           ├── ZGVsYXllZC1zdHJlYW1AMS4wLjA=
│   │           ├── ZGVwZEAyLjAuMA==
│   │           ├── ZGVzdHJveUAxLjIuMA==
│   │           ├── ZGlyLWdsb2JAMy4wLjE=
│   │           ├── ZW50aXRpZXNAMy4wLjE=
│   │           ├── ZW52aW5mb0A3LjguMQ==
│   │           ├── ZW5jb2RldXJsQDEuMC4y
│   │           ├── ZWUtZmlyc3RAMS4xLjE=
│   │           ├── ZWxlY3Ryb24tdG8tY2hyb21pdW1AMS40LjMzMw==
│   │           ├── ZXN0cmF2ZXJzZUA1LjMuMA==
│   │           ├── ZXN0cmVlLXdhbGtlckAyLjAuMg==
│   │           ├── ZXN1dGlsc0AyLjAuMw==
│   │           ├── ZXNidWlsZC13YXNtQDAuMTUuMTI=
│   │           ├── ZXNidWlsZC13YXNtQDAuMTcuMTI=
│   │           ├── ZXNidWlsZEAwLjE1LjE4
│   │           ├── ZXNidWlsZEAwLjE3Ljk=
│   │           ├── ZXNjYWxhZGVAMy4xLjE=
│   │           ├── ZXNjYXBlLWh0bWxAMS4wLjM=
│   │           ├── ZXNjYXBlLXN0cmluZy1yZWdleHBAMS4wLjU=
│   │           ├── ZXNjYXBlLXN0cmluZy1yZWdleHBANC4wLjA=
│   │           ├── ZXNsaW50LXNjb3BlQDcuMS4x
│   │           ├── ZXNsaW50LXV0aWxzQDMuMC4w
│   │           ├── ZXNsaW50LXZpc2l0b3Ita2V5c0AyLjEuMA==
│   │           ├── ZXNsaW50LXZpc2l0b3Ita2V5c0AzLjMuMA==
│   │           ├── ZXNsaW50QDguOS4w
│   │           ├── ZXNwcmVlQDkuNS4w
│   │           ├── ZXNwcmltYUA0LjAuMQ==
│   │           ├── ZXNxdWVyeUAxLjUuMA==
│   │           ├── ZXNyZWN1cnNlQDQuMy4w
│   │           ├── ZXRhZ0AxLjguMQ==
│   │           ├── ZXZlbnQtdGFyZ2V0LXNoaW1ANS4wLjE=
│   │           ├── ZXZlbnRzQDMuMy4w
│   │           ├── ZXh0ZW5kLXNoYWxsb3dAMi4wLjE=
│   │           ├── ZXhlY2FANi4xLjA=
│   │           ├── ZXhwcmVzc0A0LjE4LjI=
│   │           ├── Zm9ybS1kYXRhQDMuMC4x
│   │           ├── Zm9ybWRhdGEtcG9seWZpbGxANC4wLjEw
│   │           ├── Zm9yd2FyZGVkQDAuMi4w
│   │           ├── ZmFzdC11cmlAMi4yLjA=
│   │           ├── ZmFzdC1jb250ZW50LXR5cGUtcGFyc2VAMS4wLjA=
│   │           ├── ZmFzdC1kZWNvZGUtdXJpLWNvbXBvbmVudEAxLjAuMQ==
│   │           ├── ZmFzdC1kZWVwLWVxdWFsQDMuMS4z
│   │           ├── ZmFzdC1nbG9iQDMuMi4xMg==
│   │           ├── ZmFzdC1qc29uLXN0YWJsZS1zdHJpbmdpZnlAMi4xLjA=
│   │           ├── ZmFzdC1qc29uLXN0cmluZ2lmeUA1LjYuMg==
│   │           ├── ZmFzdC1sZXZlbnNodGVpbkAyLjAuNg==
│   │           ├── ZmFzdC1xdWVyeXN0cmluZ0AxLjEuMQ==
│   │           ├── ZmFzdC1yZWRhY3RAMy4xLjI=
│   │           ├── ZmFzdGlmeUA0LjE0LjE=
│   │           ├── ZmFzdHFAMS45LjA=
│   │           ├── ZmV0Y2gtYmxvYkAzLjIuMA==
│   │           ├── ZmlsZS1lbnRyeS1jYWNoZUA2LjAuMQ==
│   │           ├── ZmlsbC1yYW5nZUA3LjAuMQ==
│   │           ├── ZmluYWxoYW5kbGVyQDEuMi4w
│   │           ├── ZmluZC1teS13YXlANy42LjA=
│   │           ├── ZmxhdC1jYWNoZUAzLjAuNA==
│   │           ├── ZmxhdHRlZEAzLjIuNw==
│   │           ├── ZnJhY3Rpb24uanNANC4yLjA=
│   │           ├── ZnJlc2hAMC41LjI=
│   │           ├── ZnMtZXh0cmFAMTAuMS4w
│   │           ├── ZnMucmVhbHBhdGhAMS4wLjA=
│   │           ├── ZnVuY3Rpb24tYmluZEAxLjEuMQ==
│   │           ├── ZnVuY3Rpb25hbC1yZWQtYmxhY2stdHJlZUAxLjAuMQ==
│   │           ├── a2luZC1vZkA2LjAuMw==
│   │           ├── a2xldXJANC4xLjU=
│   │           ├── aGFzLWZsYWdAMy4wLjA=
│   │           ├── aGFzLWZsYWdANC4wLjA=
│   │           ├── aGFzLXN5bWJvbHNAMS4wLjM=
│   │           ├── aGFzQDEuMC4z
│   │           ├── aGFzaC1zdW1AMi4wLjA=
│   │           ├── aHR0cC1lcnJvcnNAMi4wLjA=
│   │           ├── aHVtYW4tc2lnbmFsc0AzLjAuMQ==
│   │           ├── aW11cm11cmhhc2hAMC4xLjQ=
│   │           ├── aW1tdXRhYmxlQDQuMy4w
│   │           ├── aW1wb3J0LWZyZXNoQDMuMy4w
│   │           ├── aW5mbGlnaHRAMS4wLjY=
│   │           ├── aW5oZXJpdHNAMi4wLjQ=
│   │           ├── aWNvbnYtbGl0ZUAwLjQuMjQ=
│   │           ├── aWVlZTc1NEAxLjIuMQ==
│   │           ├── aWdub3JlQDUuMi40
│   │           ├── aXBhZGRyLmpzQDEuOS4x
│   │           ├── aXMtY29yZS1tb2R1bGVAMi45LjA=
│   │           ├── aXMtYmluYXJ5LXBhdGhAMi4xLjA=
│   │           ├── aXMtZ2xvYkA0LjAuMw==
│   │           ├── aXMtZXh0Z2xvYkAyLjEuMQ==
│   │           ├── aXMtZXh0ZW5kYWJsZUAwLjEuMQ==
│   │           ├── aXMtaW50ZXJhY3RpdmVAMi4wLjA=
│   │           ├── aXMtbnVtYmVyQDcuMC4w
│   │           ├── aXMtc3RyZWFtQDMuMC4w
│   │           ├── aXMtdW5pY29kZS1zdXBwb3J0ZWRAMS4zLjA=
│   │           ├── aXNleGVAMi4wLjA=
│   │           ├── anMtdG9rZW5zQDQuMC4w
│   │           ├── anMteWFtbEA0LjEuMA==
│   │           ├── anMteWFtbEAzLjE0LjE=
│   │           ├── anNlc2NAMi41LjI=
│   │           ├── anNvbi1zY2hlbWEtdHJhdmVyc2VAMC40LjE=
│   │           ├── anNvbi1zY2hlbWEtdHJhdmVyc2VAMS4wLjA=
│   │           ├── anNvbi1zdGFibGUtc3RyaW5naWZ5LXdpdGhvdXQtanNvbmlmeUAxLjAuMQ==
│   │           ├── anNvbjVAMi4yLjM=
│   │           ├── anNvbmZpbGVANi4xLjA=
│   │           ├── b24tZXhpdC1sZWFrLWZyZWVAMi4xLjA=
│   │           ├── b24tZmluaXNoZWRAMi40LjE=
│   │           ├── b25jZUAxLjQuMA==
│   │           ├── b25ldGltZUA1LjEuMg==
│   │           ├── b25ldGltZUA2LjAuMA==
│   │           ├── b2JqZWN0LWFzc2lnbkA0LjEuMQ==
│   │           ├── b2JqZWN0LWluc3BlY3RAMS45LjA=
│   │           ├── b3B0aW9uYXRvckAwLjkuMQ==
│   │           ├── b3JhQDYuMi4w
│   │           ├── bG9kYXNoLm1lcmdlQDQuNi4y
│   │           ├── bG9kYXNoLnNvcnRieUA0LjcuMA==
│   │           ├── bG9nLXN5bWJvbHNANS4xLjA=
│   │           ├── bG9nbGV2ZWxAMS44LjE=
│   │           ├── bG9uZ0A0LjAuMA==
│   │           ├── bG9vc2UtZW52aWZ5QDEuNC4w
│   │           ├── bGV2bkAwLjQuMQ==
│   │           ├── bGlnaHQtbXktcmVxdWVzdEA1LjkuMQ==
│   │           ├── bGlsY29uZmlnQDIuMS4w
│   │           ├── bGlua2lmeS1pdEA0LjAuMQ==
│   │           ├── bHJ1LWNhY2hlQDUuMS4x
│   │           ├── bHJ1LWNhY2hlQDYuMC4w
│   │           ├── bHJ1LWNhY2hlQDcuMTguMw==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjUuOQ==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjcuMA==
│   │           ├── bWFnaWMtc3RyaW5nQDAuMjkuMA==
│   │           ├── bWFya2Rvd24taXQtY29udGFpbmVyQDMuMC4w
│   │           ├── bWFya2Rvd24taXQtYW5jaG9yQDguNi43
│   │           ├── bWFya2Rvd24taXQtZW1vamlAMi4wLjI=
│   │           ├── bWFya2Rvd24taXRAMTMuMC4x
│   │           ├── bWR1cmxAMS4wLjE=
│   │           ├── bWV0aG9kc0AxLjEuMg==
│   │           ├── bWVkaWEtdHlwZXJAMC4zLjA=
│   │           ├── bWVkaXVtLXpvb21AMS4wLjg=
│   │           ├── bWVyZ2UtZGVzY3JpcHRvcnNAMS4wLjE=
│   │           ├── bWVyZ2Utc3RyZWFtQDIuMC4w
│   │           ├── bWVyZ2UyQDEuNC4x
│   │           ├── bWljcm9tYXRjaEA0LjAuNQ==
│   │           ├── bWltZS10eXBlc0AyLjEuMzU=
│   │           ├── bWltZS1kYkAxLjUyLjA=
│   │           ├── bWltZUAxLjYuMA==
│   │           ├── bWltaWMtZm5AMi4xLjA=
│   │           ├── bWltaWMtZm5ANC4wLjA=
│   │           ├── bWluaW1hdGNoQDMuMS4y
│   │           ├── bXNAMi4xLjI=
│   │           ├── bXNAMi4xLjM=
│   │           ├── bm9kZS1hYm9ydC1jb250cm9sbGVyQDMuMS4x
│   │           ├── bm9kZS1kb21leGNlcHRpb25AMS4wLjA=
│   │           ├── bm9kZS1mZXRjaEAyLjYuOQ==
│   │           ├── bm9kZS1mZXRjaEAzLjMuMA==
│   │           ├── bm9kZS1yZWxlYXNlc0AyLjAuOQ==
│   │           ├── bm9ybWFsaXplLXBhdGhAMy4wLjA=
│   │           ├── bm9ybWFsaXplLXJhbmdlQDAuMS4y
│   │           ├── bmF0dXJhbC1jb21wYXJlQDEuNC4w
│   │           ├── bmFub2lkQDMuMy40
│   │           ├── bmVnb3RpYXRvckAwLjYuMw==
│   │           ├── bnBtLXJ1bi1wYXRoQDUuMS4w
│   │           ├── c291cmNlLW1hcC1qc0AxLjAuMg==
│   │           ├── c291cmNlLW1hcEAwLjYuMQ==
│   │           ├── c291cmNlbWFwLWNvZGVjQDEuNC44
│   │           ├── c29uaWMtYm9vbUAzLjIuMQ==
│   │           ├── c2FmZS1idWZmZXJANS4yLjE=
│   │           ├── c2FmZS1yZWdleDJAMi4wLjA=
│   │           ├── c2FmZS1zdGFibGUtc3RyaW5naWZ5QDIuNC4z
│   │           ├── c2FmZXItYnVmZmVyQDIuMS4y
│   │           ├── c2Fzc0AxLjU5LjM=
│   │           ├── c2NoZWR1bGVyQDAuMjMuMA==
│   │           ├── c2V0LWNvb2tpZS1wYXJzZXJAMi42LjA=
│   │           ├── c2V0cHJvdG90eXBlb2ZAMS4yLjA=
│   │           ├── c2VjdGlvbi1tYXR0ZXJAMS4wLjA=
│   │           ├── c2VjdXJlLWpzb24tcGFyc2VAMi43LjA=
│   │           ├── c2VtdmVyQDYuMy4w
│   │           ├── c2VtdmVyQDcuMy44
│   │           ├── c2VuZEAwLjE4LjA=
│   │           ├── c2VydmUtc3RhdGljQDEuMTUuMA==
│   │           ├── c2hhLmpzQDIuNC4xMQ==
│   │           ├── c2hlYmFuZy1jb21tYW5kQDIuMC4w
│   │           ├── c2hlYmFuZy1yZWdleEAzLjAuMA==
│   │           ├── c2lkZS1jaGFubmVsQDEuMC40
│   │           ├── c2lnbmFsLWV4aXRAMy4wLjc=
│   │           ├── c2xhc2hANC4wLjA=
│   │           ├── c3BsaXQyQDQuMS4w
│   │           ├── c3ByaW50Zi1qc0AxLjAuMw==
│   │           ├── c3RhdHVzZXNAMi4wLjE=
│   │           ├── c3RkaW4tZGlzY2FyZGVyQDAuMS4w
│   │           ├── c3RyaW5nX2RlY29kZXJAMS4zLjA=
│   │           ├── c3RyaXAtYW5zaUA2LjAuMQ==
│   │           ├── c3RyaXAtYW5zaUA3LjAuMQ==
│   │           ├── c3RyaXAtYm9tLXN0cmluZ0AxLjAuMA==
│   │           ├── c3RyaXAtZmluYWwtbmV3bGluZUAzLjAuMA==
│   │           ├── c3RyaXAtanNvbi1jb21tZW50c0AzLjEuMQ==
│   │           ├── c3VwcG9ydHMtY29sb3JANS41LjA=
│   │           ├── c3VwcG9ydHMtY29sb3JANy4yLjA=
│   │           ├── c3VwcG9ydHMtcHJlc2VydmUtc3ltbGlua3MtZmxhZ0AxLjAuMA==
│   │           ├── c3ZlbHRlLWhtckAwLjE1LjE=
│   │           ├── c3ZlbHRlQDMuNTcuMA==
│   │           ├── cG9zdGNzc0A4LjQuMjE=
│   │           ├── cG9zdGNzcy12YWx1ZS1wYXJzZXJANC4yLjA=
│   │           ├── cG9zdGNzcy1sb2FkLWNvbmZpZ0A0LjAuMQ==
│   │           ├── cGF0aC10by1yZWdleHBAMC4xLjc=
│   │           ├── cGF0aC10eXBlQDQuMC4w
│   │           ├── cGF0aC1pcy1hYnNvbHV0ZUAxLjAuMQ==
│   │           ├── cGF0aC1rZXlAMy4xLjE=
│   │           ├── cGF0aC1rZXlANC4wLjA=
│   │           ├── cGF0aC1wYXJzZUAxLjAuNw==
│   │           ├── cGFyZW50LW1vZHVsZUAxLjAuMQ==
│   │           ├── cGFyc2V1cmxAMS4zLjM=
│   │           ├── cGljb21hdGNoQDIuMy4x
│   │           ├── cGljb2NvbG9yc0AxLjAuMA==
│   │           ├── cGlub0A4LjkuMA==
│   │           ├── cGluby1hYnN0cmFjdC10cmFuc3BvcnRAMS4wLjA=
│   │           ├── cGluby1zdGQtc2VyaWFsaXplcnNANi4xLjA=
│   │           ├── cHJlbHVkZS1sc0AxLjIuMQ==
│   │           ├── cHJpc21qc0AxLjI5LjA=
│   │           ├── cHJvY2Vzc0AwLjExLjEw
│   │           ├── cHJvY2Vzcy13YXJuaW5nQDIuMS4w
│   │           ├── cHJveHktYWRkckAyLjAuNw==
│   │           ├── cHVueWNvZGVAMi4zLjA=
│   │           ├── cXNANi4xMS4w
│   │           ├── cXVldWUtbWljcm90YXNrQDEuMi4z
│   │           ├── cXVpY2stZm9ybWF0LXVuZXNjYXBlZEA0LjAuNA==
│   │           ├── cm9sbHVwQDIuNzkuMQ==
│   │           ├── cm9sbHVwQDMuMjAuMA==
│   │           ├── cmF3LWJvZHlAMi41LjE=
│   │           ├── cmF3LWJvZHlAMi41LjI=
│   │           ├── cmFuZ2UtcGFyc2VyQDEuMi4x
│   │           ├── cmV0QDAuMi4y
│   │           ├── cmV0cnlAMC4xMy4x
│   │           ├── cmV1c2lmeUAxLjAuNA==
│   │           ├── cmVhY3QtZG9tQDE4LjIuMA==
│   │           ├── cmVhY3QtcmVmcmVzaEAwLjE0LjA=
│   │           ├── cmVhY3RAMTguMi4w
│   │           ├── cmVhZGFibGUtc3RyZWFtQDMuNi4y
│   │           ├── cmVhZGFibGUtc3RyZWFtQDQuMy4w
│   │           ├── cmVhZGRpcnBAMy42LjA=
│   │           ├── cmVhbC1yZXF1aXJlQDAuMi4w
│   │           ├── cmVnZXhwcEAzLjIuMA==
│   │           ├── cmVxdWlyZS1mcm9tLXN0cmluZ0AyLjAuMg==
│   │           ├── cmVzb2x2ZS1mcm9tQDQuMC4w
│   │           ├── cmVzb2x2ZUAxLjIyLjE=
│   │           ├── cmVzdG9yZS1jdXJzb3JANC4wLjA=
│   │           ├── cmZkY0AxLjMuMA==
│   │           ├── cmltcmFmQDMuMC4y
│   │           ├── cnVuLXBhcmFsbGVsQDEuMi4w
│   │           ├── d29yZC13cmFwQDEuMi4z
│   │           ├── d2N3aWR0aEAxLjAuMQ==
│   │           ├── d2ViLXN0cmVhbXMtcG9seWZpbGxAMy4yLjE=
│   │           ├── d2ViaWRsLWNvbnZlcnNpb25zQDMuMC4x
│   │           ├── d2hhdHdnLW1pbWV0eXBlQDMuMC4w
│   │           ├── d2hhdHdnLXVybEA1LjAuMA==
│   │           ├── d2hpY2hAMi4wLjI=
│   │           ├── d3JhcHB5QDEuMC4y
│   │           ├── dG8tZmFzdC1wcm9wZXJ0aWVzQDIuMC4w
│   │           ├── dG8tcmVnZXgtcmFuZ2VANS4wLjE=
│   │           ├── dG9pZGVudGlmaWVyQDEuMC4x
│   │           ├── dGV4dC10YWJsZUAwLjIuMA==
│   │           ├── dGhyZWFkLXN0cmVhbUAyLjMuMA==
│   │           ├── dGlueS1scnVAMTAuMi4y
│   │           ├── dHI0NkAwLjAuMw==
│   │           ├── dHMtZGVib3VuY2VANC4wLjA=
│   │           ├── dHNsaWJAMi41LjA=
│   │           ├── dHlwZS1jaGVja0AwLjQuMA==
│   │           ├── dHlwZS1mZXN0QDAuMjAuMg==
│   │           ├── dHlwZS1pc0AxLjYuMTg=
│   │           ├── dW5pdmVyc2FsaWZ5QDIuMC4w
│   │           ├── dW5waXBlQDEuMC4w
│   │           ├── dWMubWljcm9AMS4wLjY=
│   │           ├── dXBhdGhAMi4wLjE=
│   │           ├── dXBkYXRlLWJyb3dzZXJzbGlzdC1kYkAxLjAuMTA=
│   │           ├── dXJpLWpzQDQuNC4x
│   │           ├── dXRpbC1kZXByZWNhdGVAMS4wLjI=
│   │           ├── dXRpbHMtbWVyZ2VAMS4wLjE=
│   │           ├── dXVpZEA5LjAuMA==
│   │           ├── djgtY29tcGlsZS1jYWNoZUAyLjMuMA==
│   │           ├── dmFsdWUtb3ItcHJvbWlzZUAxLjAuMTE=
│   │           ├── dmFyeUAxLjEuMg==
│   │           ├── dml0ZUA0LjIuMA==
│   │           ├── dml0ZUAzLjEuOA==
│   │           ├── dml0ZWZ1QDAuMi40
│   │           ├── dnVlLWRlbWlAMC45LjE=
│   │           ├── dnVlLXJvdXRlckA0LjEuNg==
│   │           ├── dnVlQDMuMi40Nw==
│   │           ├── dnVlcHJlc3Mtdml0ZUAyLjAuMC1iZXRhLjUz
│   │           ├── dnVlcHJlc3NAMi4wLjAtYmV0YS41Mw==
│   │           ├── eWFsbGlzdEA0LjAuMA==
│   │           ├── eWFsbGlzdEAzLjEuMQ==
│   │           └── eWFtbEAyLjIuMQ==
│   ├── compatibility/
│   │   ├── circular-esm.test.ts
│   │   ├── process.binding.test.ts
│   │   └── uv.test.ts
│   ├── examples/
│   │   ├── apollo-server.example.js
│   │   ├── astro.example.js
│   │   ├── console.example.js
│   │   ├── eslint.example.js
│   │   ├── exec.example.js
│   │   ├── express.example.js
│   │   ├── fastify.example.js
│   │   ├── fs-symlinks.example.js
│   │   ├── fs-watch-file.example.js
│   │   ├── http-server.example.js
│   │   ├── multiple.example.js
│   │   ├── next-13-app-simple.example.js
│   │   ├── next-13-app.example.js
│   │   ├── next-13.example.js
│   │   ├── next-api.example.js
│   │   ├── next.example.js
│   │   ├── nodemon.example.js
│   │   ├── nuxt.example.js
│   │   ├── shell-output.example.js
│   │   ├── sveltekit.example.js
│   │   ├── terminal.example.js
│   │   ├── timers.example.js
│   │   ├── vite-react.example.js
│   │   ├── vite-solid.example.js
│   │   ├── vite-svelte.example.js
│   │   ├── vite-vue.example.js
│   │   ├── vite.example.js
│   │   ├── vuepress.example.js
│   │   └── yarn.example.js
│   ├── features/
│   │   ├── child_process.test.ts
│   │   ├── console.test.ts
│   │   ├── files.start.test.ts
│   │   ├── multiple.test.ts
│   │   ├── package-manager/
│   │   │   └── hoist-pattern.test.ts
│   │   ├── shell.start.test.ts
│   │   └── worker_threads.test.ts
│   ├── frameworks/
│   │   ├── astro.start.test.ts
│   │   ├── express.test.ts
│   │   ├── fastify.test.ts
│   │   ├── http-server.start.test.ts
│   │   ├── next.start.test.ts
│   │   ├── vite.start.test.ts
│   │   └── vuepress.start.test.ts
│   ├── global.d.ts
│   ├── index.ts
│   ├── node-packages/
│   │   ├── apollo-server.test.ts
│   │   ├── eslint.test.ts
│   │   ├── node-fetch.test.ts
│   │   └── nodemon.test.ts
│   ├── setup/
│   │   ├── MockCdn.ts
│   │   ├── globalSetup.ts
│   │   ├── runSandpackCDNProxy.ts
│   │   ├── runTestServer.ts
│   │   └── server/
│   │       └── index.html
│   └── tsconfig.json
├── tsconfig.json
├── turbo.json
└── vercel.json
Download .txt
SYMBOL INDEX (129 symbols across 25 files)

FILE: internals/esbuild-plugins/inline-file.ts
  function inlineFilePlugin (line 5) | function inlineFilePlugin(): Plugin {

FILE: internals/esbuild-plugins/inline-worker.ts
  constant WORKER_RE (line 7) | const WORKER_RE = /(?:new Worker|createNodeWorker|StatefulWorker)\(requi...
  function hashString (line 10) | function hashString(val: string): string {
  function writeWorker (line 16) | async function writeWorker(dirname: string, content: string): Promise<st...
  function inlineWorkerPlugin (line 25) | function inlineWorkerPlugin(outDir: string, bundle: (entry: string) => P...

FILE: internals/servers/consumer/build.ts
  constant RUNTIME_PORT (line 9) | const RUNTIME_PORT = 4000;
  constant RUNTIME_URL (line 10) | const RUNTIME_URL = `https://${os.hostname()}-${RUNTIME_PORT}.${

FILE: internals/servers/consumer/serve.ts
  constant PORT (line 7) | const PORT = 5000;

FILE: internals/servers/main-server.ts
  constant PORT (line 7) | const PORT = +(process.env.PORT || '4000');
  constant NODE_EMULATOR_RUNTIME_BUILD_DIR (line 11) | const NODE_EMULATOR_RUNTIME_BUILD_DIR = path.join(__dirname, '../../pack...

FILE: internals/servers/preview-server.ts
  constant PORT (line 7) | const PORT = +(process.env.PORT || '3000');
  constant PREVIEW_BUILD_DIR (line 11) | const PREVIEW_BUILD_DIR = path.join(__dirname, '../../packages/runtime/p...

FILE: internals/servers/test/test-server.ts
  constant PORT (line 7) | const PORT = 4007;

FILE: internals/servers/utils.ts
  function setupApp (line 5) | function setupApp(): FastifyInstance {

FILE: packages/nodebox/build.ts
  constant EXIT_TS_ERROR (line 5) | const EXIT_TS_ERROR = Boolean(process.env.IS_PROD_BUILD || process.env.CI);
  function build (line 7) | async function build() {

FILE: packages/nodebox/src/Nodebox.ts
  constant DEFAULT_RUNTIME_URL (line 13) | const DEFAULT_RUNTIME_URL = 'https://nodebox-runtime.codesandbox.io';
  type ChannelOptions (line 15) | interface ChannelOptions {
  class Nodebox (line 34) | class Nodebox {
    method constructor (line 44) | constructor(private readonly options: ChannelOptions) {
    method connect (line 59) | public async connect(): Promise<void> {
    method fs (line 126) | get fs(): FileSystemApi {
    method shell (line 140) | get shell(): ShellApi {
    method preview (line 154) | get preview(): PreviewApi {

FILE: packages/nodebox/src/logger.ts
  constant FLAG (line 2) | const FLAG = window.localStorage['CSB_EMULATOR_DEBUG'];
  constant DEFAULT (line 7) | const DEFAULT = '\u001b[0m';
  constant GREEN (line 9) | const GREEN = '\u001b[32;1m';
  constant RED (line 10) | const RED = '\u001b[31m';
  constant BLUE (line 12) | const BLUE = '\u001b[34m';
  constant YELLOW (line 13) | const YELLOW = '\u001b[33;1m';
  constant MAGENTA (line 14) | const MAGENTA = '\u001b[35;1m';
  constant CYAN (line 15) | const CYAN = '\u001b[36;1m';
  type Scope (line 17) | type Scope = 'preview' | 'emulator' | 'runtime' | 'bridge' | 'runtime:wo...
  constant COLOR_SCOPE (line 18) | const COLOR_SCOPE: Record<Scope, string> = {
  function createDebug (line 26) | function createDebug(scope: Scope) {

FILE: packages/nodebox/src/messages.ts
  type ConsumerEvents (line 16) | interface ConsumerEvents extends FileSystemEvents, ShellEvents, PreviewE...
  type WatcherEvent (line 22) | type WatcherEvent =
  type FSWatchEvent (line 44) | type FSWatchEvent = WatcherEvent & {
  type WorkerStatusUpdate (line 48) | type WorkerStatusUpdate =
  type WorkerEvents (line 65) | interface WorkerEvents {
  type OperationEvent (line 98) | type OperationEvent<Payload> = Payload & {
  type MaybePromise (line 102) | type MaybePromise<T> = T | Promise<T>;
  class MessageReceiver (line 104) | class MessageReceiver {
    method constructor (line 108) | constructor() {
    method waitForHandshake (line 113) | private waitForHandshake() {
    method addMessageListener (line 147) | private addMessageListener(): void {
    method on (line 167) | public on<Event extends keyof ConsumerEvents & string>(
    method send (line 197) | public send<Event extends keyof WorkerEvents & string>(
  class MessageSender (line 214) | class MessageSender {
    method constructor (line 220) | constructor(private readonly target: Window) {
    method handshake (line 248) | public async handshake(): Promise<void> {
    method on (line 274) | public on<Event extends keyof WorkerEvents & string>(
    method off (line 292) | public off<Event extends keyof WorkerEvents & string>(
    method send (line 300) | public async send<Event extends keyof ConsumerEvents & string>(

FILE: packages/nodebox/src/modules/fs.ts
  type FSEncoding (line 5) | type FSEncoding = BufferEncoding | 'buffer';
  type FileContent (line 7) | type FileContent = Uint8Array | string;
  type FilesMap (line 9) | interface FilesMap {
  type FileWatchOptions (line 13) | interface FileWatchOptions {
  type FileWatchEvent (line 17) | type FileWatchEvent = Omit<FSWatchEvent, 'watcherId'>;
  type IFileStats (line 19) | interface IFileStats {
  type FileSystemEvents (line 30) | interface FileSystemEvents {
  type WriteFileOptions (line 83) | type WriteFileOptions = BufferEncoding | { encoding?: BufferEncoding; re...
  class FileSystemApi (line 85) | class FileSystemApi {
    method constructor (line 86) | constructor(private readonly channel: MessageSender) {}
    method init (line 91) | public async init(files: FilesMap): Promise<void> {
    method readFile (line 104) | public async readFile(path: string, encoding?: FSEncoding): Promise<Fi...
    method writeFile (line 121) | public async writeFile(path: string, content: FileContent, options?: W...
    method readdir (line 137) | public async readdir(path: string): Promise<string[]> {
    method mkdir (line 147) | public async mkdir(path: string, options?: { recursive?: boolean }): P...
    method stat (line 154) | public async stat(path: string): Promise<IFileStats> {
    method rm (line 164) | public async rm(path: string, options?: { force?: boolean; recursive?:...
    method watch (line 174) | public async watch(

FILE: packages/nodebox/src/modules/preview.ts
  type PreviewEvents (line 5) | interface PreviewEvents {
  constant TIMEOUT (line 15) | const TIMEOUT = 20_000;
  type PreviewInfo (line 17) | type PreviewInfo = {
  class PreviewApi (line 23) | class PreviewApi {
    method constructor (line 24) | constructor(private readonly channel: MessageSender) {}
    method waitFor (line 26) | private async waitFor(
    method getByShellId (line 77) | public async getByShellId(sourceShellId: string, timeout?: number): Pr...
    method waitForPort (line 83) | public async waitForPort(port: number, timeout?: number): Promise<Prev...

FILE: packages/nodebox/src/modules/shell.ts
  type ShellEvents (line 5) | interface ShellEvents {
  type ShellCommandOptions (line 18) | interface ShellCommandOptions {
  type ShellInfo (line 23) | type ShellInfo = {
  class ShellApi (line 27) | class ShellApi {
    method constructor (line 28) | constructor(private readonly channel: MessageSender) {}
    method create (line 30) | public create(): ShellProcess {
  class ShellProcess (line 35) | class ShellProcess {
    method constructor (line 49) | constructor(private readonly channel: MessageSender) {
    method forwardStdEvents (line 66) | private forwardStdEvents(): void {
    method runCommand (line 91) | public async runCommand(command: string, args: Array<string>, options:...
    method on (line 107) | public async on(message: 'exit' | 'progress' | 'error', listener: any)...
    method kill (line 130) | public async kill(): Promise<void> {

FILE: packages/nodebox/src/runtime-protocol.types.ts
  constant INJECT_MESSAGE_TYPE (line 1) | const INJECT_MESSAGE_TYPE = 'INJECT_AND_INVOKE';
  constant PREVIEW_LOADED_MESSAGE_TYPE (line 2) | const PREVIEW_LOADED_MESSAGE_TYPE = 'PREVIEW_LOADED';
  type Message (line 4) | interface Message {
  type BaseScope (line 8) | type BaseScope = Record<string, unknown>;
  type InjectMessage (line 10) | interface InjectMessage<Scope = BaseScope> {

FILE: packages/utils/withTimeout.ts
  function withTimeout (line 7) | function withTimeout(promise: DeferredPromise<any>, duration: number): v...

FILE: sync-repo.js
  constant INTERNAL_ENTRIES (line 35) | const INTERNAL_ENTRIES = ['packages/runtime', 'documentation'];

FILE: tests/features/files.start.test.ts
  type WatchOutput (line 28) | type WatchOutput = FileWatchEvent | undefined;

FILE: tests/global.d.ts
  type ProcessEnv (line 2) | interface ProcessEnv {
  type Window (line 9) | interface Window {

FILE: tests/index.ts
  type Window (line 6) | interface Window {
  type Fixtures (line 14) | interface Fixtures {
  constant EMULATOR_URL (line 29) | const EMULATOR_URL = `https://${process.env.EMULATOR_HOST}?layout=debug`;
  method runTestServer (line 34) | async runTestServer({ page }, use) {
  method getBridgeFrameLocator (line 54) | async getBridgeFrameLocator({ page }, use) {
  method getPreviewFrameLocator (line 64) | async getPreviewFrameLocator({ page }, use) {
  method getPreviewFrame (line 74) | async getPreviewFrame({ getBridgeFrameLocator, getPreviewFrameLocator },...
  method runExample (line 86) | async runExample({ page }, use) {

FILE: tests/setup/MockCdn.ts
  type MockCdnOptions (line 7) | interface MockCdnOptions {
  type MockCdnPackage (line 11) | interface MockCdnPackage {
  class MockCdn (line 17) | class MockCdn {
    method constructor (line 22) | constructor(options: MockCdnOptions) {
    method respondWith (line 35) | private respondWith(res: FastifyReply, data: unknown) {
    method dependencyQueryMiddleware (line 40) | private dependencyQueryMiddleware(req: FastifyRequest, res: FastifyRep...
    method moduleQueryMiddleware (line 53) | private moduleQueryMiddleware(req: FastifyRequest<{ Params: { query: s...
    method getPackagePragma (line 70) | private getPackagePragma(pkgName: string, packageVersion: string): str...
    method url (line 74) | get url(): string {
    method listen (line 79) | public async listen(options?: FastifyListenOptions): Promise<string> {

FILE: tests/setup/globalSetup.ts
  function globalSetup (line 16) | async function globalSetup(_context: Config): Promise<() => Promise<void...
  function runRuntimeServer (line 41) | function runRuntimeServer(): DeferredPromise<ChildProcess> {
  function runPreviewServer (line 47) | function runPreviewServer(): DeferredPromise<ChildProcess> {
  function spawnAndWaitForStdout (line 53) | function spawnAndWaitForStdout(

FILE: tests/setup/runSandpackCDNProxy.ts
  type TestServerReturnType (line 8) | interface TestServerReturnType {
  constant TEST_DATA_DIR (line 13) | const TEST_DATA_DIR = path.join(__dirname, '../cdn-proxy');
  function runSandpackCDNProxy (line 15) | async function runSandpackCDNProxy(): Promise<TestServerReturnType> {

FILE: tests/setup/runTestServer.ts
  type TestServerReturnType (line 7) | interface TestServerReturnType {
  function runTestServer (line 12) | async function runTestServer(): Promise<TestServerReturnType> {
Copy disabled (too large) Download .json
Condensed preview — 625 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (34,105K chars).
[
  {
    "path": ".codesandbox/tasks.json",
    "chars": 1220,
    "preview": "{\n  // These tasks will run in order when initializing your CodeSandbox project.\n  \"setupTasks\": [\n    {\n      \"name\": \""
  },
  {
    "path": ".editorconfig",
    "chars": 120,
    "preview": "root = true\n\n[*]\nend_of_line = lf\n\n[*.{js,ts,json}]\nindent_style = space\nindent_size = 2\n\n[Makefile]\nindent_style = tab\n"
  },
  {
    "path": ".env.example",
    "chars": 26,
    "preview": "PREVIEW_HOST=csb.test:3000"
  },
  {
    "path": ".env.test",
    "chars": 97,
    "preview": "EMULATOR_HOST=localhost:4000\nPREVIEW_HOST=csb.test:3000\nSANDPACK_CDN_ROOT=https://localhost:3500\n"
  },
  {
    "path": ".eslintignore",
    "chars": 103,
    "preview": ".turbo\nbuild\ninternals/servers/consumer/dist/consumer.js\n/packages/runtime/preview/**/*.js\n/preview\ntmp"
  },
  {
    "path": ".eslintrc.js",
    "chars": 270,
    "preview": "module.exports = {\n  env: { browser: true, es2021: true },\n  parser: '@typescript-eslint/parser',\n  parserOptions: { ecm"
  },
  {
    "path": ".gitignore",
    "chars": 232,
    "preview": "node_modules\n.DS_Store\n.turbo\nbuild\ninternals/servers/consumer/dist/consumer.js\ninternals/servers/consumer/bin\n.env*\n!.e"
  },
  {
    "path": ".prettierignore",
    "chars": 113,
    "preview": "fixture\nfixtures\nbuild\ninternals/servers/consumer/dist/consumer.js\n/packages/runtime/preview/**/*.js\n/preview\ntmp"
  },
  {
    "path": ".prettierrc",
    "chars": 227,
    "preview": "{\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"bracketSpacing\": true,\n  \"printWidth\": 120,\n  \"tabWidth\": 2,\n  \"overrides\": "
  },
  {
    "path": ".release-please-manifest.json",
    "chars": 29,
    "preview": "{\"packages/nodebox\":\"0.1.9\"}\n"
  },
  {
    "path": "ATTRIBUTIONS.md",
    "chars": 737,
    "preview": "# Open Source License Attribution\n\nNodebox uses various components from existing open source projects. You can find the "
  },
  {
    "path": "LICENSE",
    "chars": 3553,
    "preview": "Sustainable Use License\n\nVersion 1.0\n\nAcceptance\n\nBy using the software, you agree to all of the terms and conditions be"
  },
  {
    "path": "README.md",
    "chars": 9714,
    "preview": "# Nodebox\n\nNodebox is a runtime for executing Node.js modules in the browser.\n\n## Why we built Nodebox\n\nWith `sandpack-b"
  },
  {
    "path": "dnsmasq.conf",
    "chars": 290,
    "preview": "# Handle local wildcard codesandbox domain\naddress=/csb.test/127.0.0.1\n\n# Don't read /etc/resolv.conf or any other confi"
  },
  {
    "path": "internals/esbuild-plugins/inline-file.ts",
    "chars": 1923,
    "preview": "import path from 'path';\nimport fs from 'fs-extra';\nimport type { Plugin, OnLoadArgs } from 'esbuild';\n\nexport function "
  },
  {
    "path": "internals/esbuild-plugins/inline-worker.ts",
    "chars": 3194,
    "preview": "import crypto from 'crypto';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport type { Plugin } from 'esbuild';\n"
  },
  {
    "path": "internals/servers/consumer/build.ts",
    "chars": 1785,
    "preview": "import esbuild from 'esbuild';\nimport path from 'path';\nimport os from 'os';\nimport { readFile, writeFile } from 'node:f"
  },
  {
    "path": "internals/servers/consumer/dist/index.html",
    "chars": 4880,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"I"
  },
  {
    "path": "internals/servers/consumer/serve.ts",
    "chars": 597,
    "preview": "import 'dotenv/config';\nimport { setupApp } from '../utils';\n\nimport fastifyStatic from '@fastify/static';\nimport path f"
  },
  {
    "path": "internals/servers/main-server.ts",
    "chars": 1107,
    "preview": "import path from 'path';\nimport 'dotenv/config';\nimport { setupApp } from './utils';\n\nimport fastifyStatic from '@fastif"
  },
  {
    "path": "internals/servers/preview-server.ts",
    "chars": 666,
    "preview": "import 'dotenv/config';\nimport { setupApp } from './utils';\n\nimport fastifyStatic from '@fastify/static';\nimport path fr"
  },
  {
    "path": "internals/servers/test/index.html",
    "chars": 563,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"I"
  },
  {
    "path": "internals/servers/test/test-server.ts",
    "chars": 618,
    "preview": "import 'dotenv/config';\nimport { setupApp } from '../utils';\n\nimport fastifyStatic from '@fastify/static';\nimport path f"
  },
  {
    "path": "internals/servers/utils.ts",
    "chars": 544,
    "preview": "import fastify, { FastifyInstance } from 'fastify';\nimport fs from 'fs';\nimport path from 'path';\n\nexport function setup"
  },
  {
    "path": "package.json",
    "chars": 2850,
    "preview": "{\n  \"private\": true,\n  \"name\": \"nodebox\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"build\": \"turbo run build --no-cache "
  },
  {
    "path": "packages/nodebox/.npmignore",
    "chars": 25,
    "preview": "src\nbuild.ts\nCHANGELOG.md"
  },
  {
    "path": "packages/nodebox/CHANGELOG.md",
    "chars": 30861,
    "preview": "# Changelog\n\n## [0.1.9](https://github.com/Sandpack/nodebox-internal/compare/nodebox-v0.1.8...nodebox-v0.1.9) (2023-11-2"
  },
  {
    "path": "packages/nodebox/LICENSE",
    "chars": 3553,
    "preview": "Sustainable Use License\n\nVersion 1.0\n\nAcceptance\n\nBy using the software, you agree to all of the terms and conditions be"
  },
  {
    "path": "packages/nodebox/README.md",
    "chars": 9714,
    "preview": "# Nodebox\n\nNodebox is a runtime for executing Node.js modules in the browser.\n\n## Why we built Nodebox\n\nWith `sandpack-b"
  },
  {
    "path": "packages/nodebox/api.md",
    "chars": 8729,
    "preview": "# API\n\n- [Class: `Nodebox`](#class-nodebox)\n  - [`new Nodebox(options)`](#new-nodeboxurl-options)\n  - [`nodebox.connect("
  },
  {
    "path": "packages/nodebox/build.ts",
    "chars": 958,
    "preview": "import path from 'path';\nimport esbuild from 'esbuild';\nimport { spawnSync } from 'node:child_process';\n\nconst EXIT_TS_E"
  },
  {
    "path": "packages/nodebox/package.json",
    "chars": 762,
    "preview": "{\n  \"name\": \"@codesandbox/nodebox\",\n  \"version\": \"0.1.9\",\n  \"description\": \"Public API of Nodebox\",\n  \"main\": \"./build/i"
  },
  {
    "path": "packages/nodebox/src/Nodebox.ts",
    "chars": 4384,
    "preview": "import { invariant } from 'outvariant';\nimport { DeferredPromise } from '@open-draft/deferred-promise';\nimport { createD"
  },
  {
    "path": "packages/nodebox/src/index.ts",
    "chars": 146,
    "preview": "export * from './messages';\nexport * from './Nodebox';\nexport * from './runtime-protocol.types';\n\nexport type { IFileSta"
  },
  {
    "path": "packages/nodebox/src/logger.ts",
    "chars": 1057,
    "preview": "/* eslint-disable no-console */\nconst FLAG = window.localStorage['CSB_EMULATOR_DEBUG'];\n\n/**\n * Colors\n */\nconst DEFAULT"
  },
  {
    "path": "packages/nodebox/src/messages.ts",
    "chars": 10390,
    "preview": "/**\n * This is a message contract between the Consumer and the Worker (Emulator).\n * @see \"consumer-worker-messages.md\" "
  },
  {
    "path": "packages/nodebox/src/modules/fs.ts",
    "chars": 5503,
    "preview": "import cuid from 'cuid';\nimport { format } from 'outvariant';\nimport type { MessageSender, FSWatchEvent } from '../messa"
  },
  {
    "path": "packages/nodebox/src/modules/preview.ts",
    "chars": 2535,
    "preview": "import { format } from 'outvariant';\nimport { DeferredPromise } from '@open-draft/deferred-promise';\nimport type { Messa"
  },
  {
    "path": "packages/nodebox/src/modules/shell.ts",
    "chars": 4002,
    "preview": "import { format, invariant } from 'outvariant';\nimport { Emitter } from 'strict-event-emitter';\nimport type { MessageSen"
  },
  {
    "path": "packages/nodebox/src/runtime-protocol.types.ts",
    "chars": 495,
    "preview": "export const INJECT_MESSAGE_TYPE = 'INJECT_AND_INVOKE';\nexport const PREVIEW_LOADED_MESSAGE_TYPE = 'PREVIEW_LOADED';\n\nex"
  },
  {
    "path": "packages/nodebox/tsconfig.build.json",
    "chars": 253,
    "preview": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"commonjs\",\n    \"root"
  },
  {
    "path": "packages/nodebox/tsconfig.json",
    "chars": 181,
    "preview": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"commonjs\",\n    \"noEm"
  },
  {
    "path": "packages/utils/jest.config.js",
    "chars": 43,
    "preview": "module.exports = {\n  preset: 'ts-jest',\n};\n"
  },
  {
    "path": "packages/utils/package.json",
    "chars": 97,
    "preview": "{\n  \"name\": \"internal-utils\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"test:unit\": \"jest\"\n  }\n}\n"
  },
  {
    "path": "packages/utils/withTimeout.test.ts",
    "chars": 2184,
    "preview": "import { DeferredPromise } from '@open-draft/deferred-promise';\nimport { withTimeout } from './withTimeout';\n\nit('reject"
  },
  {
    "path": "packages/utils/withTimeout.ts",
    "chars": 689,
    "preview": "import { DeferredPromise } from '@open-draft/deferred-promise';\n\n/**\n * Rejects a given `DeferredPromise` if it doesn't "
  },
  {
    "path": "playwright.config.ts",
    "chars": 1131,
    "preview": "import type { PlaywrightTestConfig } from '@playwright/test';\nimport { devices } from '@playwright/test';\n\nconst config:"
  },
  {
    "path": "pnpm-workspace.yaml",
    "chars": 27,
    "preview": "packages:\n  - ./packages/*\n"
  },
  {
    "path": "release-please-config.json",
    "chars": 167,
    "preview": "{\n  \"packages\": {\n    \"packages/nodebox\": {\n      \"release-type\": \"node\",\n      \"bump-minor-pre-major\": true,\n      \"bum"
  },
  {
    "path": "req.conf",
    "chars": 446,
    "preview": "[req]\ndistinguished_name = req_distinguished_name\nx509_extensions = v3_req\nprompt = no\n\n[req_distinguished_name]\n# C = U"
  },
  {
    "path": "sync-repo.js",
    "chars": 1198,
    "preview": "const fs = require(\"fs\");\nconst path = require(\"path\");\n\nconsole.log('Syncing private repo to this public repo...');\n\nco"
  },
  {
    "path": "tests/cdn-proxy/v2/deps/ZXNidWlsZC13YXNtQDAuMTcuMTI7dml0ZUA0LjIuMA==",
    "chars": 248,
    "preview": "esbuild-wasm@00.17.12esbuild@00.17.9function-bind@11.1.1has@11.0.3is-core-module@22.9.0nanoid@33.3.4path-parse@11.0.7pic"
  },
  {
    "path": "tests/cdn-proxy/v2/deps/bm9kZS1mZXRjaEAzLjMuMA==",
    "chars": 135,
    "preview": "data-uri-to-buffer@44.0.1fetch-blob@33.2.0formdata-polyfill@44.0.10node-domexception@11.0.0node-fetch@33.3.0web-streams-"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi10aXRsZUAwLjExLjI=",
    "chars": 4616,
    "preview": "/dist/index.cjs\u0001'use strict';\n\nconst shared = require('@mdit-vue/shared');\n\nconst titlePlugin = (md) => {\n  const render"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi10b2NAMC4xMS4y",
    "chars": 14220,
    "preview": "/dist/index.cjs\f\u0001'use strict';\n\nconst shared = require('@mdit-vue/shared');\n\nconst createRenderHeaders = ({\n  listTag,\n "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1jb21wb25lbnRAMC4xMS4y",
    "chars": 19932,
    "preview": "/dist/index.d.ts\bimport MarkdownIt from 'markdown-it';\nimport ParserBlock from 'markdown-it/lib/parser_block.js';\nimport"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1mcm9udG1hdHRlckAwLjExLjE=",
    "chars": 6992,
    "preview": "/LICENSE\u0004IThe MIT License (MIT)\n\nCopyright (c) 2022-present, mdit-vue Contributors\n\nPermission is hereby granted, free o"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1oZWFkZXJzQDAuMTEuMg==",
    "chars": 6412,
    "preview": "/dist/index.mjs\u0002\nimport { resolveHeadersFromTokens, slugify } from '@mdit-vue/shared';\n\nconst headersPlugin = (md, { lev"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3BsdWdpbi1zZmNAMC4xMS4x",
    "chars": 10809,
    "preview": "/package.json\u0004O{\n  \"name\": \"@mdit-vue/plugin-sfc\",\n  \"version\": \"0.11.1\",\n  \"description\": \"A markdown-it plugin to help"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3NoYXJlZEAwLjExLjI=",
    "chars": 10150,
    "preview": "/README.md# @mdit-vue/shared\n\n[![npm](https://badgen.net/npm/v/@mdit-vue/shared)](https://www.npmjs.com/package/@mdit-vu"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG1kaXQtdnVlL3R5cGVzQDAuMTEuMA==",
    "chars": 3406,
    "preview": "/README.md\u0002# @mdit-vue/types\n\n[![npm](https://badgen.net/npm/v/@mdit-vue/types)](https://www.npmjs.com/package/@mdit-vue"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QG5vZGVsaWIvZnMuc3RhdEAyLjAuNQ==",
    "chars": 12126,
    "preview": "/out/providers/async.js\u0004\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.read = void"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFtcHByb2plY3QvcmVtYXBwaW5nQDIuMi4w",
    "chars": 55599,
    "preview": "/LICENSE,M\n                                 Apache License\n                           Version 2.0, January 2004\n        "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy53aXRocmVxdWlyZWRAMS4wLjE=",
    "chars": 3738,
    "preview": "/src/index.tsKexport type WithRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;\n/package.json\u0001{\n  \"name\": \"@apo"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5jcmVhdGVoYXNoQDEuMS4w",
    "chars": 3901,
    "preview": "/LICENSE\u0004]MIT License\n\nCopyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)\n\nPermission is he"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5kcm9wdW51c2VkZGVmaW5pdGlvbnNAMS4xLjA=",
    "chars": 6039,
    "preview": "/package.json\u0002{\n  \"name\": \"@apollo/utils.dropunuseddefinitions\",\n  \"version\": \"1.1.0\",\n  \"description\": \"Drop unused def"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5mZXRjaGVyQDEuMS4x",
    "chars": 10100,
    "preview": "/README.md\u0005# Fetcher interface\n\nThis package defines TypeScript typings for a subset of the [web `fetch` API](https://de"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5mZXRjaGVyQDIuMC4w",
    "chars": 10139,
    "preview": "/src/index.ts\rexport interface FetcherRequestInit {\n  method?: string;\n  // We explicitly do not allow you to pass in a "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5pc25vZGVsaWtlQDEuMS4w",
    "chars": 3139,
    "preview": "/LICENSE\u0004]MIT License\n\nCopyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)\n\nPermission is he"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5sb2dnZXJAMS4wLjE=",
    "chars": 7781,
    "preview": "/LICENSE\u0004]MIT License\n\nCopyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)\n\nPermission is he"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5sb2dnZXJAMi4wLjA=",
    "chars": 7820,
    "preview": "/LICENSE\u0004]MIT License\n\nCopyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)\n\nPermission is he"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5wcmludHdpdGhyZWR1Y2Vkd2hpdGVzcGFjZUAxLjEuMA==",
    "chars": 6623,
    "preview": "/dist/index.d.ts.map{\"version\":3,\"file\":\"index.d.ts\",\"sourceRoot\":\"\",\"sources\":[\"../src/index.ts\"],\"names\":[],\"mappings\""
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5yZW1vdmVhbGlhc2VzQDEuMC4w",
    "chars": 5175,
    "preview": "/README.md\u0001~# removeAliases\n\nThe `removeAliases` function is a `graphql-js` visitor which removes aliases from all `Fiel"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5zb3J0YXN0QDEuMS4w",
    "chars": 8721,
    "preview": "/LICENSE\u0004]MIT License\n\nCopyright (c) 2022 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)\n\nPermission is he"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby91dGlscy5zdHJpcHNlbnNpdGl2ZWxpdGVyYWxzQDEuMi4w",
    "chars": 9155,
    "preview": "/dist/index.d.ts.map\u0001\u0003{\"version\":3,\"file\":\"index.d.ts\",\"sourceRoot\":\"\",\"sources\":[\"../src/index.ts\"],\"names\":[],\"mapping"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby9jYWNoZS1jb250cm9sLXR5cGVzQDEuMC4y",
    "chars": 10714,
    "preview": "/dist/index.js\u0005W\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.cacheControlFromInf"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby9zZXJ2ZXItZ2F0ZXdheS1pbnRlcmZhY2VAMS4xLjA=",
    "chars": 13748,
    "preview": "/dist/index.d.ts\rpimport type { KeyValueCache } from '@apollo/utils.keyvaluecache';\nimport type { DocumentNode, Executio"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGFwb2xsby9zZXJ2ZXJANC4xLjE=",
    "chars": 1358699,
    "preview": "\u0001$/src/plugin/drainHttpServer/index.ts\u0004iimport type http from 'http';\nimport type { ApolloServerPlugin } from '../../ext"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2NvZGUtZnJhbWVANy4xOC42",
    "chars": 7031,
    "preview": "/README.md\u0001Q# @babel/code-frame\n\n> Generate errors that contain a code frame that point to source locations.\n\nSee our we"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2NvbXBhdC1kYXRhQDcuMjEuMA==",
    "chars": 58207,
    "preview": "/data/corejs2-built-ins.jsonŏ+{\n  \"es6.array.copy-within\": {\n    \"chrome\": \"45\",\n    \"opera\": \"32\",\n    \"edge\": \"12\",\n  "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci12YWxpZGF0b3ItaWRlbnRpZmllckA3LjE5LjE=",
    "chars": 51841,
    "preview": "/lib/identifier.js.mapmf{\"version\":3,\"names\":[\"nonASCIIidentifierStartChars\",\"nonASCIIidentifierChars\",\"nonASCIIidentifi"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci12YWxpZGF0b3Itb3B0aW9uQDcuMjEuMA==",
    "chars": 11606,
    "preview": "/lib/index.js.map{\"version\":3,\"names\":[],\"sources\":[\"../src/index.ts\"],\"sourcesContent\":[\"export { OptionValidator } fro"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1lbnZpcm9ubWVudC12aXNpdG9yQDcuMTguOQ==",
    "chars": 3438,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1mdW5jdGlvbi1uYW1lQDcuMjEuMA==",
    "chars": 21430,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1ob2lzdC12YXJpYWJsZXNANy4xOC42",
    "chars": 3512,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1tb2R1bGUtaW1wb3J0c0A3LjE4LjY=",
    "chars": 16187,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1tb2R1bGUtdHJhbnNmb3Jtc0A3LjIxLjI=",
    "chars": 146371,
    "preview": "'/lib/normalize-and-load-metadata.js.mapł{\"version\":3,\"names\":[\"hasExports\",\"metadata\",\"isSideEffectImport\",\"source\",\"im"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1wbHVnaW4tdXRpbHNANy4yMC4y",
    "chars": 11925,
    "preview": "/README.md\u0001O# @babel/helper-plugin-utils\n\n> General utilities for plugins to use\n\nSee our website [@babel/helper-plugin-"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1zaW1wbGUtYWNjZXNzQDcuMjAuMg==",
    "chars": 13764,
    "preview": "/lib/index.js\u000b\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports.default = simplify"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1zcGxpdC1leHBvcnQtZGVjbGFyYXRpb25ANy4xOC42",
    "chars": 4441,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hlbHBlci1zdHJpbmctcGFyc2VyQDcuMTkuNA==",
    "chars": 31777,
    "preview": "/lib/index.js.mapT{\"version\":3,\"names\":[\"isDigit\",\"code\",\"forbiddenNumericSeparatorSiblings\",\"decBinOct\",\"Set\",\"hex\",\"is"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL2hpZ2hsaWdodEA3LjE4LjY=",
    "chars": 4957,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL3BhcnNlckA3LjIxLjM=",
    "chars": 1871991,
    "preview": "/README.md\u0001# @babel/parser\n\n> A JavaScript parser\n\nSee our website [@babel/parser](https://babeljs.io/docs/en/babel-pars"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNlbGZANy4yMS4w",
    "chars": 8996,
    "preview": "/package.json\u0003{\n  \"name\": \"@babel/plugin-transform-react-jsx-self\",\n  \"version\": \"7.21.0\",\n  \"description\": \"Add a __sel"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGJhYmVsL3BsdWdpbi10cmFuc2Zvcm0tcmVhY3QtanN4LXNvdXJjZUA3LjE5LjY=",
    "chars": 9080,
    "preview": "/LICENSE\u0004RMIT License\n\nCopyright (c) 2014-present Sebastian McKenzie and other contributors\n\nPermission is hereby grante"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGZhc3RpZnkvZGVlcG1lcmdlQDEuMy4w",
    "chars": 14314,
    "preview": "/types/index.d.ts\u0007type DeepMergeFn = <T1, T2>(target: T1, source: T2) => DeepMerge<T1, T2>;\ntype DeepMergeAllFn = <T ext"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGZhc3RpZnkvZXJyb3JAMy4yLjA=",
    "chars": 11786,
    "preview": "/package.json\u0003{\n  \"name\": \"@fastify/error\",\n  \"version\": \"3.2.0\",\n  \"description\": \"A small utility, used by Fastify its"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGZhc3RpZnkvZmFzdC1qc29uLXN0cmluZ2lmeS1jb21waWxlckA0LjIuMA==",
    "chars": 22264,
    "preview": "/package.json\u0004o{\n  \"name\": \"@fastify/fast-json-stringify-compiler\",\n  \"description\": \"Build and manage the fast-json-str"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGh1bWFud2hvY29kZXMvY29uZmlnLWFycmF5QDAuOS41",
    "chars": 45594,
    "preview": "/LICENSE,]                                 Apache License\n                           Version 2.0, January 2004\n         "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGh1bWFud2hvY29kZXMvb2JqZWN0LXNjaGVtYUAxLjIuMQ==",
    "chars": 49706,
    "preview": "/package.json\u0002{\n  \"name\": \"@humanwhocodes/object-schema\",\n  \"version\": \"1.2.1\",\n  \"description\": \"An object schema merge"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGpvc2VwaGcvcmVzb2x2YWJsZUAxLjAuMQ==",
    "chars": 3290,
    "preview": "/index.js\u0001\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst resolvablePromise = () => {"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGpyaWRnZXdlbGwvZ2VuLW1hcHBpbmdAMC4zLjI=",
    "chars": 93295,
    "preview": "/LICENSE\u00048Copyright 2022 Justin Ridgewell <jridgewell@google.com>\n\nPermission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGpyaWRnZXdlbGwvc291cmNlbWFwLWNvZGVjQDEuNC4xNA==",
    "chars": 40198,
    "preview": "/dist/sourcemap-codec.umd.js\u0018(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefin"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGpyaWRnZXdlbGwvc2V0LWFycmF5QDEuMS4y",
    "chars": 15666,
    "preview": "/LICENSE\u00048Copyright 2022 Justin Ridgewell <jridgewell@google.com>\n\nPermission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QGpyaWRnZXdlbGwvcmVzb2x2ZS11cmlAMy4xLjA=",
    "chars": 55327,
    "preview": "/dist/resolve-uri.umd.js(a(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined'"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvY29kZWdlbkAyLjAuNA==",
    "chars": 9212,
    "preview": "/index.d.ts\u0004export = codegen;\r\n\r\n/**\r\n * Appends code to the function's body.\r\n * @param [formatStringOrScope] Format st"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvYXNwcm9taXNlQDEuMS4y",
    "chars": 9130,
    "preview": "/index.js\u00068\"use strict\";\r\nmodule.exports = asPromise;\r\n\r\n/**\r\n * Callback as used by {@link util.asPromise}.\r\n * @typede"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvYmFzZTY0QDEuMS4y",
    "chars": 9300,
    "preview": "/index.js\u000fg\"use strict\";\r\n\r\n/**\r\n * A minimal base64 implementation for number arrays.\r\n * @memberof util\r\n * @namespace"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvZXZlbnRlbWl0dGVyQDEuMS4w",
    "chars": 7828,
    "preview": "/index.d.ts\u0005\u000fexport = EventEmitter;\r\n\r\n/**\r\n * Constructs a new event emitter instance.\r\n * @classdesc A minimal event e"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvZmV0Y2hAMS4xLjA=",
    "chars": 8835,
    "preview": "/tests/index.js\u0001var tape = require(\"tape\");\r\n\r\nvar fetch = require(\"..\");\r\n\r\ntape.test(\"fetch\", function(test) {\r\n\r\n    "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvZmxvYXRAMS4wLjI=",
    "chars": 27054,
    "preview": "/package.json\u0002{\r\n  \"name\": \"@protobufjs/float\",\r\n  \"description\": \"Reads / writes floats / doubles from / to buffers in "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvaW5xdWlyZUAxLjEuMA==",
    "chars": 4471,
    "preview": "/package.json\u0002Z{\r\n  \"name\": \"@protobufjs/inquire\",\r\n  \"description\": \"Requires a module only if available and hides the "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvcG9vbEAxLjEuMA==",
    "chars": 6334,
    "preview": "/tests/index.js\u0005var tape = require(\"tape\");\r\n\r\nvar pool = require(\"..\");\r\n\r\nif (typeof Uint8Array !== \"undefined\")\r\ntape"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvcGF0aEAxLjEuMg==",
    "chars": 7846,
    "preview": "/LICENSE\u0005Copyright (c) 2016, Daniel Wirtz  All rights reserved.\r\n\r\nRedistribution and use in source and binary forms, wi"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHByb3RvYnVmanMvdXRmOEAxLjEuMA==",
    "chars": 16991,
    "preview": "/package.json\u0002'{\n  \"name\": \"@protobufjs/utf8\",\n  \"description\": \"A minimal UTF8 implementation for number arrays.\",\n  \"v"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL21hcmtkb3duLWl0LWVtb2ppQDIuMC4y",
    "chars": 4694,
    "preview": "/light.d.tssimport emoji = require(\"./index\");\n\ndeclare namespace light {}\n\ndeclare const light: typeof emoji;\nexport = "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL21kdXJsQDEuMC4y",
    "chars": 3599,
    "preview": "/README.md\u0001# Installation\r\n> `npm install --save @types/mdurl`\r\n\r\n# Summary\r\nThis package contains type definitions for "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL21pbWVAMy4wLjE=",
    "chars": 3639,
    "preview": "/lite.d.tssimport Mime = require('./Mime');\n\ndeclare const mimelite: Mime;\n\nexport as namespace mimelite;\n\nexport = mime"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL21zQDAuNy4zMQ==",
    "chars": 2925,
    "preview": "/README.md\u0001# Installation\r\n> `npm install --save @types/ms`\r\n\r\n# Summary\r\nThis package contains type definitions for ms "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2JvZHktcGFyc2VyQDEuMTkuMg==",
    "chars": 8334,
    "preview": "/LICENSE\u0004u    MIT License\n\n    Copyright (c) Microsoft Corporation.\n\n    Permission is hereby granted, free of charge, t"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2Nvbm5lY3RAMy40LjM1",
    "chars": 6186,
    "preview": "/index.d.ts\ru// Type definitions for connect v3.4.0\n// Project: https://github.com/senchalabs/connect\n// Definitions by:"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2RlYnVnQDQuMS43",
    "chars": 7265,
    "preview": "/README.md\n^# Installation\r\n> `npm install --save @types/debug`\r\n\r\n# Summary\r\nThis package contains type definitions for"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2V4cHJlc3Mtc2VydmUtc3RhdGljLWNvcmVANC4xNy4zMw==",
    "chars": 44928,
    "preview": "/index.d.tsŠ// Type definitions for Express 4.17\n// Project: http://expressjs.com\n// Definitions by: Boris Yankov <https"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2V4cHJlc3NANC4xNy4xNw==",
    "chars": 8339,
    "preview": "/package.json\u0005{\n    \"name\": \"@types/express\",\n    \"version\": \"4.17.17\",\n    \"description\": \"TypeScript definitions for E"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2ZzLWV4dHJhQDkuMC4xMw==",
    "chars": 27950,
    "preview": "/package.json\u0007{\n    \"name\": \"@types/fs-extra\",\n    \"version\": \"9.0.13\",\n    \"description\": \"TypeScript definitions for f"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2hhc2gtc3VtQDEuMC4w",
    "chars": 2661,
    "preview": "/package.json\u0002{\n    \"name\": \"@types/hash-sum\",\n    \"version\": \"1.0.0\",\n    \"description\": \"TypeScript definitions for ha"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2xpbmtpZnktaXRAMy4wLjI=",
    "chars": 7682,
    "preview": "/index.d.ts\b// Type definitions for linkify-it 3.0.2\n// Project: https://github.com/markdown-it/linkify-it\n// Definition"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL2xvbmdANC4wLjI=",
    "chars": 13310,
    "preview": "/LICENSE\u0004u    MIT License\n\n    Copyright (c) Microsoft Corporation.\n\n    Permission is hereby granted, free of charge, t"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL3FzQDYuOS43",
    "chars": 7050,
    "preview": "/index.d.ts\f\u0010// Type definitions for qs 6.9\n// Project: https://github.com/ljharb/qs\n// Definitions by: Roman Korneev <h"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL3JhbmdlLXBhcnNlckAxLjIuNA==",
    "chars": 5098,
    "preview": "/package.json\u0003%{\n    \"name\": \"@types/range-parser\",\n    \"version\": \"1.2.4\",\n    \"description\": \"TypeScript definitions f"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL3NlcnZlLXN0YXRpY0AxLjcuMzI=",
    "chars": 6215,
    "preview": "/README.md\u0002\u001b# Installation\r\n> `npm install --save @types/serve-static`\r\n\r\n# Summary\r\nThis package contains type definiti"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHR5cGVzL3dlYi1ibHVldG9vdGhAMC4wLjE2",
    "chars": 10946,
    "preview": "/README.md\u0002# Installation\r\n> `npm install --save @types/web-bluetooth`\r\n\r\n# Summary\r\nThis package contains type definiti"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9jb21waWxlci1kb21AMy4yLjQ3",
    "chars": 744293,
    "preview": "&/dist/compiler-dom.esm-browser.prod.js\u0007function e(e,t){const n=Object.create(null),o=e.split(\",\");for(let r=0;r<o.lengt"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9jb21waWxlci1zZmNAMy4yLjQ3",
    "chars": 2073564,
    "preview": "/package.json\u0005{\n  \"name\": \"@vue/compiler-sfc\",\n  \"version\": \"3.2.47\",\n  \"description\": \"@vue/compiler-sfc\",\n  \"main\": \"d"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9jb21waWxlci1zc3JAMy4yLjQ3",
    "chars": 58116,
    "preview": "/package.json\u0002{\n  \"name\": \"@vue/compiler-ssr\",\n  \"version\": \"3.2.47\",\n  \"description\": \"@vue/compiler-ssr\",\n  \"main\": \"d"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9yZWFjdGl2aXR5LXRyYW5zZm9ybUAzLjIuNDc=",
    "chars": 30621,
    "preview": "/LICENSE\u0004CThe MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9yZWFjdGl2aXR5QDMuMi40Nw==",
    "chars": 254840,
    "preview": "/dist/reactivity.esm-bundler.jsŧimport { extend, isArray, isMap, isIntegerKey, hasOwn, isSymbol, isObject, hasChanged, m"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9ydW50aW1lLWRvbUAzLjIuNDc=",
    "chars": 1231732,
    "preview": "/README.md# @vue/runtime-dom\n\n``` js\nimport { h, createApp } from '@vue/runtime-dom'\n\nconst RootComponent = {\n  render()"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9zZXJ2ZXItcmVuZGVyZXJAMy4yLjQ3",
    "chars": 474581,
    "preview": "/dist/server-renderer.cjs.jsŘg'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nvar Vue = r"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZS9zaGFyZWRAMy4yLjQ3",
    "chars": 87894,
    "preview": "/package.json\u0002{\n  \"name\": \"@vue/shared\",\n  \"version\": \"3.2.47\",\n  \"description\": \"internal utils shared across @vue pack"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL21hcmtkb3duQDIuMC4wLWJldGEuNTM=",
    "chars": 24420,
    "preview": "/LICENSE\u0004CThe MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL2J1bmRsZXItdml0ZUAyLjAuMC1iZXRhLjUz",
    "chars": 16548,
    "preview": "/dist/index.d.ts\u0001import { Bundler } from '@vuepress/core';\nimport { Options } from '@vitejs/plugin-vue';\nimport { Inline"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL2NsaUAyLjAuMC1iZXRhLjUz",
    "chars": 27274,
    "preview": "/dist/index.jsQ4// src/commands/build/createBuild.ts\nimport process6 from \"process\";\nimport { createBuildApp } from \"@vu"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL2NsaWVudEAyLjAuMC1iZXRhLjUz",
    "chars": 30415,
    "preview": "/templates/dev.html<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" conten"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL2NvcmVAMi4wLjAtYmV0YS41Mw==",
    "chars": 50917,
    "preview": "/LICENSE\u0004CThe MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3BsdWdpbi1hY3RpdmUtaGVhZGVyLWxpbmtzQDIuMC4wLWJldGEuNTM=",
    "chars": 9801,
    "preview": "/lib/node/index.d.tsĞimport { activeHeaderLinksPlugin } from './activeHeaderLinksPlugin.js';\nexport * from './activeHead"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3BsdWdpbi1jb250YWluZXJAMi4wLjAtYmV0YS41Mw==",
    "chars": 7571,
    "preview": "/LICENSE\u0004CThe MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3BsdWdpbi1wYWxldHRlQDIuMC4wLWJldGEuNTM=",
    "chars": 9064,
    "preview": "/lib/node/prepareStyleFile.js\u0001`import { fs } from '@vuepress/utils';\nexport const prepareStyleFile = async (app, { userS"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3BsdWdpbi1wcmlzbWpzQDIuMC4wLWJldGEuNTM=",
    "chars": 5433,
    "preview": "/lib/node/resolveHighlighter.js\u0004\u001dimport Prism from 'prismjs';\nimport { loadLanguages } from './loadLanguages.js';\nconst "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3NoYXJlZEAyLjAuMC1iZXRhLjUz",
    "chars": 12513,
    "preview": "/LICENSE\u0004CThe MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXByZXNzL3V0aWxzQDIuMC4wLWJldGEuNTM=",
    "chars": 7572,
    "preview": "/dist/index.js\u000b// src/index.ts\nimport chalk2 from \"chalk\";\nimport debug from \"debug\";\nimport fs from \"fs-extra\";\nimport "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZ1ZXVzZS9zaGFyZWRAOS45LjA=",
    "chars": 220100,
    "preview": "/index.iife.js\u001cvar VueDemi = (function (VueDemi, Vue, VueCompositionAPI) {\n  if (VueDemi.install) {\n    return VueDemi\n "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/QHZpdGVqcy9wbHVnaW4tcmVhY3RAMy4xLjA=",
    "chars": 37193,
    "preview": "/dist/refreshUtils.js\u0007function debounce(fn, delay) {\n  let handle\n  return () => {\n    clearTimeout(handle)\n    handle ="
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29sb3ItY29udmVydEAxLjkuMw==",
    "chars": 27051,
    "preview": "/route.js\bvar conversions = require('./conversions');\n\n/*\n\tthis function routes a model to all other models.\n\n\tall funct"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29sb3ItY29udmVydEAyLjAuMQ==",
    "chars": 27276,
    "preview": "/CHANGELOG.md\u0005# 1.0.0 - 2016-01-07\n\n- Removed: unused speed test\n- Added: Automatic routing between previously unsupport"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29sb3ItbmFtZUAxLjEuMw==",
    "chars": 9445,
    "preview": "/LICENSE\u0004=The MIT License (MIT)\r\nCopyright (c) 2015 Dmitry Ivanov\r\n\r\nPermission is hereby granted, free of charge, to an"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29sb3ItbmFtZUAxLjEuNA==",
    "chars": 6740,
    "preview": "/README.md\u0001A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.\r\n\r\n[![NPM]("
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29tYmluZWQtc3RyZWFtQDEuMC44",
    "chars": 11585,
    "preview": "/package.json\u0002{\n  \"author\": \"Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)\",\n  \"name\": \"combined-st"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29uY2F0LW1hcEAwLjAuMQ==",
    "chars": 4956,
    "preview": "/example/map.jsīvar concatMap = require('../');\nvar xs = [ 1, 2, 3, 4, 5, 6 ];\nvar ys = concatMap(xs, function (x) {\n   "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29ubmVjdC1oaXN0b3J5LWFwaS1mYWxsYmFja0AyLjAuMA==",
    "chars": 10261,
    "preview": "/LICENSE\u0004BThe MIT License\n\nCopyright (c) 2022 Ben Blackmore and contributors\n\nPermission is hereby granted, free of char"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29udGVudC10eXBlQDEuMC41",
    "chars": 10530,
    "preview": "/LICENSE\u0004A(The MIT License)\n\nCopyright (c) 2015 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29udGVudC1kaXNwb3NpdGlvbkAwLjUuNA==",
    "chars": 19168,
    "preview": "/LICENSE\u0004F(The MIT License)\n\nCopyright (c) 2014-2017 Douglas Christopher Wilson\n\nPermission is hereby granted, free of c"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29udmVydC1zb3VyY2UtbWFwQDEuOS4w",
    "chars": 11480,
    "preview": "/package.json\u0003J{\n  \"name\": \"convert-source-map\",\n  \"version\": \"1.9.0\",\n  \"description\": \"Converts a source-map from/to  "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29va2llLXNpZ25hdHVyZUAxLjAuNg==",
    "chars": 3995,
    "preview": "/.npmignore\u001dsupport\ntest\nexamples\n*.sock\n/package.json\u0001{\n  \"name\": \"cookie-signature\",\n  \"version\": \"1.0.6\",\n  \"descript"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29va2llQDAuNS4w",
    "chars": 23188,
    "preview": "/SECURITY.md\u0004# Security Policies and Procedures\n\n## Reporting a Bug\n\nThe `cookie` team and community take all security b"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y29yc0AyLjguNQ==",
    "chars": 20068,
    "preview": "/README.md## cors\n\n[![NPM Version][npm-image]][npm-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build Stat"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2FjQDYuNy4xNA==",
    "chars": 81970,
    "preview": "/deno/deno.ts// Ignore the TypeScript errors\n// Since this file will only be used in Deno runtime\nexport const processAr"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2FsbC1iaW5kQDEuMC4y",
    "chars": 14912,
    "preview": "/LICENSE\u0004/MIT License\n\nCopyright (c) 2020 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2FsbHNpdGVzQDMuMS4w",
    "chars": 6392,
    "preview": "/license\u0004UMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby gra"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2FuaXVzZS1saXRlQDEuMC4zMDAwMTQ2OA==",
    "chars": 1959071,
    "preview": "\u0003-/data/features/innertext.js\u0005module.exports={A:{A:{\"1\":\"J D E F A B\",\"16\":\"DC\"},B:{\"1\":\"C K L G M N O P Q R S T U V W X"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2hhbGtAMi40LjI=",
    "chars": 27018,
    "preview": "/package.json\u0004{\n\t\"name\": \"chalk\",\n\t\"version\": \"2.4.2\",\n\t\"description\": \"Terminal string styling done right\",\n\t\"license\":"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2hhbGtANC4xLjI=",
    "chars": 35149,
    "preview": "/source/templates.js\r''use strict';\nconst TEMPLATE_REGEX = /(?:\\\\(u(?:[a-f\\d]{4}|\\{[a-f\\d]{1,6}\\})|x[a-f\\d]{2}|.))|(?:\\{"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2hhbGtANS4yLjA=",
    "chars": 43905,
    "preview": "*/source/vendor/supports-color/browser.d.ts$export {default} from './index.js';\n/source/utilities.js\u0003// TODO: When targe"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2hva2lkYXJAMy41LjM=",
    "chars": 90174,
    "preview": "/lib/fsevents-handler.js?'use strict';\n\nconst fs = require('fs');\nconst sysPath = require('path');\nconst { promisify } ="
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2xpLWN1cnNvckA0LjAuMA==",
    "chars": 4509,
    "preview": "/package.json\u0003W{\n\t\"name\": \"cli-cursor\",\n\t\"version\": \"4.0.0\",\n\t\"description\": \"Toggle the CLI cursor\",\n\t\"license\": \"MIT\","
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2xpLXNwaW5uZXJzQDIuNy4w",
    "chars": 21904,
    "preview": "/package.json\u0003{\n\t\"name\": \"cli-spinners\",\n\t\"version\": \"2.7.0\",\n\t\"description\": \"Spinners for use in the terminal\",\n\t\"lice"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y2xvbmVAMS4wLjQ=",
    "chars": 11181,
    "preview": "/README.md\u000e\u0001# clone\n\n[![build status](https://secure.travis-ci.org/pvorb/node-clone.png)](http://travis-ci.org/pvorb/nod"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y3Jvc3Mtc3Bhd25ANy4wLjM=",
    "chars": 21370,
    "preview": "/README.md\u0012x# cross-spawn\n\n[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Y3NzdHlwZUAyLjYuOQ==",
    "chars": 1667623,
    "preview": "/README.md\"f# CSSType\n\n[![npm](https://img.shields.io/npm/v/csstype.svg)](https://www.npmjs.com/package/csstype)\n\nTypeSc"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YW55bWF0Y2hAMy4xLjM=",
    "chars": 9710,
    "preview": "/package.json\u0003{\n  \"name\": \"anymatch\",\n  \"version\": \"3.1.3\",\n  \"description\": \"Matches strings against configurable strin"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YW5zaS1yZWdleEA1LjAuMQ==",
    "chars": 5669,
    "preview": "/readme.md\n\u0005# ansi-regex\n\n> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escap"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YW5zaS1yZWdleEA2LjAuMQ==",
    "chars": 5725,
    "preview": "/package.json\u0003{\n\t\"name\": \"ansi-regex\",\n\t\"version\": \"6.0.1\",\n\t\"description\": \"Regular expression for matching ANSI escape"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YW5zaS1zdHlsZXNAMy4yLjE=",
    "chars": 9417,
    "preview": "/package.json\u0003{\n\t\"name\": \"ansi-styles\",\n\t\"version\": \"3.2.1\",\n\t\"description\": \"ANSI escape codes for styling strings in t"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YW5zaS1zdHlsZXNANC4zLjA=",
    "chars": 17037,
    "preview": "/package.json\u0004\u001e{\n\t\"name\": \"ansi-styles\",\n\t\"version\": \"4.3.0\",\n\t\"description\": \"ANSI escape codes for styling strings in "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWJvcnQtY29udHJvbGxlckAzLjAuMA==",
    "chars": 76582,
    "preview": "/browser.js\u0001/*globals self, window */\n\"use strict\"\n\n/*eslint-disable @mysticatea/prettier */\nconst { AbortController, Ab"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWJzdHJhY3QtbG9nZ2luZ0AyLjAuMQ==",
    "chars": 2345,
    "preview": "/package.json\u0002{\n  \"name\": \"abstract-logging\",\n  \"version\": \"2.0.1\",\n  \"description\": \"A noop logger that conforms to the"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWNjZXB0c0AxLjMuOA==",
    "chars": 16852,
    "preview": "/HISTORY.md\u00131.3.8 / 2022-02-02\n==================\n\n  * deps: mime-types@~2.1.34\n    - deps: mime-db@~1.51.0\n  * deps: ne"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWNvcm4tanN4QDUuMy4y",
    "chars": 24455,
    "preview": "/index.js='use strict';\n\nconst XHTMLEntities = require('./xhtml');\n\nconst hexNumber = /^[\\da-fA-F]+$/;\nconst decimalNumb"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWNvcm5AOC44LjI=",
    "chars": 467493,
    "preview": "/dist/bin.js\f'use strict';\n\nvar path = require('path');\nvar fs = require('fs');\nvar acorn = require('./acorn.js');\n\nfunc"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWp2LWZvcm1hdHNAMi4xLjE=",
    "chars": 52472,
    "preview": "/dist/index.js\u0005\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst formats_1 = require(\"."
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YWp2QDguMTIuMA==",
    "chars": 1041543,
    "preview": "\u00010/dist/vocabularies/applicator/additionalItems.js\u0007\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: t"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YXJjaHlAMS4wLjA=",
    "chars": 8369,
    "preview": "/index.js\u0004tmodule.exports = function archy (obj, prefix, opts) {\n    if (prefix === undefined) prefix = '';\n    if (!opt"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YXJncGFyc2VAMi4wLjE=",
    "chars": 171640,
    "preview": "/CHANGELOG.md\u0017N# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YXJyYXktZmxhdHRlbkAxLjEuMQ==",
    "chars": 4476,
    "preview": "/LICENSE\u0004OThe MIT License (MIT)\n\nCopyright (c) 2014 Blake Embrey (hello@blakeembrey.com)\n\nPermission is hereby granted, "
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YXN5bmMtcmV0cnlAMS4zLjM=",
    "chars": 5267,
    "preview": "/README.md\u0006# async-retry\n\nRetrying made simple, easy, and async.\n\n## Usage\n\n```js\n// Packages\nconst retry = require('asy"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YXRvbWljLXNsZWVwQDEuMC4w",
    "chars": 6633,
    "preview": "/readme.md\u0006<h1 align=\"center\">Welcome to atomic-sleep ⏱️</h1>\n<p>\n  <img alt=\"Version\" src=\"https://img.shields.io/badge"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Ym9keS1wYXJzZXJAMS4yMC4x",
    "chars": 60480,
    "preview": "/lib/types/json.js\u0013/*!\n * body-parser\n * Copyright(c) 2014 Jonathan Ong\n * Copyright(c) 2014-2015 Douglas Christopher Wi"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/Ym9keS1wYXJzZXJAMS4yMC4y",
    "chars": 60948,
    "preview": "/lib/types/raw.js\u0007\\/*!\n * body-parser\n * Copyright(c) 2014-2015 Douglas Christopher Wilson\n * MIT Licensed\n */\n\n'use str"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YmFsYW5jZWQtbWF0Y2hAMS4wLjI=",
    "chars": 7009,
    "preview": "/.github/FUNDING.yml5tidelift: \"npm/balanced-match\"\npatreon: juliangruber\n/README.md\r# balanced-match\n\nMatch balanced st"
  },
  {
    "path": "tests/cdn-proxy/v2/mod/YmFzZTY0LWpzQDEuNS4x",
    "chars": 9701,
    "preview": "/base64js.min.js\b(function(a){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=a();else if(\"functi"
  }
]

// ... and 425 more files (download for full content)

About this extraction

This page contains the full source code of the codesandbox/nodebox-runtime GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 625 files (52.0 MB), approximately 8.1M tokens, and a symbol index with 129 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!