Closed kaosat-dev closed 3 years ago
Actually, I think that the concept of include() came from OPENSCAD so possibly this compatibility can be maintained via the JSCAD library.
@z3dev true, but not sure if it can /should behave the same way : unlike Openscad we have a full programming language at our disposal :)
Just my 2p after submitting the metaball PR above...
This looks great (esp the common.js format for defining modules), but IMO simplicity (and it working easily on https://openjscad.org) is key.
The majority of your users won't be Node.js devs, so asking them to submit to NPM will probably cut down the amount of submissions you get a lot. The great bonus of openjscad.org is it works in the browser, so asking for a full Node.js install just to submit code seems like a step backwards.
While I mentioned require
, chances are it wouldn't be that standards compliant with NPM and might just annoy people. include(url)
might be preferable from that point of view.
Also, while I said about common.js above, having the ability to find someone's jscad object online and just include
it into your design would be amazing. Perhaps the loader could check for the existence of the main
function or exports
fields and decide how to interpret file file based on that (or maybe just the file extension?).
Sorry for the late reply, I introduced include()
as I wanted to keep things simple. In general OpenJsCad (the original) was OO-based and I wanted to add functions and UI to make it easier to use, openscad.js
provided OpenSCAD-like JS functions, where include()
was added in the same spirit.
Now that things we modular, it surely makes sense to adapt common ways, but keep include()
as well. OpenJSCAD.org I did to be a hybrid: simple OpenSCAD-like, aside of the more elaborate OO approach which JS experts will use.
Sorry, not sure how I missed that it's already there: https://en.wikibooks.org/wiki/OpenJSCAD_User_Guide#Including_Files
Looking at the docs, include via URL isn't possible yet... Would it be possible to add it? It'd be amazingly handy for referencing a file on GitHub, Gist or similar. Obviously cross-origin could be a pain, but I think GitHub at least is ok from that point of view?
@gfwilliams while I agree that simplicity is great and should be at the forefront , I don't thing it needs to be incompatible with a sane way to define & (re)use code:
Side notes:
@gfwilliams while adding loading from an URL is possible to add it relatively simply I really don't think it should be done : simplicity is good
hi @Spiritdude ! :) I am ok with keeping include as it is, but building upon its very fragile foundations seem like a bad idea for all the reasons above. side note , we only need functions, not OO haha (I have come to embrace functional like programming in JS, and man does it rock)
btw I am also willing to provide a proof of concept for 'require-lite' functionality for demo purposes :)
I'm still VERY new to OpenJSCAD so I don't know the historic reasons for include()
being the way it is and I'm not sure what the ultimate goals are for this project but I'm very interested in seeing a thriving open library of parametric CAD objects. Definitely opt for modules if possible. Having functions defined globally sounds totally insane to me as a front-end webapp developer with a functional programming bent. Coming in fresh, the OO-like function() main() { ... }
had me wondering what magic parser was picking it up and what else was going on behind the scenes. It starts to feel like OpenJSCAD is a language extending javascript.
The wiki says
An OpenJSCAD script must have at least one function defined...
In es6 for say cube.js: export default () => { ... }
gives you just that.
Then in some other module, import cube from './cube'
Essentially, I'll echo the "don't reinvent the wheel" arguments in this thread.
Check out https://aframe.io/aframe-registry/ for inspiration regarding a repo of community modules.
thanks a lot for the feedback @meta-meta ! I also think modules is a must have : since we are planning a set of breaking API changes in the near future, it might make sense to include that as well. The globals spamming IS horrible in every possible way :)
Wow a-frame
has grown a lot since I last saw it ! Nice set of community modules!
Btw I have seen a lot of users create module based code that gets 'flattened' down (ie something like browserify) for simple online use, so I think it is up to us to making the modules approachable even for non technical folks ? Ie a simple UI that could wrap up your current work as a reuseable package? (with optional github/npm publishing ?)
I think we could re-use the engines
field in package.json
(just like Atom does, except we would set it to 'jscad' ) to be able to easily query jscad packages created by users... hmm lots of good stuff !
As a follow up to this discussion, the newly relased pre alpha of jscad-desktop supports common.js code for jscad designs :)
https://github.com/jscad/jscad-desktop/blob/master/src/core/scripLoading.js#L75 loads either jscad code as common.js modules OR creates a virtual common.js module for jscad scripts which are not using it explicitly :)
I think there might be a way to do something very similar in the browser, stay tuned!
A bit of update on this front :
Any feature that allows either of the 2 options below is welcomed!
This would finally allow giving out URLs of objects you have made that uses lower level libraries, without requiring you to copy/paste the libraries into a single file, or forcing the use of node.js for the same task.
@udif while I can understand the appeal of those options, I am honestly not sure if they are feasible at all without major hassles: (as always, contributions are very welcome !)
If you see solutions for this that do not require a specific backend, please post , we are really open to discussing these things and finding solutions
about node.js : when I say node modules, I really mean the common.js syntax of require & imports : you could have a set of files containing / folders containing your different pieces of code without actually needing node.js itself : the main goal of the changes above is to move to a more sane management of reuseable code : it is no wonder pill that solves all issues, but at least we will stop doing hacky globals-insertions etc
I do this kind of thing in the Espruino IDE - you can just do var baz = require("http://foo.bar/baz.js")
if you want to (I know that's not very spec compliant, but it's really helpful).
CORS can bite you, but 99% of the time people are linking to GitHub, and in that case we detect the URL and just use GitHub's API to access the file directly.
Before I start, let me just state that I have zero experience as a web frontend/backend designer. I merely use Openjscad and pure Javascript to create 3D objects.
@kaosat-dev regarding your points:
I just saw @gfwilliams answer before I posted mine - limiting loading from github would be more than enough for me.
I think I just answered myself: It seems that www.openjscad.org is not merely a static web page but an actual server that can load these pages? My forked github.io copy of openjscad fails to load URIs :-(
Correct. There’s a small sever piece that happens behind the scene.
With the require() approach, this piece (and CORS) is not required.
@gfwilliams that is very interesting ! I took a look at the relevant Espruino docs , it is a nice solution ! :) Having specific adaptors (with API fallback) to 'popular websites' is very nice ! One thing I would very likely do differently for jscad though: not overriding require() , so it does not hide sync/async differences (that is a horrible part of the older jscad code for example).
Since dynamic import()
is not really present yet in browsers I would likely just add mockImport()
that returns a promise, making it distinct from sync require() calls. (yes, it adds another function to remember, but conflating things that work in a very different manner is already an issue with jscad, and if we ovveride require() with remote url support the scripts would not work in 'vanilla' node.js
@udif it is a bit more complicated then that , sadly
In Espruino, for require
we scan over the code first, pick out instances of require
with a string and then load the modules in beforehand. It works in our case but it'd be far from ideal for you.
mockImport
sounds like a great idea - at that point it's then basically just a function that you add into the library of functions that OpenJSCAD provides? Seems quite tidy - and I think it's fair to keep it in the browser and ignore the CORS issues? Pretty much everyone will be using it on some well known service like GitHub or on their own server where it's trivial to tweak the CORS headers.
Seems to me that include() and mockImport() are the same, unless you can point out something significantly different. Trying to provide something that looks like import() proposal... and let’s see...
Umm... nothing there is easy.
@gfwilliams thanks for the insights! pre-emptive loading works but can get a headache :) and adds complexity
And you are spot on with mockImport
! Small utility function, limited scope, syntax should follow https://github.com/tc39/proposal-dynamic-import as much as possible I think (still EAGERLY awaiting the day where we do not have to reinvent the wheel...).
Not sure if we should limit to web , as it would mean different scripts for browser & node, which should be avoided, but it could be a simple api function with a different implementation in web & node (or just trust browserify & co)
@z3dev they would not the same at all, one is sync, the other async : require() returns the exports of the given module, mockImport() would return a PROMISE of a module
import()
itself will be added in the future to browsers & co https://github.com/tc39/proposal-dynamic-import
but yes, all this is horribly complex (too many edge cases): this is why for now , my main goal it jus to have support for modules , how/when/if to load them is another layer of complexity on top :)
(guess what? I managed to get node modules loading from the web drag & drop, and the crappy circular dependencies in CSG.js breaks stuff ... )
Cool! A little progress anyway.
CSG.js.... working on that little by little.
With the release of V2 JSCAD, this issue has been resolved as the Common.js (Node) method for require() has been adopted. This may be extended or changed in the future.
Thanks all for the feedback!
Curent system
Hi everyone ! right now we are using a custom and rather limited
include
system to enable modular design & part reuse, with a few major flaws:pros
cons
include()
are pushed to the global scopeProposal
The node.js & js ecosystem have been very successfully using modules for years, let's use that tech and knowledge to our advantage :
function coolPart(){ return cube({size:someValue}).union(text(someText) } module.exports = { //these are exported and available from any consumer someValue, coolPart }
cons
Of course this could be rolled out progressively, tested & tried, and would not need to impact the current implementation of include.
As you can likely see, I am quite passionate about the subject . Any thoughts ?