Switch to webpack
This commit is contained in:
parent
5e0dfaf13d
commit
4b11073437
17 changed files with 238 additions and 69 deletions
54
Makefile
54
Makefile
|
|
@ -4,12 +4,13 @@ SINGLE_BRANCH_MAIN=--branch main --single-branch
|
|||
SINGLE_BRANCH=--branch master --single-branch
|
||||
SHALLOW=--depth 1
|
||||
|
||||
all: build
|
||||
all: public
|
||||
|
||||
.PHONY: public
|
||||
public: \
|
||||
libs/openscad \
|
||||
public/openscad.js \
|
||||
public/openscad-worker-inlined.js \
|
||||
public/openscad.wasm \
|
||||
public/libraries/fonts.zip \
|
||||
public/libraries/NopSCADlib.zip \
|
||||
public/libraries/BOSL.zip \
|
||||
|
|
@ -27,26 +28,49 @@ public: \
|
|||
|
||||
clean:
|
||||
rm -fR libs build
|
||||
rm -fR public/openscad-worker-inlined.js
|
||||
rm -fR public/openscad.{js,wasm}
|
||||
rm -fR public/libraries
|
||||
rm -fR src/wasm
|
||||
|
||||
build: public
|
||||
npm run build
|
||||
dist/index.js: public
|
||||
npm run build2
|
||||
# mkdir -f build/libraries
|
||||
# cp -f public/libraries/*.zip build/libraries
|
||||
|
||||
src/wasm/openscad.js:
|
||||
wget ${WASM_BUILD_URL} -O OpenSCAD-WebAssembly.zip
|
||||
mkdir -p src/wasm
|
||||
( cd src/wasm && rm -f openscad.{js,wasm} && unzip ../../OpenSCAD-WebAssembly.zip )
|
||||
rm OpenSCAD-WebAssembly.zip
|
||||
|
||||
public/openscad.js: src/wasm/openscad.js
|
||||
cp src/wasm/openscad.{js,wasm} public
|
||||
|
||||
public/openscad-worker-inlined.js: src/openscad-worker.ts src/wasm/openscad.js
|
||||
dist/openscad-worker.js: src/openscad-worker.ts
|
||||
npx rollup -c
|
||||
|
||||
libs/openscad:
|
||||
mkdir -p libs/openscad
|
||||
wget ${WASM_BUILD_URL} -O libs/openscad.zip
|
||||
( cd libs/openscad && unzip ../openscad.zip )
|
||||
rm libs/openscad.zip
|
||||
rm -f src/wasm
|
||||
ln -sf $(shell pwd)/libs/openscad src/wasm
|
||||
|
||||
public/openscad.js: libs/openscad libs/openscad/openscad.js
|
||||
cp libs/openscad/openscad.{js,wasm} public
|
||||
|
||||
public/openscad.wasm: libs/openscad libs/openscad/openscad.wasm
|
||||
cp libs/openscad/openscad.wasm public
|
||||
|
||||
# public/openscad-worker-inlined.js: src/openscad-worker.ts src/wasm/openscad.js
|
||||
# npx rollup -c
|
||||
|
||||
# js/src/openscad-worker.js: src/openscad-worker.ts
|
||||
# tsc
|
||||
|
||||
# public/openscad-worker-inlined.js: inline-openscad-worker.ts js/src/openscad-worker.js public/openscad.js js/src/filesystem.js js/src/zip-archives.js
|
||||
# cp src/wasm/openscad.{js,wasm} public
|
||||
# npx webpack --config webpack.config.js
|
||||
# tsc src/BrowserFS.d.ts src/openscad-worker.ts --outFile public/openscad-worker-inlined.js --module amd --moduleResolution nodenext
|
||||
# deno run --allow-net --allow-read --allow-write inline-openscad-worker.ts \
|
||||
# js/src/openscad-worker.js \
|
||||
# public/openscad.js \
|
||||
# public/openscad-worker-inlined.js \
|
||||
# https://ochafik.com/openscad/openscad-worker-inlined.js
|
||||
# cp js/src/{filesystem,zip-archives}.js public
|
||||
|
||||
public/libraries/fonts.zip: libs/liberation
|
||||
mkdir -p public/libraries
|
||||
cp fonts.conf libs/liberation
|
||||
|
|
|
|||
38
README.md
38
README.md
|
|
@ -4,6 +4,19 @@ WIP revamp of https://github.com/ochafik/openscad-wasm/tree/editor-ochafik.com /
|
|||
|
||||
Licenses: see [LICENSES](./LICENSES).
|
||||
|
||||
## Features
|
||||
|
||||
- Automatic preview on edit (F5), and full rendering on Ctrl+Enter (or F6)
|
||||
- Syntax highlighting
|
||||
- Ships with many standard SCAD libraries
|
||||
- Autocomplete of imports
|
||||
- Autocomplete of symbols / function calls (pseudo-parses file and its transitive imports)
|
||||
-
|
||||
|
||||
## TODO
|
||||
|
||||
- Investigate https://www.npmjs.com/package/react-codemirror for mobile editor (Monaco on iOS is terribly broken)
|
||||
- Link to https://www.npmjs.com/package/monaco-languages MIT JS source for language
|
||||
## Build
|
||||
|
||||
Prerequisites:
|
||||
|
|
@ -12,14 +25,23 @@ Prerequisites:
|
|||
* npm
|
||||
* deno
|
||||
|
||||
Local dev:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
|
||||
# When doing local development, ensure the import.meta.url is replaced to localhost:
|
||||
# (otherwise will get cryptic `RangeError: WebAssembly.Table.get(): invalid index 999948 into function table`)
|
||||
dev=1 make public
|
||||
make public
|
||||
npm start
|
||||
|
||||
# When building a release
|
||||
make
|
||||
# http://localhost:4000/
|
||||
```
|
||||
make public
|
||||
npm run start:prod
|
||||
# http://localhost:3000/dist/
|
||||
|
||||
Deployment (edit "homepage" in `package.json` to match your deployment root!):
|
||||
|
||||
```bash
|
||||
make public
|
||||
npm build
|
||||
|
||||
rm -fR ../ochafik.github.io/openscad2 && cp -R dist ../ochafik.github.io/openscad2
|
||||
# Now commit and push changes, wait for site update and enjoy!
|
||||
```
|
||||
25
openscad-worker.rollup.config.js
Normal file
25
openscad-worker.rollup.config.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import typescript from 'rollup-plugin-typescript';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
import packageConfig from './package.json'
|
||||
|
||||
const LOCAL_URL = process.env.LOCAL_URL ?? 'http://localhost:4000/';
|
||||
const PUBLIC_URL = process.env.PUBLIC_URL ?? packageConfig.homepage;
|
||||
|
||||
export default [
|
||||
{
|
||||
input: 'src/openscad-worker.ts',
|
||||
output: {
|
||||
file: 'dist/openscad-worker.js',
|
||||
format: 'es'
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
rootDir: 'src',
|
||||
}),
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
'import.meta.url': JSON.stringify(process.env.NODE_ENV !== 'production' ? LOCAL_URL : PUBLIC_URL),
|
||||
})
|
||||
]
|
||||
},
|
||||
];
|
||||
31
package.json
31
package.json
|
|
@ -2,28 +2,29 @@
|
|||
"name": "openscad-playground",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"homepage": "https://ochafik.com/openscad2/",
|
||||
"dependencies": {
|
||||
"@monaco-editor/loader": "^1.3.2",
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"debug": "^4.3.4",
|
||||
"monaco-editor": "^0.36.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-stl-viewer": "^2.2.5",
|
||||
"react-widgets": "^5.8.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"tsc": "tsc"
|
||||
"start": "concurrently 'npx webpack serve --mode=development' 'NODE_ENV=development npx rollup --config openscad-worker.rollup.config.js --watch'",
|
||||
"start:prod": "PUBLIC_URL=http://localhost:3000/dist/ npm run build && npx serve",
|
||||
"build": "NODE_ENV=production npx rollup --config openscad-worker.rollup.config.js && webpack --mode=production"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
|
|
@ -44,12 +45,28 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-html": "^1.0.2",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-typescript": "^11.0.0",
|
||||
"@types/filesystem": "^0.0.32",
|
||||
"@types/node": "^18.15.6",
|
||||
"@web/rollup-plugin-html": "^1.11.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.3",
|
||||
"livereload": "^0.9.3",
|
||||
"rollup": "^2.79.1",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-css": "^1.0.10",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-typescript": "^1.0.1",
|
||||
"rollup-plugin-typescript2": "^0.34.1",
|
||||
"rollup-watch": "^4.3.1",
|
||||
"serve": "^14.2.0",
|
||||
"ts-loader": "^9.4.2",
|
||||
"tslib": "^2.5.0",
|
||||
"webpack-cli": "^5.0.1"
|
||||
"webpack": "^5.76.3",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.13.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
<meta charset="utf-8" />
|
||||
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/BrowserFS/2.0.0/browserfs.min.js" defer></script> -->
|
||||
<script src="%PUBLIC_URL%/browserfs.min.js"></script>
|
||||
<script src="./browserfs.min.js" defer></script>
|
||||
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<script src="./index.js" defer></script>
|
||||
|
||||
<link rel="icon" href="../public/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
|
||||
|
|
@ -16,9 +18,9 @@
|
|||
name="description"
|
||||
content="OpenSCAD Playground: edit .scad models and render them to STL from the browser (WebAssembly build OpenSCAD, with Monaco editor and STL Viewer)"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<!-- https://developers.google.com/web/fundamentals/web-app-manifest/ -->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
|
|
|
|||
16
public/openscad.js
Normal file
16
public/openscad.js
Normal file
File diff suppressed because one or more lines are too long
BIN
public/openscad.wasm
Executable file
BIN
public/openscad.wasm
Executable file
Binary file not shown.
|
|
@ -1,24 +0,0 @@
|
|||
// npx rollup -c
|
||||
// npx rollup ./src/openscad-worker.ts -o public/openscad-worker-inlined.js -f cjs
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
export default {
|
||||
input: 'src/openscad-worker.ts',
|
||||
output: {
|
||||
file: 'public/openscad-worker-inlined.js',
|
||||
format: 'es'
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
// outDir: 'public2',
|
||||
rootDir: 'src',
|
||||
}),
|
||||
replace({
|
||||
'import.meta.url': JSON.stringify(process.env.dev
|
||||
? 'http://localhost:3000/'
|
||||
: 'https://ochafik.com/openscad/openscad-worker-inlined.js'),
|
||||
})
|
||||
|
||||
]
|
||||
};
|
||||
10
src/App.tsx
10
src/App.tsx
|
|
@ -31,7 +31,13 @@ function EditorPanel() {
|
|||
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter,
|
||||
monaco.KeyCode.F6,
|
||||
],
|
||||
run: () => model.render()
|
||||
run: () => model.render({isPreview: false})
|
||||
});
|
||||
editor.addAction({
|
||||
id: "openscad-preview",
|
||||
label: "Preview OpenSCAD",
|
||||
keybindings: [monaco.KeyCode.F5],
|
||||
run: () => model.render({isPreview: false})
|
||||
});
|
||||
setEditor(editor)
|
||||
}
|
||||
|
|
@ -100,7 +106,7 @@ export function App({initialState}: {initialState: State}) {
|
|||
}
|
||||
</div>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<button onClick={() => model.render()}>Render</button>
|
||||
<button onClick={() => model.render({isPreview: false})}>Render</button>
|
||||
{model.state.previewing && 'previewing... '}
|
||||
{model.state.rendering && 'rendering... '}
|
||||
{model.state.checkingSyntax && 'checking syntax... '}
|
||||
|
|
|
|||
1
src/BrowserFS.d.ts
vendored
1
src/BrowserFS.d.ts
vendored
|
|
@ -5,6 +5,7 @@
|
|||
declare interface FS {
|
||||
readdir(path: string, cb: (err: any, files: string[]) => void): void;
|
||||
symlink(target: string, source: string): void;
|
||||
readFileSync(path: string): BufferSource;
|
||||
}
|
||||
|
||||
declare interface EmscriptenFS extends FS {}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||
|
||||
import { createContext } from "react"
|
||||
import React from 'react';
|
||||
import { Model } from "./model"
|
||||
|
||||
export interface State {
|
||||
|
|
@ -19,12 +19,13 @@ export interface State {
|
|||
checkingSyntax?: boolean,
|
||||
|
||||
output?: {
|
||||
isPreview: boolean,
|
||||
stlFile: File,
|
||||
stlFileURL: string,
|
||||
},
|
||||
};
|
||||
|
||||
export const ModelContext = createContext(new Model(
|
||||
export const ModelContext = React.createContext(new Model(
|
||||
{
|
||||
params: {
|
||||
source: '',
|
||||
|
|
|
|||
17
src/default-scad.ts
Normal file
17
src/default-scad.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
export default `
|
||||
rotate([90, 0, 0]) {
|
||||
translate([-50, 0, 50])
|
||||
linear_extrude(10)
|
||||
text("hello world!");
|
||||
|
||||
}
|
||||
cube(40, center=true);
|
||||
translate([10, 10, 10])
|
||||
cube(40, center=true);
|
||||
|
||||
// This demo includes many libraries:
|
||||
//
|
||||
// include <BOSL2/std.scad>
|
||||
// translate([-100, 0, 0])
|
||||
spheroid(d=100, style="icosa", $fn=20);
|
||||
`
|
||||
|
|
@ -10,6 +10,17 @@ import { zipArchives } from './zip-archives';
|
|||
import {readStateFromFragment} from './fragment-state'
|
||||
import { State } from './app-state';
|
||||
import './index.css';
|
||||
import defaultScad from './default-scad'
|
||||
|
||||
import debug from 'debug';
|
||||
const log = debug('app:log');
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
debug.enable('*');
|
||||
log('Logging is enabled!');
|
||||
} else {
|
||||
debug.disable();
|
||||
}
|
||||
|
||||
(async () => {
|
||||
|
||||
|
|
@ -17,11 +28,12 @@ import './index.css';
|
|||
const fs = await createEditorFS(workingDir);
|
||||
await registerOpenSCADLanguage(fs, workingDir, zipArchives);
|
||||
|
||||
const initialState = readStateFromFragment() ?? {
|
||||
const initialState: State = readStateFromFragment() ?? {
|
||||
params: {
|
||||
source: 'cube(1);\ntranslate([0.5, 0.5, 0.5])\n\tcube(1);',
|
||||
source: defaultScad,
|
||||
features: [],
|
||||
}
|
||||
} as State;
|
||||
};
|
||||
|
||||
const defaultFeatures = ['manifold', 'fast-csg', 'lazy-union'];
|
||||
defaultFeatures.forEach(f => {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const builtinCompletions = [
|
|||
insertText: `${v}`,
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
||||
})),
|
||||
...openscadLanguage.language.keywords.map(v => ({
|
||||
...openscadLanguage.language.keywords.map((v: string) => ({
|
||||
label: v,
|
||||
kind: monaco.languages.CompletionItemKind.Function,
|
||||
insertText: v,
|
||||
|
|
@ -92,7 +92,7 @@ export async function buildOpenSCADCompletionItemProvider(fs: FS, workingDir: st
|
|||
path = toAbsolutePath(path);
|
||||
try {
|
||||
const bytes = await fs.readFileSync(path);
|
||||
const src = new TextDecoder("utf-8").decode(bytes);
|
||||
const src = new TextDecoder("utf-8").decode(bytes as any);
|
||||
return src;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export function spawnOpenSCAD({inputs, args, outputPaths}: OpenSCADInvocation):
|
|||
}
|
||||
|
||||
return AbortablePromise<OpenSCADInvocationResults>((resolve, reject) => {
|
||||
worker = new Worker('./openscad-worker-inlined.js');//, {type: "module"})
|
||||
worker = new Worker('./openscad-worker.js');//, {type: "module"})
|
||||
// if (navigator.userAgent.indexOf(' Chrome/') < 0) {
|
||||
// worker = new Worker('./openscad-worker-firefox.js'); // {'type': 'module'}
|
||||
// } else {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"WebWorker",
|
||||
],
|
||||
"rootDir": "src",
|
||||
"outDir": "js",
|
||||
// "outDir": "js",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
@ -20,11 +20,12 @@
|
|||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": false,
|
||||
// "noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts",
|
||||
"src/*.tsx",
|
||||
// "public"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
49
webpack.config.js
Normal file
49
webpack.config.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.tsx',
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [
|
||||
{loader: 'css-loader', options:{url: false}}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
},
|
||||
output: {
|
||||
filename: 'index.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
},
|
||||
devServer: {
|
||||
static: path.join(__dirname, "dist"),
|
||||
compress: true,
|
||||
port: 4000,
|
||||
},
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.resolve(__dirname, 'public'),
|
||||
toType: 'dir',
|
||||
},
|
||||
{
|
||||
from: path.resolve(__dirname, 'src/wasm/openscad.js'),
|
||||
from: path.resolve(__dirname, 'src/wasm/openscad.wasm'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
Loading…
Reference in a new issue