From c70e968dcfb1c64eb17aa05ca079703d5a9e644d Mon Sep 17 00:00:00 2001 From: Davor Hrg Date: Thu, 7 Dec 2023 08:50:13 +0100 Subject: [PATCH] require-geometry-files (#71) I hacked up a quick support to require stl and other jscad supported geometry. it may not work for all that work on jscad web, but it definitely works for openjscad examples https://github.com/jscad/OpenJSCAD.org/tree/master/packages/examples/import AMFImport ![image](https://github.com/hrgdavor/jscadui/assets/2480762/db129913-c667-4aca-9285-3944b88b4417) STLImport ![image](https://github.com/hrgdavor/jscadui/assets/2480762/14bad511-27dc-47b0-8aad-fe9787b52fb4) SVGImport ![image](https://github.com/hrgdavor/jscadui/assets/2480762/96b6722b-d18e-487e-a1d4-c5b45edddd8f) --- apps/jscad-web/src_bundle/bundle.worker.js | 20 +++++++++++++++++++- packages/require/src/readFileWeb.js | 10 +++++++++- packages/require/src/require.js | 10 ++++++++-- packages/worker/worker.js | 9 +++++---- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/apps/jscad-web/src_bundle/bundle.worker.js b/apps/jscad-web/src_bundle/bundle.worker.js index a893e11..2913a2f 100644 --- a/apps/jscad-web/src_bundle/bundle.worker.js +++ b/apps/jscad-web/src_bundle/bundle.worker.js @@ -29,4 +29,22 @@ const exportData = ({format, options={}})=>{ return withTransferable({ data }, data.filter(v=>typeof v !== 'string')) } -initWorker(transformcjs, exportData) +const importData = (url, readFile, base, root, moduleBase)=>{ + try { + const jscad_io = require('./bundle.jscad_io.js', null, readFileWeb) + let idx = url.lastIndexOf('/') + let filename = url.substring(idx+1) + idx = filename.lastIndexOf('.') + let ext = filename.substring(idx+1) + let deserializer = jscad_io.deserializers[ext] + let file = readFile(url,{output:ext === 'stl' ? 'bin':'text'}) + + if(deserializer) return deserializer({output:'geometry', filename}, file) + throw new Error('unsupportd format in '+url) + } catch (error) { + console.error(error) + throw error + } +} + +initWorker(transformcjs, exportData, importData) diff --git a/packages/require/src/readFileWeb.js b/packages/require/src/readFileWeb.js index a0d6ed4..d8045f3 100644 --- a/packages/require/src/readFileWeb.js +++ b/packages/require/src/readFileWeb.js @@ -4,11 +4,19 @@ export const readFileWeb = (path, {base = '', output='text'}={}) => { const req = new XMLHttpRequest() req.open('GET', base ? new URL(path, base) : path, 0) // sync + + if(output !== 'text'){ + // this hack was hard to find, and we can not use fetch because we need sync request + // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com] + req.overrideMimeType("text/plain; charset=x-user-defined"); + } + req.send() if (req.status && req.status === 404) { throw new Error(`file not found ${path}`) } else if (req.status && req.status !== 200) { throw new Error(`failed to fetch file ${path} ${req.status} ${req.statusText}`) } - return req.responseText + + return output == 'text' ? req.responseText : req.response } diff --git a/packages/require/src/require.js b/packages/require/src/require.js index c577cd9..8a41eca 100644 --- a/packages/require/src/require.js +++ b/packages/require/src/require.js @@ -24,7 +24,7 @@ export const runModule = (typeof self === 'undefined' ? eval : self.eval)( '(require, exports, module, source)=>eval(source)', ) -export const require = (urlOrSource, transform, readFile, base, root, moduleBase = MODULE_BASE) => { +export const require = (urlOrSource, transform, readFile, base, root, importData = null, moduleBase = MODULE_BASE) => { let source let url let isRelativeFile @@ -46,6 +46,12 @@ export const require = (urlOrSource, transform, readFile, base, root, moduleBase const aliasedUrl = bundleAlias || requireCache.alias[url] || url const resolved = resolveUrl(aliasedUrl, base, root, moduleBase) + const resolvedStr = resolved.url.toString() + const isJs = resolvedStr.endsWith('.ts') || resolvedStr.endsWith('.js') + if(!isJs && importData){ + return importData(resolvedStr, readFile, base, root, moduleBase) + } + isRelativeFile = resolved.isRelativeFile resolvedUrl = resolved.url cacheUrl = resolved.url @@ -90,7 +96,7 @@ export const require = (urlOrSource, transform, readFile, base, root, moduleBase // do not transform bundles that are already cjs ( requireCache.bundleAlias.*) if (transform && !bundleAlias) source = transform(source, resolvedUrl).code // construct require function relative to resolvedUrl - let requireFunc = newUrl => require(newUrl, transform, readFile, resolvedUrl, root, moduleBase) + let requireFunc = newUrl => require(newUrl, transform, readFile, resolvedUrl, root, importData, moduleBase) const module = requireModule(url, resolvedUrl, source, requireFunc) module.local = isRelativeFile exports = module.exports diff --git a/packages/worker/worker.js b/packages/worker/worker.js index ce035f0..7ab9650 100644 --- a/packages/worker/worker.js +++ b/packages/worker/worker.js @@ -12,6 +12,7 @@ let transformFunc = x => x let client let globalBase = location.origin let userInstances +let importData export const flatten = arr=>{ const doFlatten = (_in, out)=>{ @@ -72,11 +73,10 @@ const exportReg = /export.*from/ const runScript = async ({ script, url, base=globalBase, root=base }) => { if(!script) script = readFileWeb(resolveUrl(url, base, root).url) - console.log('{ script, url, base, root }', { script, url, base, root }) const shouldTransform = url.endsWith('.ts') || script.includes('import') && (importReg.test(script) || exportReg.test(script)) let def = [] - - const scriptModule = require({url,script}, shouldTransform ? transformFunc : undefined, readFileWeb, base, root) + + const scriptModule = require({url,script}, shouldTransform ? transformFunc : undefined, readFileWeb, base, root, importData) const fromSource = getParameterDefinitionsFromSource(script) def = combineParameterDefinitions(fromSource, await scriptModule.getParameterDefinitions?.()) main = scriptModule.main @@ -108,9 +108,10 @@ export const currentSolids = ()=>solids const handlers = { runScript, init, runMain, clearTempCache, clearFileCache, exportData } -export const initWorker = (transform, exportData) => { +export const initWorker = (transform, exportData, _importData) => { if (transform) transformFunc = transform if(exportData) handlers.exportData = exportData + importData = _importData client = initMessaging(self, handlers) }