From f532e4b467ad0d1c0a122aba0cb87581b862c5d2 Mon Sep 17 00:00:00 2001 From: Davor Hrg Date: Tue, 19 Dec 2023 14:02:38 +0100 Subject: [PATCH] feat-file-input (#72) file imput supprot for parameters, that reads file the same ways as require for different types of geometry. example script: ```js import * as jscad from '@jscad/modeling' export const main =({// @jscad-params mesh,// {type:"file"} check=false, })=>{ return mesh ? mesh : jscad.primitives.sphere() } ``` no file chosen, the sample script returns a sphere ![image](https://github.com/hrgdavor/jscadui/assets/2480762/54181e8c-64dc-47d7-bf0c-0b0ec0523389) stl file, the sample script returns the geometry form the stl ![image](https://github.com/hrgdavor/jscadui/assets/2480762/9a8a952e-0b1a-4ac1-8e6c-ae26f4ed0883) --- apps/jscad-web/src_bundle/bundle.worker.js | 28 ++++++++++------------ apps/jscad-web/static/test.file.js | 9 +++++++ packages/fs-provider/fs-provider.js | 9 +++++-- packages/require/src/require.js | 5 +++- packages/worker/worker.js | 15 ++++++++++++ 5 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 apps/jscad-web/static/test.file.js diff --git a/apps/jscad-web/src_bundle/bundle.worker.js b/apps/jscad-web/src_bundle/bundle.worker.js index 2913a2f..81a7201 100644 --- a/apps/jscad-web/src_bundle/bundle.worker.js +++ b/apps/jscad-web/src_bundle/bundle.worker.js @@ -29,21 +29,19 @@ const exportData = ({format, options={}})=>{ return withTransferable({ data }, data.filter(v=>typeof v !== 'string')) } -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 +const importData = { + isBinaryExt: ext=>ext === 'stl' ? 'bin':'text', + deserialize: ({url, filename, ext}, fileContent)=>{ + try { + const jscad_io = require('./bundle.jscad_io.js', null, readFileWeb) + let deserializer = jscad_io.deserializers[ext] + + if(deserializer) return deserializer({output:'geometry', filename}, fileContent) + throw new Error('unsupportd format in '+url) + } catch (error) { + console.error(error) + throw error + } } } diff --git a/apps/jscad-web/static/test.file.js b/apps/jscad-web/static/test.file.js new file mode 100644 index 0000000..e69abb3 --- /dev/null +++ b/apps/jscad-web/static/test.file.js @@ -0,0 +1,9 @@ +import * as jscad from '@jscad/modeling' + +export const main =({// @jscad-params + mesh,// {type:"file"} + check=false, +})=>{ + return mesh ? mesh : jscad.primitives.sphere() + +} diff --git a/packages/fs-provider/fs-provider.js b/packages/fs-provider/fs-provider.js index f2339de..45c2736 100644 --- a/packages/fs-provider/fs-provider.js +++ b/packages/fs-provider/fs-provider.js @@ -20,7 +20,13 @@ export * from './src/FileEntry.js' * @returns {Array} */ export const splitPath = path => (typeof path === 'string' ? path.split('/').filter(p => p && p !== '.') : path) - +export function extractPathInfo(url){ + let idx = url.lastIndexOf('/') + let filename = url.substring(idx+1) + idx = filename.lastIndexOf('.') + let ext = filename.substring(idx+1) + return {url, filename, ext} +} export const getFile = async (path, sw) => { let arr = splitPath(path) let match = await findFileInRoots(sw.roots, arr) @@ -233,7 +239,6 @@ export async function fileDropped(sw, files) { let time = Date.now() const preLoad = ['/' + sw.fileToRun, '/package.json'] const loaded = await addPreLoadAll(sw, preLoad, true) - console.log(Date.now() - time, 'preload', loaded) sw.projectName = sw.defProjectName if (sw.fileToRun !== 'index.js') sw.projectName = sw.fileToRun.replace(/\.js$/, '') diff --git a/packages/require/src/require.js b/packages/require/src/require.js index 8a41eca..89aa168 100644 --- a/packages/require/src/require.js +++ b/packages/require/src/require.js @@ -10,6 +10,7 @@ - typescript import must use .js (it is a bit strange, but probably has good reasons) */ +import { extractPathInfo } from '../../fs-provider/fs-provider' import { MODULE_BASE, getExtension, resolveUrl } from './resolveUrl' export { resolveUrl } from './resolveUrl' @@ -49,7 +50,9 @@ export const require = (urlOrSource, transform, readFile, base, root, importData const resolvedStr = resolved.url.toString() const isJs = resolvedStr.endsWith('.ts') || resolvedStr.endsWith('.js') if(!isJs && importData){ - return importData(resolvedStr, readFile, base, root, moduleBase) + const info = extractPathInfo(resolvedStr) + let content = readFile(resolvedStr,{output: importData.isBinaryExt(info.ext)}) + return importData.deserialize(info, content) } isRelativeFile = resolved.isRelativeFile diff --git a/packages/worker/worker.js b/packages/worker/worker.js index 7ab9650..98338ca 100644 --- a/packages/worker/worker.js +++ b/packages/worker/worker.js @@ -5,6 +5,7 @@ import { clearFileCache, clearTempCache, readFileWeb, require, requireCache, res import { exportStlText } from './src/exportStlText.js' import { combineParameterDefinitions, getParameterDefinitionsFromSource } from './src/getParameterDefinitionsFromSource.js' import { extractDefaults } from './src/extractDefaults.js' +import { extractPathInfo, readAsArrayBuffer, readAsText } from '../fs-provider/fs-provider.js' let main self.JSCAD_WORKER_ENV = {} @@ -41,8 +42,22 @@ export const init = params => { userInstances = params.userInstances } +async function readFileFile(file, {bin=false}={}){ + if(bin) return await readAsArrayBuffer(file) + else return readAsText(file) +} + solids = [] export async function runMain({ params } = {}) { + params = {...params} + for(let p in params){ + if(params[p] instanceof File && importData){ + const info = extractPathInfo(params[p].name) + let content = await readFileFile(params[p],{bin: importData.isBinaryExt(info.ext)}) + params[p] = importData.deserialize(info, content) + } + } + console.log('runMain', params) let entities = [] const transferable = []