├── tests ├── cube │ └── test.scad ├── cylinder │ └── test.scad ├── lib │ ├── test.scad │ └── libraries │ │ └── util.scad ├── text │ └── test.scad ├── mcad │ └── test.scad ├── roof │ └── test.scad ├── csg │ └── test.scad ├── testing.ts ├── examples.test.ts └── included.test.ts ├── .gitignore ├── res └── fonts │ └── fonts.conf ├── runtime ├── src │ ├── modules.d.ts │ ├── openscad.mcad.ts │ ├── openscad.fonts.ts │ ├── files.ts │ └── openscad.ts ├── plugins │ ├── type-reference.js │ └── embed-file.js ├── tsconfig.json ├── package.json ├── rollup.config.js └── package-lock.json ├── patches ├── glib.patch └── fontconfig.patch ├── example ├── www │ └── index.html └── server.ts ├── Dockerfile ├── README.md ├── Makefile ├── Dockerfile.base └── COPYING /tests/cube/test.scad: -------------------------------------------------------------------------------- 1 | cube(10); 2 | -------------------------------------------------------------------------------- /tests/cylinder/test.scad: -------------------------------------------------------------------------------- 1 | $fn = 100; cylinder(20, 5, 10); 2 | -------------------------------------------------------------------------------- /tests/lib/test.scad: -------------------------------------------------------------------------------- 1 | use ; 2 | 3 | test_util(); 4 | -------------------------------------------------------------------------------- /tests/lib/libraries/util.scad: -------------------------------------------------------------------------------- 1 | module test_util() { 2 | cube(10); 3 | } -------------------------------------------------------------------------------- /tests/text/test.scad: -------------------------------------------------------------------------------- 1 | linear_extrude(10) 2 | text("hello world!"); 3 | -------------------------------------------------------------------------------- /tests/mcad/test.scad: -------------------------------------------------------------------------------- 1 | use ; 2 | 3 | bevel_gear(); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | libs 2 | build 3 | tests/**/out.stl 4 | .vscode 5 | runtime/dist 6 | node_modules 7 | res 8 | !res/fonts 9 | *.make 10 | -------------------------------------------------------------------------------- /res/fonts/fonts.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/roof/test.scad: -------------------------------------------------------------------------------- 1 | module sketch() { 2 | polygon(points=[[-5,-1],[-0.15,-1],[0,0],[0.15,-1],[5,-1], 3 | [5,-0.1],[4,0],[5,0.1],[5,1],[-5,1]]); 4 | } 5 | 6 | roof(method = "straight") sketch(); 7 | -------------------------------------------------------------------------------- /runtime/src/modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '../../res/*.conf' { 2 | const data: string; 3 | export default data; 4 | } 5 | 6 | declare module '../../res/*' { 7 | const data: Record; 8 | export default data; 9 | } 10 | -------------------------------------------------------------------------------- /runtime/src/openscad.mcad.ts: -------------------------------------------------------------------------------- 1 | import { OpenSCAD } from "./openscad"; 2 | import { writeFolder } from "./files"; 3 | 4 | import mcad from "../../res/MCAD"; 5 | 6 | export function addMCAD(openscad: OpenSCAD) { 7 | writeFolder(openscad.FS, "/libraries/MCAD/", mcad as Record); 8 | } 9 | -------------------------------------------------------------------------------- /runtime/plugins/type-reference.js: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | 3 | export default function typeReference(file, name) { 4 | return { 5 | name: "type-reference", 6 | transform(code, id) { 7 | if (resolve(id) == resolve(file)) { 8 | return `/// \n${code}`; 9 | } 10 | }, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /patches/glib.patch: -------------------------------------------------------------------------------- 1 | diff --git a/build.sh b/build.sh 2 | index 7ade24a..4a7a945 100644 3 | --- a/build.sh 4 | +++ b/build.sh 5 | @@ -5,7 +5,7 @@ SOURCE_DIR=$PWD 6 | 7 | # Working directories 8 | DEPS=$SOURCE_DIR/deps 9 | -TARGET=$SOURCE_DIR/target 10 | +TARGET=/emsdk/upstream/emscripten/cache/sysroot/ 11 | rm -rf $DEPS/ 12 | mkdir $DEPS 13 | mkdir -p $TARGET 14 | -------------------------------------------------------------------------------- /runtime/src/openscad.fonts.ts: -------------------------------------------------------------------------------- 1 | import { OpenSCAD } from "./openscad"; 2 | import { writeFile, writeFolder } from "./files"; 3 | 4 | import config from "../../res/fonts/fonts.conf"; 5 | import fonts from "../../res/liberation"; 6 | 7 | export function addFonts(openscad: OpenSCAD) { 8 | writeFile(openscad.FS, "/fonts/fonts.conf", config as string); 9 | writeFolder(openscad.FS, "/fonts/", fonts as Record); 10 | } 11 | -------------------------------------------------------------------------------- /runtime/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "exclude": ["dist"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "target": "esnext", 7 | "moduleResolution": "node", 8 | "esModuleInterop": false, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "skipLibCheck": true, 12 | "outDir": "dist", 13 | "declaration": true, 14 | "declarationDir": ".", 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /runtime/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openscad-runtime", 3 | "description": "OpenSCAD WASM Runtime Extensions", 4 | "module": "openscad.runtime.js", 5 | "scripts": { 6 | "build": "rollup --config rollup.config.js" 7 | }, 8 | "devDependencies": { 9 | "@rollup/plugin-typescript": "^8.3.1", 10 | "glob": "^7.2.0", 11 | "rollup": "^2.69.2", 12 | "typescript": "^4.6.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /runtime/rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from "@rollup/plugin-typescript"; 2 | import embedFile from "./plugins/embed-file"; 3 | import typeReference from "./plugins/type-reference"; 4 | 5 | const bundle = (name) => ({ 6 | input: `src/${name}.ts`, 7 | output: { 8 | file: `dist/${name}.js`, 9 | format: "esm", 10 | }, 11 | plugins: [ 12 | embedFile(), 13 | typescript({ tsconfig: "./tsconfig.json" }), 14 | typeReference(`src/${name}.ts`, name), 15 | ] 16 | }); 17 | 18 | export default [ 19 | bundle("openscad"), 20 | bundle("openscad.fonts"), 21 | bundle("openscad.mcad") 22 | ]; 23 | -------------------------------------------------------------------------------- /patches/fontconfig.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Makefile.am b/Makefile.am 2 | index 6d4cd32..3e88fe0 100644 3 | --- a/Makefile.am 4 | +++ b/Makefile.am 5 | @@ -21,10 +21,7 @@ 6 | # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 7 | # PERFORMANCE OF THIS SOFTWARE. 8 | 9 | -SUBDIRS=fontconfig fc-case fc-lang src \ 10 | - fc-cache fc-cat fc-conflist fc-list fc-match \ 11 | - fc-pattern fc-query fc-scan fc-validate conf.d \ 12 | - its po po-conf test 13 | +SUBDIRS=fontconfig src 14 | if ENABLE_DOCS 15 | SUBDIRS += doc 16 | endif 17 | @@ -86,7 +83,7 @@ xml_DATA = fonts.dtd 18 | if !ENABLE_CACHE_BUILD 19 | RUN_FC_CACHE_TEST=false 20 | else 21 | - RUN_FC_CACHE_TEST=test -z "$(DESTDIR)" 22 | + RUN_FC_CACHE_TEST=false 23 | endif 24 | 25 | # Creating ChangeLog from git log: 26 | -------------------------------------------------------------------------------- /example/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/csg/test.scad: -------------------------------------------------------------------------------- 1 | 2 | // CSG.scad - Basic example of CSG usage 3 | 4 | translate([-24,0,0]) { 5 | union() { 6 | cube(15, center=true); 7 | sphere(10); 8 | } 9 | } 10 | 11 | intersection() { 12 | cube(15, center=true); 13 | sphere(10); 14 | } 15 | 16 | translate([24,0,0]) { 17 | difference() { 18 | cube(15, center=true); 19 | sphere(10); 20 | } 21 | } 22 | 23 | echo(version=version()); 24 | // Written by Marius Kintel 25 | // 26 | // To the extent possible under law, the author(s) have dedicated all 27 | // copyright and related and neighboring rights to this software to the 28 | // public domain worldwide. This software is distributed without any 29 | // warranty. 30 | // 31 | // You should have received a copy of the CC0 Public Domain 32 | // Dedication along with this software. 33 | // If not, see . 34 | -------------------------------------------------------------------------------- /example/server.ts: -------------------------------------------------------------------------------- 1 | import { Application } from "https://deno.land/x/oak/mod.ts"; 2 | import logger from "https://deno.land/x/oak_logger/mod.ts"; 3 | import { join } from "https://deno.land/std/path/mod.ts"; 4 | 5 | const app = new Application(); 6 | 7 | app.use(logger.logger); 8 | 9 | // Serve static files from example/www and build folders 10 | app.use(async (context, next) => { 11 | if(context.request.url.pathname.startsWith("/src")){ 12 | context.request.url.pathname = context.request.url.pathname.substring("/src".length); 13 | await context.send({ root: join(Deno.cwd(), "../libs/openscad") }); 14 | return; 15 | } 16 | 17 | try { 18 | await context.send({ root: join(Deno.cwd(), "www"), index: "index.html" }); 19 | } catch { 20 | try { 21 | await context.send({ root: join(Deno.cwd(), "../build") }); 22 | } catch { 23 | await next(); 24 | } 25 | } 26 | }); 27 | 28 | const port = 8080; 29 | console.log(`server listening on port ${port}...`); 30 | await app.listen({ port }); 31 | -------------------------------------------------------------------------------- /tests/testing.ts: -------------------------------------------------------------------------------- 1 | import { join, dirname } from "https://deno.land/std/path/mod.ts"; 2 | import { OpenSCAD, FS } from "../build/openscad.js"; 3 | 4 | export async function loadTestFiles(instance: OpenSCAD, directory: string) { 5 | const fileMap = new Map(); 6 | 7 | await readFiles(fileMap, directory, '.'); 8 | 9 | for(const [from, to] of fileMap){ 10 | const content = await Deno.readFile(from); 11 | ensureDirExists(instance.FS, dirname(to)); 12 | instance.FS.writeFile(to, content); 13 | } 14 | } 15 | 16 | function ensureDirExists(fs: FS, path: string){ 17 | try{ 18 | fs.stat(path); 19 | }catch(e: unknown){ 20 | ensureDirExists(fs, dirname(path)); 21 | fs.mkdir(path); 22 | } 23 | } 24 | 25 | async function readFiles(map: Map, root: string, location: string) { 26 | const cwd = join(root, location); 27 | for await (const testFile of Deno.readDir(cwd)) { 28 | if(testFile.isDirectory){ 29 | await readFiles(map, root, join(location, testFile.name)); 30 | }else{ 31 | map.set(join(cwd, testFile.name), join('/', location, testFile.name)) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/examples.test.ts: -------------------------------------------------------------------------------- 1 | import { assertEquals } from "https://deno.land/std@0.125.0/testing/asserts.ts"; 2 | import OpenScad from "../build/openscad.js"; 3 | import { addFonts } from "../build/openscad.fonts.js"; 4 | import { join } from "https://deno.land/std/path/mod.ts"; 5 | import { loadTestFiles } from "./testing.ts"; 6 | 7 | const exampleDir = "../libs/openscad/examples/"; 8 | const sets = [ 9 | "Basics", 10 | "Advanced", 11 | "Parametric", 12 | ]; 13 | const exclude = [ 14 | "Advanced: module_recursion.scad" 15 | ] 16 | 17 | const examples = JSON.parse( 18 | await Deno.readTextFile(join(exampleDir, "examples.json")), 19 | ); 20 | 21 | for (const set of sets) { 22 | for (const file of examples[set]) { 23 | const name = `${set}: ${file}`; 24 | if(exclude.indexOf(name) != -1) { 25 | continue; 26 | } 27 | 28 | Deno.test({ 29 | name, 30 | fn: () => runTest(file, join(exampleDir, set)), 31 | }); 32 | } 33 | } 34 | 35 | async function runTest(entrypoint: string, directory: string) { 36 | const instance = await OpenScad({ noInitialRun: true }); 37 | addFonts(instance); 38 | 39 | await loadTestFiles(instance, directory); 40 | 41 | const code = instance.callMain([entrypoint, "--enable=roof", "-o", "out.stl"]); 42 | assertEquals(0, code); 43 | } 44 | -------------------------------------------------------------------------------- /runtime/src/files.ts: -------------------------------------------------------------------------------- 1 | import { FS } from "./openscad"; 2 | 3 | export function writeFile( 4 | fs: FS, 5 | filePath: string, 6 | contents: string, 7 | ) { 8 | ensureDirectoryExists(fs, filePath); 9 | fs.writeFile(filePath, fromHex(contents)); 10 | } 11 | 12 | export function writeFolder( 13 | fs: FS, 14 | base: string, 15 | contents: Record, 16 | ) { 17 | for (const [file, data] of Object.entries(contents)) { 18 | const fullPath = base + file; 19 | ensureDirectoryExists(fs, fullPath); 20 | fs.writeFile(fullPath, fromHex(data)); 21 | } 22 | } 23 | 24 | function fromHex(hex: string): Uint8Array { 25 | if (hex.length == 0) { 26 | return new Uint8Array(0); 27 | } 28 | return new Uint8Array(hex.match(/../g)!.map((h) => parseInt(h, 16))); 29 | } 30 | 31 | function ensureDirectoryExists(fs: FS, filePath: string) { 32 | const dirIndex = filePath.lastIndexOf("/"); 33 | if (dirIndex != -1) { 34 | const dirname = filePath.substring(0, dirIndex); 35 | ensureDirectoryExists(fs, dirname); 36 | if (dirname != "" && !exists(fs, dirname)) { 37 | fs.mkdir(dirname); 38 | } 39 | } 40 | } 41 | 42 | function exists(fs: FS, path: string) { 43 | try { 44 | fs.stat(path); 45 | return true; 46 | } catch (e) { 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /runtime/plugins/embed-file.js: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { readFileSync, statSync } from "fs"; 3 | import { join } from "path"; 4 | import { promisify } from "util"; 5 | import glob from "glob"; 6 | 7 | export default function embedFile() { 8 | function loadFile(path) { 9 | const content = readFileSync(path); 10 | return `export default "${content.toString("hex")}";`; 11 | } 12 | 13 | async function loadFolder(path) { 14 | const files = {}; 15 | 16 | const res = await promisify(glob)("**/*", { cwd: resolve(path), nodir: true }); 17 | for (const file of res) { 18 | files[file] = readFileSync(join(path, file)).toString("hex"); 19 | } 20 | 21 | return `export default ${JSON.stringify(files)};`; 22 | } 23 | 24 | return { 25 | name: "embed-file", 26 | resolveId(source) { 27 | const id = resolve("./src", source); 28 | if (id.startsWith(resolve("../res"))) { 29 | return id; 30 | } 31 | }, 32 | load(id) { 33 | if (id.startsWith(resolve("../res"))) { 34 | return ""; 35 | } 36 | }, 37 | transform(_, id) { 38 | if (id.startsWith(resolve("../res"))) { 39 | if (statSync(id).isFile()) { 40 | return loadFile(id); 41 | } else { 42 | return loadFolder(id); 43 | } 44 | } 45 | }, 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openscad-base 2 | 3 | ARG CMAKE_BUILD_TYPE=Release 4 | ARG EMXX_FLAGS 5 | 6 | COPY . . 7 | RUN export PKG_CONFIG_PATH="/emsdk/upstream/emscripten/cache/sysroot/lib/pkgconfig" && \ 8 | emcmake cmake -B ../build . \ 9 | -DWASM=ON \ 10 | -DSNAPSHOT=ON \ 11 | -DEXPERIMENTAL=ON \ 12 | -DENABLE_CAIRO=OFF \ 13 | -DUSE_MIMALLOC=OFF \ 14 | -DBoost_USE_STATIC_RUNTIME=ON \ 15 | -DBoost_USE_STATIC_LIBS=ON \ 16 | -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ 17 | -DHARFBUZZ_INCLUDE_DIRS=/emsdk/upstream/emscripten/cache/sysroot/include/harfbuzz \ 18 | -DFONTCONFIG_INCLUDE_DIR=/emsdk/upstream/emscripten/cache/sysroot/include/fontconfig \ 19 | -DFONTCONFIG_LIBRARIES=libfontconfig.a 20 | 21 | # Hack to fix build includes 22 | RUN sed -e "s|-isystem /emsdk/upstream/emscripten/cache/sysroot/include[^/]||g" -i ../build/CMakeFiles/OpenSCAD.dir/includes_C.rsp 23 | RUN sed -e "s|-isystem /emsdk/upstream/emscripten/cache/sysroot/include[^/]||g" -i ../build/CMakeFiles/OpenSCAD.dir/includes_CXX.rsp 24 | RUN sed -e "s|-lfontconfig|/emsdk/upstream/emscripten/cache/sysroot/lib/libglib-2.0.a /emsdk/upstream/emscripten/cache/sysroot/lib/libzip.a /emsdk/upstream/emscripten/cache/sysroot/lib/libz.a /emsdk/upstream/emscripten/cache/sysroot/lib/libfontconfig.a|g" -i ../build/CMakeFiles/OpenSCAD.dir/linklibs.rsp 25 | 26 | # Add emscripten flags here 27 | RUN sed -e "s|em++|em++ ${EMXX_FLAGS} -s USE_PTHREADS=0 -s NO_DISABLE_EXCEPTION_CATCHING -s FORCE_FILESYSTEM=1 -s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_RUNTIME_METHODS=['FS','callMain'] -s ENVIRONMENT=web,worker -s EXPORT_NAME=OpenSCAD -s EXIT_RUNTIME=1|g" -i ../build/CMakeFiles/OpenSCAD.dir/link.txt 28 | 29 | RUN cd ../build && make -j6 VERBOSE=1 30 | -------------------------------------------------------------------------------- /runtime/src/openscad.ts: -------------------------------------------------------------------------------- 1 | export interface InitOptions { 2 | noInitialRun: boolean; 3 | print?: (text: string) => void; 4 | printErr?: (text: string) => void; 5 | } 6 | 7 | export interface OpenSCAD { 8 | callMain(args: Array): number; 9 | FS: FS; 10 | locateFile?: (path: string, prefix: string) => string; 11 | onRuntimeInitialized?: () => void; 12 | } 13 | 14 | export interface FS { 15 | mkdir(path: string): void; 16 | rename(oldpath: string, newpath: string): void; 17 | rmdir(path: string): void; 18 | stat(path: string): unknown; //TODO: add stat result obj 19 | readFile(path: string): string | Uint8Array; 20 | readFile(path: string, opts: { encoding: "utf8" }): string; 21 | readFile(path: string, opts: { encoding: "binary" }): Uint8Array; 22 | writeFile(path: string, data: string | ArrayBufferView): void; 23 | unlink(path: string): void; 24 | } 25 | 26 | declare module globalThis { 27 | let OpenSCAD: Partial | undefined; 28 | } 29 | 30 | let wasmModule: string; 31 | 32 | async function OpenSCAD(options?: InitOptions): Promise { 33 | if (!wasmModule) { 34 | const url = new URL(`./openscad.wasm.js`, import.meta.url).href; 35 | const request = await fetch(url); 36 | wasmModule = "data:text/javascript;base64," + btoa(await request.text()); 37 | } 38 | 39 | const module: Partial = { 40 | noInitialRun: true, 41 | locateFile: (path: string) => new URL(`./${path}`, import.meta.url).href, 42 | ...options, 43 | }; 44 | 45 | globalThis.OpenSCAD = module; 46 | await import(wasmModule + `#${Math.random()}`); 47 | delete globalThis.OpenSCAD; 48 | 49 | await new Promise((resolve) => { 50 | module.onRuntimeInitialized = () => resolve(null); 51 | }); 52 | 53 | return module as unknown as OpenSCAD; 54 | } 55 | 56 | export default OpenSCAD; 57 | -------------------------------------------------------------------------------- /tests/included.test.ts: -------------------------------------------------------------------------------- 1 | import { assertEquals, assertStringIncludes, assertNotEquals } from "https://deno.land/std@0.125.0/testing/asserts.ts"; 2 | import { join } from "https://deno.land/std/path/mod.ts"; 3 | import { loadTestFiles } from "./testing.ts"; 4 | 5 | import OpenScad, { OpenSCAD } from "../build/openscad.js"; 6 | import { addFonts } from "../build/openscad.fonts.js"; 7 | import { addMCAD } from "../build/openscad.mcad.js"; 8 | 9 | Deno.test("csg", async () => { 10 | const instance = await OpenScad({ noInitialRun: true }); 11 | await runTest(instance, "./csg"); 12 | }); 13 | 14 | Deno.test("cube", async () => { 15 | const instance = await OpenScad({ noInitialRun: true }); 16 | await runTest(instance, "./cube"); 17 | }); 18 | 19 | Deno.test("cylinder", async () => { 20 | const instance = await OpenScad({ noInitialRun: true }); 21 | await runTest(instance, "./cylinder"); 22 | }); 23 | 24 | Deno.test("lib", async () => { 25 | const instance = await OpenScad({ noInitialRun: true }); 26 | await runTest(instance, "./lib"); 27 | }); 28 | 29 | Deno.test("mcad", async () => { 30 | const instance = await OpenScad({ noInitialRun: true }); 31 | addMCAD(instance); 32 | await runTest(instance, "./mcad"); 33 | }); 34 | 35 | Deno.test("text", async () => { 36 | const instance = await OpenScad({ noInitialRun: true }); 37 | addFonts(instance); 38 | await runTest(instance, "./text"); 39 | }); 40 | 41 | Deno.test("print stderr", async () => { 42 | let stderr = ""; 43 | 44 | const instance = await OpenScad({ 45 | noInitialRun: true, 46 | printErr: (text) => stderr += text + "\n", 47 | }); 48 | await runTest(instance, "./cube"); 49 | 50 | assertStringIncludes(stderr, "Facets:"); 51 | }); 52 | 53 | Deno.test("print stdout", async () => { 54 | let stdout = ""; 55 | 56 | const instance = await OpenScad({ 57 | noInitialRun: true, 58 | print: (text) => stdout += text + "\n", 59 | }); 60 | await runTest(instance, "./cube", "-"); 61 | 62 | assertNotEquals(stdout.length, 0); 63 | }); 64 | 65 | async function runTest(instance: OpenSCAD, directory: string, outfile?: string) { 66 | const __dirname = new URL('.', import.meta.url).pathname; 67 | 68 | await loadTestFiles(instance, join(__dirname, directory)); 69 | 70 | const code = instance.callMain([`/test.scad`, "--export-format", "stl", "-o", outfile ?? "out.stl"]); 71 | assertEquals(0, code); 72 | 73 | const output = instance.FS.readFile("out.stl", { encoding: "binary" }); 74 | await Deno.writeFile(join(__dirname, directory, "out.stl"), output); 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenSCAD WASM Port 2 | 3 | A full port of OpenSCAD to WASM. 4 | 5 | This project cross compiles all of the project dependencies and created a headless OpenSCAD WASM module. 6 | 7 | ## Setup 8 | 9 | Make sure that you have the following installed: 10 | 11 | - Make 12 | - Docker 13 | - Deno 14 | - lzip (might be missing on some distros) 15 | 16 | To build the project: 17 | 18 | ``` 19 | make all 20 | ``` 21 | 22 | Or for specific steps: 23 | 24 | ``` 25 | # Generate the library files 26 | make libs 27 | 28 | # Build the project 29 | make build 30 | 31 | # Build the project in debug mode 32 | make ENV=Debug build 33 | ``` 34 | 35 | ## Usage 36 | 37 | There is an example project in the example folder. Run it using: 38 | 39 | ``` 40 | cd example 41 | deno run --allow-net --allow-read server.ts 42 | 43 | # or 44 | 45 | make example 46 | ``` 47 | 48 | There are also automated tests that can be run using: 49 | 50 | ``` 51 | cd tests 52 | deno test --allow-read --allow-write 53 | 54 | # or 55 | 56 | make test 57 | ``` 58 | 59 | ## API 60 | 61 | The project is an ES6 module. Simply import the module: 62 | 63 | ```ts 64 | 65 | 66 | 67 | 68 | 102 | 103 | 104 | 105 | ``` 106 | 107 | For more information on reading and writing files check out the [Emscripten File System API](https://emscripten.org/docs/api_reference/Filesystem-API.html). 108 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DOCKER_TAG_BASE ?= openscad-base 2 | DOCKER_TAG_OPENSCAD ?= openscad 3 | 4 | all: build 5 | 6 | clean: 7 | rm -rf libs 8 | rm -rf build 9 | 10 | test: 11 | cd tests; deno test --allow-read --allow-write --jobs 4 12 | 13 | .PHONY: example 14 | example: 15 | cd example; deno run --allow-net --allow-read server.ts 16 | 17 | ENV=Release 18 | ifeq ($(strip $(ENV)),Debug) 19 | DOCKER_FLAGS= --build-arg CMAKE_BUILD_TYPE=Debug --build-arg EMXX_FLAGS="-gsource-map --source-map-base=/" 20 | endif 21 | 22 | .PHONY: build 23 | build: build/openscad.wasm.js build/openscad.fonts.js 24 | 25 | build/openscad.fonts.js: runtime/node_modules runtime/**/* res 26 | mkdir -p build 27 | cd runtime; npm run build 28 | cp runtime/dist/* build 29 | 30 | runtime/node_modules: 31 | cd runtime; npm install 32 | 33 | build/openscad.wasm.js: .image.make 34 | mkdir -p build 35 | docker run --name tmpcpy openscad 36 | docker cp tmpcpy:/build/openscad.js build/openscad.wasm.js 37 | docker cp tmpcpy:/build/openscad.wasm build/ 38 | docker cp tmpcpy:/build/openscad.wasm.map build/ || true 39 | docker rm tmpcpy 40 | 41 | .image.make: .base-image.make Dockerfile 42 | docker build libs/openscad -f Dockerfile -t $(DOCKER_TAG_OPENSCAD) ${DOCKER_FLAGS} 43 | touch $@ 44 | 45 | .base-image.make: libs Dockerfile.base 46 | docker build libs -f Dockerfile.base -t $(DOCKER_TAG_BASE) 47 | touch $@ 48 | 49 | libs: libs/cgal \ 50 | libs/eigen \ 51 | libs/fontconfig \ 52 | libs/freetype \ 53 | libs/glib \ 54 | libs/harfbuzz \ 55 | libs/lib3mf \ 56 | libs/libexpat \ 57 | libs/liblzma \ 58 | libs/libzip \ 59 | libs/openscad \ 60 | libs/boost \ 61 | libs/gmp-6.1.2 \ 62 | libs/mpfr-4.1.0 \ 63 | libs/zlib \ 64 | libs/libxml2 \ 65 | libs/doubleconversion 66 | 67 | SINGLE_BRANCH_MAIN=--branch main --single-branch 68 | SINGLE_BRANCH=--branch master --single-branch 69 | SHALLOW=--depth 1 70 | 71 | libs/cgal: 72 | git clone https://github.com/CGAL/cgal.git ${SHALLOW} --branch v5.4.5 --single-branch $@ 73 | 74 | libs/eigen: 75 | git clone https://github.com/PX4/eigen.git ${SHALLOW} ${SINGLE_BRANCH} $@ 76 | 77 | libs/fontconfig: 78 | git clone https://gitlab.freedesktop.org/fontconfig/fontconfig ${SHALLOW} ${SINGLE_BRANCH_MAIN} $@ 79 | git -C $@ apply ../../patches/fontconfig.patch 80 | 81 | libs/freetype: 82 | git clone https://github.com/freetype/freetype.git ${SHALLOW} ${SINGLE_BRANCH} $@ 83 | 84 | libs/glib: 85 | git clone https://gist.github.com/acfa1c09522705efa5eb0541d2d00887.git ${SHALLOW} ${SINGLE_BRANCH} $@ 86 | git -C $@ apply ../../patches/glib.patch 87 | 88 | libs/harfbuzz: 89 | git clone https://github.com/harfbuzz/harfbuzz.git ${SHALLOW} ${SINGLE_BRANCH_MAIN} $@ 90 | 91 | libs/lib3mf: 92 | git clone https://github.com/3MFConsortium/lib3mf.git ${SHALLOW} ${SINGLE_BRANCH} $@ 93 | 94 | libs/libexpat: 95 | git clone https://github.com/libexpat/libexpat ${SHALLOW} ${SINGLE_BRANCH} $@ 96 | 97 | libs/liblzma: 98 | git clone https://github.com/kobolabs/liblzma.git ${SHALLOW} ${SINGLE_BRANCH} $@ 99 | 100 | libs/libzip: 101 | git clone https://github.com/nih-at/libzip.git ${SHALLOW} ${SINGLE_BRANCH_MAIN} $@ 102 | 103 | libs/zlib: 104 | git clone https://github.com/madler/zlib.git ${SHALLOW} ${SINGLE_BRANCH} $@ 105 | 106 | libs/libxml2: 107 | git clone https://gitlab.gnome.org/GNOME/libxml2.git ${SHALLOW} ${SINGLE_BRANCH} $@ 108 | 109 | libs/doubleconversion: 110 | git clone https://github.com/google/double-conversion ${SHALLOW} ${SINGLE_BRANCH} $@ 111 | 112 | libs/openscad: 113 | git clone --recurse https://github.com/ochafik/openscad.git --branch filtered-number --single-branch $@ 114 | 115 | libs/boost: 116 | git clone --recurse https://github.com/boostorg/boost.git ${SHALLOW} ${SINGLE_BRANCH} $@ 117 | 118 | libs/gmp-6.1.2: 119 | wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz 120 | tar xf gmp-6.1.2.tar.lz -C libs 121 | rm gmp-6.1.2.tar.lz 122 | 123 | libs/mpfr-4.1.0: 124 | wget https://www.mpfr.org/mpfr-4.1.0/mpfr-4.1.0.tar.xz 125 | tar xf mpfr-4.1.0.tar.xz -C libs 126 | rm mpfr-4.1.0.tar.xz 127 | 128 | res: \ 129 | res/liberation \ 130 | res/MCAD 131 | 132 | res/liberation: 133 | git clone --recurse https://github.com/shantigilbert/liberation-fonts-ttf.git ${SHALLOW} ${SINGLE_BRANCH} $@ 134 | 135 | res/MCAD: 136 | git clone https://github.com/openscad/MCAD.git ${SHALLOW} ${SINGLE_BRANCH} $@ 137 | -------------------------------------------------------------------------------- /Dockerfile.base: -------------------------------------------------------------------------------- 1 | FROM emscripten/emsdk as boost 2 | COPY boost . 3 | RUN ./bootstrap.sh 4 | RUN ./b2 toolset=emscripten cxxflags="-std=c++11 -stdlib=libc++" linkflags="-stdlib=libc++" release --disable-icu --with-regex --with-filesystem --with-system --with-program_options install link=static runtime-link=static --prefix=/emsdk/upstream/emscripten/cache/sysroot 5 | 6 | 7 | FROM emscripten/emsdk as zlib 8 | COPY zlib . 9 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release 10 | RUN cd ../build && make && make install 11 | 12 | 13 | FROM emscripten/emsdk as libzip 14 | COPY --from=zlib /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 15 | COPY libzip . 16 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release 17 | RUN cd ../build && make && make install 18 | 19 | 20 | FROM emscripten/emsdk as glib 21 | COPY --from=zlib /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 22 | COPY glib . 23 | RUN apt-get update \ 24 | && apt-get install -qqy \ 25 | build-essential \ 26 | prelink \ 27 | autoconf \ 28 | libtool \ 29 | texinfo \ 30 | pkgconf \ 31 | ninja-build \ 32 | python3-pip \ 33 | && pip3 install git+https://github.com/kleisauke/meson@wasm-vips 34 | RUN chmod +x build.sh; ./build.sh 35 | 36 | 37 | FROM emscripten/emsdk as freetype 38 | COPY --from=zlib /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 39 | COPY freetype . 40 | RUN emcmake cmake -B ../build . -DFT_REQUIRE_ZLIB=TRUE -DCMAKE_BUILD_TYPE=Release 41 | RUN cd ../build && make && make install 42 | 43 | 44 | FROM emscripten/emsdk as libxml2 45 | COPY libxml2 . 46 | RUN emcmake cmake -B ../build . -DLIBXML2_WITH_PYTHON=OFF -DLIBXML2_WITH_LZMA=OFF -DLIBXML2_WITH_ZLIB=OFF -DCMAKE_BUILD_TYPE=Release 47 | RUN cd ../build && make && make install 48 | 49 | 50 | FROM emscripten/emsdk as fontconfig 51 | RUN apt-get update && apt-get install pkg-config gperf automake libtool gettext autopoint -y 52 | COPY --from=zlib /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 53 | COPY --from=freetype /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 54 | COPY --from=libxml2 /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 55 | COPY fontconfig . 56 | RUN FREETYPE_CFLAGS="-I/emsdk/upstream/emscripten/cache/sysroot/include/freetype2" FREETYPE_LIBS="-lfreetype -lz" emconfigure ./autogen.sh --host none --disable-docs --disable-shared --enable-static --sysconfdir=/ --localstatedir=/ --with-default-fonts=/fonts --enable-libxml2 --prefix=/emsdk/upstream/emscripten/cache/sysroot 57 | RUN emmake make 58 | RUN emmake make install 59 | 60 | 61 | FROM emscripten/emsdk as harfbuzz 62 | COPY --from=freetype /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 63 | COPY harfbuzz . 64 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release -DHB_HAVE_FREETYPE=ON 65 | RUN cd ../build && make && make install 66 | 67 | 68 | FROM emscripten/emsdk as eigen 69 | COPY eigen . 70 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release 71 | RUN cd ../build && make && make install 72 | 73 | 74 | FROM emscripten/emsdk as cgal 75 | COPY cgal . 76 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release 77 | RUN cd ../build && make && make install 78 | 79 | 80 | FROM emscripten/emsdk as gmp 81 | COPY gmp-6.1.2 . 82 | RUN emconfigure ./configure --disable-assembly --host none --enable-cxx --prefix=/emsdk/upstream/emscripten/cache/sysroot 83 | RUN make && make install 84 | 85 | 86 | FROM emscripten/emsdk as mpfr 87 | COPY --from=gmp /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 88 | COPY mpfr-4.1.0 . 89 | RUN emconfigure ./configure --host none --with-gmp=/emsdk/upstream/emscripten/cache/sysroot --prefix=/emsdk/upstream/emscripten/cache/sysroot 90 | RUN make && make install 91 | 92 | 93 | FROM emscripten/emsdk as doubleconversion 94 | COPY doubleconversion . 95 | RUN emcmake cmake -B ../build . -DCMAKE_BUILD_TYPE=Release 96 | RUN cd ../build && make && make install 97 | 98 | 99 | FROM emscripten/emsdk as openscad-base 100 | RUN apt-get update && apt-get install pkg-config flex bison gettext python-is-python3 gpg -y 101 | COPY --from=boost /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 102 | COPY --from=gmp /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 103 | COPY --from=mpfr /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 104 | COPY --from=cgal /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 105 | COPY --from=eigen /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 106 | COPY --from=harfbuzz /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 107 | COPY --from=fontconfig /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 108 | COPY --from=glib /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 109 | COPY --from=libzip /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 110 | COPY --from=doubleconversion /emsdk/upstream/emscripten/cache/sysroot /emsdk/upstream/emscripten/cache/sysroot 111 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /runtime/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openscad-runtime", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "openscad-runtime", 8 | "devDependencies": { 9 | "@rollup/plugin-typescript": "^8.3.1", 10 | "glob": "^7.2.0", 11 | "rollup": "^2.69.2", 12 | "typescript": "^4.6.2" 13 | } 14 | }, 15 | "node_modules/@rollup/plugin-typescript": { 16 | "version": "8.3.1", 17 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.1.tgz", 18 | "integrity": "sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==", 19 | "dev": true, 20 | "dependencies": { 21 | "@rollup/pluginutils": "^3.1.0", 22 | "resolve": "^1.17.0" 23 | }, 24 | "engines": { 25 | "node": ">=8.0.0" 26 | }, 27 | "peerDependencies": { 28 | "rollup": "^2.14.0", 29 | "tslib": "*", 30 | "typescript": ">=3.7.0" 31 | } 32 | }, 33 | "node_modules/@rollup/pluginutils": { 34 | "version": "3.1.0", 35 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", 36 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", 37 | "dev": true, 38 | "dependencies": { 39 | "@types/estree": "0.0.39", 40 | "estree-walker": "^1.0.1", 41 | "picomatch": "^2.2.2" 42 | }, 43 | "engines": { 44 | "node": ">= 8.0.0" 45 | }, 46 | "peerDependencies": { 47 | "rollup": "^1.20.0||^2.0.0" 48 | } 49 | }, 50 | "node_modules/@types/estree": { 51 | "version": "0.0.39", 52 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 53 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 54 | "dev": true 55 | }, 56 | "node_modules/balanced-match": { 57 | "version": "1.0.2", 58 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 59 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 60 | "dev": true 61 | }, 62 | "node_modules/brace-expansion": { 63 | "version": "1.1.11", 64 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 65 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 66 | "dev": true, 67 | "dependencies": { 68 | "balanced-match": "^1.0.0", 69 | "concat-map": "0.0.1" 70 | } 71 | }, 72 | "node_modules/concat-map": { 73 | "version": "0.0.1", 74 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 75 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 76 | "dev": true 77 | }, 78 | "node_modules/estree-walker": { 79 | "version": "1.0.1", 80 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 81 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 82 | "dev": true 83 | }, 84 | "node_modules/fs.realpath": { 85 | "version": "1.0.0", 86 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 87 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 88 | "dev": true 89 | }, 90 | "node_modules/fsevents": { 91 | "version": "2.3.2", 92 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 93 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 94 | "dev": true, 95 | "hasInstallScript": true, 96 | "optional": true, 97 | "os": [ 98 | "darwin" 99 | ], 100 | "engines": { 101 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 102 | } 103 | }, 104 | "node_modules/function-bind": { 105 | "version": "1.1.1", 106 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 107 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 108 | "dev": true 109 | }, 110 | "node_modules/glob": { 111 | "version": "7.2.0", 112 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 113 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 114 | "dev": true, 115 | "dependencies": { 116 | "fs.realpath": "^1.0.0", 117 | "inflight": "^1.0.4", 118 | "inherits": "2", 119 | "minimatch": "^3.0.4", 120 | "once": "^1.3.0", 121 | "path-is-absolute": "^1.0.0" 122 | }, 123 | "engines": { 124 | "node": "*" 125 | }, 126 | "funding": { 127 | "url": "https://github.com/sponsors/isaacs" 128 | } 129 | }, 130 | "node_modules/has": { 131 | "version": "1.0.3", 132 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 133 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 134 | "dev": true, 135 | "dependencies": { 136 | "function-bind": "^1.1.1" 137 | }, 138 | "engines": { 139 | "node": ">= 0.4.0" 140 | } 141 | }, 142 | "node_modules/inflight": { 143 | "version": "1.0.6", 144 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 145 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 146 | "dev": true, 147 | "dependencies": { 148 | "once": "^1.3.0", 149 | "wrappy": "1" 150 | } 151 | }, 152 | "node_modules/inherits": { 153 | "version": "2.0.4", 154 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 155 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 156 | "dev": true 157 | }, 158 | "node_modules/is-core-module": { 159 | "version": "2.8.1", 160 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", 161 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", 162 | "dev": true, 163 | "dependencies": { 164 | "has": "^1.0.3" 165 | }, 166 | "funding": { 167 | "url": "https://github.com/sponsors/ljharb" 168 | } 169 | }, 170 | "node_modules/minimatch": { 171 | "version": "3.1.2", 172 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 173 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 174 | "dev": true, 175 | "dependencies": { 176 | "brace-expansion": "^1.1.7" 177 | }, 178 | "engines": { 179 | "node": "*" 180 | } 181 | }, 182 | "node_modules/once": { 183 | "version": "1.4.0", 184 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 185 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 186 | "dev": true, 187 | "dependencies": { 188 | "wrappy": "1" 189 | } 190 | }, 191 | "node_modules/path-is-absolute": { 192 | "version": "1.0.1", 193 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 194 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 195 | "dev": true, 196 | "engines": { 197 | "node": ">=0.10.0" 198 | } 199 | }, 200 | "node_modules/path-parse": { 201 | "version": "1.0.7", 202 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 203 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 204 | "dev": true 205 | }, 206 | "node_modules/picomatch": { 207 | "version": "2.3.1", 208 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 209 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 210 | "dev": true, 211 | "engines": { 212 | "node": ">=8.6" 213 | }, 214 | "funding": { 215 | "url": "https://github.com/sponsors/jonschlinkert" 216 | } 217 | }, 218 | "node_modules/resolve": { 219 | "version": "1.22.0", 220 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 221 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 222 | "dev": true, 223 | "dependencies": { 224 | "is-core-module": "^2.8.1", 225 | "path-parse": "^1.0.7", 226 | "supports-preserve-symlinks-flag": "^1.0.0" 227 | }, 228 | "bin": { 229 | "resolve": "bin/resolve" 230 | }, 231 | "funding": { 232 | "url": "https://github.com/sponsors/ljharb" 233 | } 234 | }, 235 | "node_modules/rollup": { 236 | "version": "2.69.2", 237 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.69.2.tgz", 238 | "integrity": "sha512-KghktpWg3Wd+nYCsx3Griidm2/CKIJYG2yyaaKspo0TXSoGdW+0duwzKl4wWIu62oN3mFg3zCDbwVRPwuNPPlA==", 239 | "dev": true, 240 | "bin": { 241 | "rollup": "dist/bin/rollup" 242 | }, 243 | "engines": { 244 | "node": ">=10.0.0" 245 | }, 246 | "optionalDependencies": { 247 | "fsevents": "~2.3.2" 248 | } 249 | }, 250 | "node_modules/supports-preserve-symlinks-flag": { 251 | "version": "1.0.0", 252 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 253 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 254 | "dev": true, 255 | "engines": { 256 | "node": ">= 0.4" 257 | }, 258 | "funding": { 259 | "url": "https://github.com/sponsors/ljharb" 260 | } 261 | }, 262 | "node_modules/tslib": { 263 | "version": "2.3.1", 264 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 265 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", 266 | "dev": true, 267 | "peer": true 268 | }, 269 | "node_modules/typescript": { 270 | "version": "4.6.2", 271 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", 272 | "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", 273 | "dev": true, 274 | "bin": { 275 | "tsc": "bin/tsc", 276 | "tsserver": "bin/tsserver" 277 | }, 278 | "engines": { 279 | "node": ">=4.2.0" 280 | } 281 | }, 282 | "node_modules/wrappy": { 283 | "version": "1.0.2", 284 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 285 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 286 | "dev": true 287 | } 288 | }, 289 | "dependencies": { 290 | "@rollup/plugin-typescript": { 291 | "version": "8.3.1", 292 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.1.tgz", 293 | "integrity": "sha512-84rExe3ICUBXzqNX48WZV2Jp3OddjTMX97O2Py6D1KJaGSwWp0mDHXj+bCGNJqWHIEKDIT2U0sDjhP4czKi6cA==", 294 | "dev": true, 295 | "requires": { 296 | "@rollup/pluginutils": "^3.1.0", 297 | "resolve": "^1.17.0" 298 | } 299 | }, 300 | "@rollup/pluginutils": { 301 | "version": "3.1.0", 302 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", 303 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", 304 | "dev": true, 305 | "requires": { 306 | "@types/estree": "0.0.39", 307 | "estree-walker": "^1.0.1", 308 | "picomatch": "^2.2.2" 309 | } 310 | }, 311 | "@types/estree": { 312 | "version": "0.0.39", 313 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 314 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 315 | "dev": true 316 | }, 317 | "balanced-match": { 318 | "version": "1.0.2", 319 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 320 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 321 | "dev": true 322 | }, 323 | "brace-expansion": { 324 | "version": "1.1.11", 325 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 326 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 327 | "dev": true, 328 | "requires": { 329 | "balanced-match": "^1.0.0", 330 | "concat-map": "0.0.1" 331 | } 332 | }, 333 | "concat-map": { 334 | "version": "0.0.1", 335 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 336 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 337 | "dev": true 338 | }, 339 | "estree-walker": { 340 | "version": "1.0.1", 341 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", 342 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", 343 | "dev": true 344 | }, 345 | "fs.realpath": { 346 | "version": "1.0.0", 347 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 348 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 349 | "dev": true 350 | }, 351 | "fsevents": { 352 | "version": "2.3.2", 353 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 354 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 355 | "dev": true, 356 | "optional": true 357 | }, 358 | "function-bind": { 359 | "version": "1.1.1", 360 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 361 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 362 | "dev": true 363 | }, 364 | "glob": { 365 | "version": "7.2.0", 366 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 367 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 368 | "dev": true, 369 | "requires": { 370 | "fs.realpath": "^1.0.0", 371 | "inflight": "^1.0.4", 372 | "inherits": "2", 373 | "minimatch": "^3.0.4", 374 | "once": "^1.3.0", 375 | "path-is-absolute": "^1.0.0" 376 | } 377 | }, 378 | "has": { 379 | "version": "1.0.3", 380 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 381 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 382 | "dev": true, 383 | "requires": { 384 | "function-bind": "^1.1.1" 385 | } 386 | }, 387 | "inflight": { 388 | "version": "1.0.6", 389 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 390 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 391 | "dev": true, 392 | "requires": { 393 | "once": "^1.3.0", 394 | "wrappy": "1" 395 | } 396 | }, 397 | "inherits": { 398 | "version": "2.0.4", 399 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 400 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 401 | "dev": true 402 | }, 403 | "is-core-module": { 404 | "version": "2.8.1", 405 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", 406 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", 407 | "dev": true, 408 | "requires": { 409 | "has": "^1.0.3" 410 | } 411 | }, 412 | "minimatch": { 413 | "version": "3.1.2", 414 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 415 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 416 | "dev": true, 417 | "requires": { 418 | "brace-expansion": "^1.1.7" 419 | } 420 | }, 421 | "once": { 422 | "version": "1.4.0", 423 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 424 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 425 | "dev": true, 426 | "requires": { 427 | "wrappy": "1" 428 | } 429 | }, 430 | "path-is-absolute": { 431 | "version": "1.0.1", 432 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 433 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 434 | "dev": true 435 | }, 436 | "path-parse": { 437 | "version": "1.0.7", 438 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 439 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 440 | "dev": true 441 | }, 442 | "picomatch": { 443 | "version": "2.3.1", 444 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 445 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 446 | "dev": true 447 | }, 448 | "resolve": { 449 | "version": "1.22.0", 450 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 451 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 452 | "dev": true, 453 | "requires": { 454 | "is-core-module": "^2.8.1", 455 | "path-parse": "^1.0.7", 456 | "supports-preserve-symlinks-flag": "^1.0.0" 457 | } 458 | }, 459 | "rollup": { 460 | "version": "2.69.2", 461 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.69.2.tgz", 462 | "integrity": "sha512-KghktpWg3Wd+nYCsx3Griidm2/CKIJYG2yyaaKspo0TXSoGdW+0duwzKl4wWIu62oN3mFg3zCDbwVRPwuNPPlA==", 463 | "dev": true, 464 | "requires": { 465 | "fsevents": "~2.3.2" 466 | } 467 | }, 468 | "supports-preserve-symlinks-flag": { 469 | "version": "1.0.0", 470 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 471 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 472 | "dev": true 473 | }, 474 | "tslib": { 475 | "version": "2.3.1", 476 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", 477 | "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", 478 | "dev": true, 479 | "peer": true 480 | }, 481 | "typescript": { 482 | "version": "4.6.2", 483 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", 484 | "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", 485 | "dev": true 486 | }, 487 | "wrappy": { 488 | "version": "1.0.2", 489 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 490 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 491 | "dev": true 492 | } 493 | } 494 | } 495 | --------------------------------------------------------------------------------