@jscad/core 2.5.2 → 2.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/jscad-core.min.js +931 -934
- package/package.json +6 -6
- package/src/code-evaluation/rebuildGeometry.js +0 -3
- package/src/code-evaluation/rebuildGeometryCli.js +2 -3
- package/src/code-evaluation/serializeSolids.js +1 -2
- package/src/code-loading/loadDesign.js +0 -26
- package/src/code-loading/makeFakeFs.js +0 -6
- package/src/code-loading/modulifySource.js +2 -1
- package/src/code-loading/normalizeDesignModule.js +5 -5
- package/src/code-loading/transformSources.js +4 -16
- package/src/code-loading/webRequire.js +5 -2
- package/src/code-loading/webRequire.test.js +4 -1
- package/src/parameters/getParameterDefinitionsFromSource.test.js +1 -1
- package/src/parameters/getParameterValuesFromUIControls.js +0 -9
- package/src/web/walkFileTree.js +1 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/core",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.5",
|
|
4
4
|
"description": "Core functionality for JSCAD Applications",
|
|
5
5
|
"repository": "https://github.com/jscad/OpenJSCAD.org",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
],
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@jscad/array-utils": "2.1.
|
|
38
|
-
"@jscad/io": "2.2.
|
|
39
|
-
"@jscad/io-utils": "2.0.
|
|
40
|
-
"@jscad/modeling": "2.
|
|
37
|
+
"@jscad/array-utils": "2.1.2",
|
|
38
|
+
"@jscad/io": "2.2.5",
|
|
39
|
+
"@jscad/io-utils": "2.0.14",
|
|
40
|
+
"@jscad/modeling": "2.8.0",
|
|
41
41
|
"json5": "2.2.0",
|
|
42
42
|
"strip-bom": "4.0.0"
|
|
43
43
|
},
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"url": "https://opencollective.com/openjscad",
|
|
53
53
|
"logo": "https://opencollective.com/openjscad/logo.txt"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "92fb9c75eb070fca5f5ee8c2bab6614b1f54514e"
|
|
56
56
|
}
|
|
@@ -24,7 +24,6 @@ const applyParameterDefinitions = require('../parameters/applyParameterDefinitio
|
|
|
24
24
|
* And transfering data back & forth is both complex (see transferables) and costly (time)
|
|
25
25
|
**/
|
|
26
26
|
const rebuildSolids = (data, callback) => {
|
|
27
|
-
console.log('rebuildSolids',data)
|
|
28
27
|
const defaults = {
|
|
29
28
|
mainPath: '',
|
|
30
29
|
apiMainPath: '@jscad/modeling',
|
|
@@ -47,7 +46,6 @@ const rebuildSolids = (data, callback) => {
|
|
|
47
46
|
parameterDefaults: designData.parameterValues,
|
|
48
47
|
parameterDefinitions: designData.parameterDefinitions
|
|
49
48
|
})
|
|
50
|
-
// console.warn(`loadDesignData`, new Date() - start)
|
|
51
49
|
// make sure parameters are correct by applying parameter definitions
|
|
52
50
|
// this might be redundant with ui-side logic, but it makes sure this core piece works regardless of ui
|
|
53
51
|
parameterValues = applyParameterDefinitions(parameterValues, designData.parameterDefinitions)
|
|
@@ -59,7 +57,6 @@ const rebuildSolids = (data, callback) => {
|
|
|
59
57
|
serialize
|
|
60
58
|
}
|
|
61
59
|
const solidsData = instanciateDesign(designData.rootModule, parameterValues, options)
|
|
62
|
-
// console.warn(`instanciateDesign`, new Date() - start)
|
|
63
60
|
|
|
64
61
|
// send back solids & any other metadata
|
|
65
62
|
callback(null, {
|
|
@@ -7,10 +7,9 @@ const makeWebRequire = require('../code-loading/webRequire')
|
|
|
7
7
|
|
|
8
8
|
const rebuildSolids = (data) => {
|
|
9
9
|
const defaults = {
|
|
10
|
-
apiMainPath: '@jscad/modeling'
|
|
11
|
-
serialize: false
|
|
10
|
+
apiMainPath: '@jscad/modeling'
|
|
12
11
|
}
|
|
13
|
-
let { apiMainPath,
|
|
12
|
+
let { apiMainPath, mainPath, parameterValues, useFakeFs } = Object.assign({}, defaults, data)
|
|
14
13
|
// we need to update the source for our module
|
|
15
14
|
let requireFn = require
|
|
16
15
|
|
|
@@ -11,7 +11,7 @@ const serializeSolids = (solids) => {
|
|
|
11
11
|
// imcomplete support for transfering objects via web workers
|
|
12
12
|
|
|
13
13
|
// NOTE: JSON.stringify was used at some point, but was removed because it was no longer needed
|
|
14
|
-
// for postMessage JavaScript engines now use an optimized structured clone alg.
|
|
14
|
+
// for postMessage JavaScript engines now use an optimized structured clone alg.
|
|
15
15
|
// which should be at least as fast as JSON.stringify
|
|
16
16
|
solids = solids.map((object) => {
|
|
17
17
|
// apply the transforms before serializing
|
|
@@ -23,5 +23,4 @@ const serializeSolids = (solids) => {
|
|
|
23
23
|
return solids
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
27
26
|
module.exports = serializeSolids
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// loading
|
|
2
1
|
const { registerAllExtensions } = require('../io/registerExtensions')
|
|
3
2
|
|
|
4
3
|
const transformSources = require('./transformSources')
|
|
@@ -16,27 +15,6 @@ const getAllParameterDefintionsAndValues = require('../parameters/getParameterDe
|
|
|
16
15
|
* @param {Object} parameterValuesOverride - the values to use to override the defaults for the current design
|
|
17
16
|
*/
|
|
18
17
|
const loadDesign = (mainPath, apiMainPath, filesAndFolders, parameterValuesOverride) => {
|
|
19
|
-
// console.log('***** loadDesign',mainPath)
|
|
20
|
-
// the root script is the main entry point in a design
|
|
21
|
-
// ie either the only file if there is only one
|
|
22
|
-
// OR the file in the 'main' entry of package.js, index.js, main.js or <folderName>.js
|
|
23
|
-
|
|
24
|
-
/*
|
|
25
|
-
- if the script is a common.js file already
|
|
26
|
-
> load as it is
|
|
27
|
-
- if we have real require() access (CLI, desktop)
|
|
28
|
-
use standard require() to load the rootScript
|
|
29
|
-
- if we do NOT have real require() access (web)
|
|
30
|
-
use fake require() to load the rootScript
|
|
31
|
-
- if the script is NOT a common.js file (implicit imports)
|
|
32
|
-
> add explicit api imports to the rootScript's source
|
|
33
|
-
> add explicit exports ie module.exports {main, getParameterDefinitions}
|
|
34
|
-
- if we have real require() access (CLI, desktop)
|
|
35
|
-
use standard require() to load the rootScript
|
|
36
|
-
- if we do NOT have real require() access (web)
|
|
37
|
-
use fake require() to load the rootScript
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
18
|
// transform the source if passed non-javascript content, i.e. stl
|
|
41
19
|
filesAndFolders = transformSources({ apiMainPath }, filesAndFolders)
|
|
42
20
|
|
|
@@ -52,8 +30,6 @@ const loadDesign = (mainPath, apiMainPath, filesAndFolders, parameterValuesOverr
|
|
|
52
30
|
}
|
|
53
31
|
]
|
|
54
32
|
}
|
|
55
|
-
// console.log('filesAndFolders',filesAndFolders)
|
|
56
|
-
|
|
57
33
|
const fakeFs = makeFakeFs(filesAndFolders)
|
|
58
34
|
|
|
59
35
|
const webRequire = makeWebRequire(filesAndFolders, { apiMainPath })
|
|
@@ -64,8 +40,6 @@ const loadDesign = (mainPath, apiMainPath, filesAndFolders, parameterValuesOverr
|
|
|
64
40
|
// find the root module
|
|
65
41
|
let rootModule = webRequire(filesAndFolders[0].fullPath)
|
|
66
42
|
|
|
67
|
-
// console.log('***** rootModule',rootModule)
|
|
68
|
-
|
|
69
43
|
rootModule = normalizeDesignModule(rootModule)
|
|
70
44
|
|
|
71
45
|
// rootModule SHOULD contain a main() entry and optionally a getParameterDefinitions entry
|
|
@@ -13,7 +13,6 @@ const makeFakeFs = (filesAndFolders) => {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
return undefined
|
|
16
|
-
// return filesAndFolders
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
const statSync = (path) => {
|
|
@@ -27,16 +26,13 @@ const makeFakeFs = (filesAndFolders) => {
|
|
|
27
26
|
statSync,
|
|
28
27
|
existsSync: (path) => {
|
|
29
28
|
const entry = findMatch(path)
|
|
30
|
-
// console.log('does ', path, 'exist ?', entry !== undefined)
|
|
31
29
|
return entry !== undefined
|
|
32
30
|
},
|
|
33
31
|
readdirSync: (path) => {
|
|
34
32
|
const entry = findMatch(path)
|
|
35
33
|
return entry.children.map((x) => x.name)
|
|
36
|
-
// filesAndFolders
|
|
37
34
|
},
|
|
38
35
|
readDir: (path, callback) => {
|
|
39
|
-
// console.log('readDir', path, callback)
|
|
40
36
|
const entry = findMatch(path)
|
|
41
37
|
callback(null, entry)
|
|
42
38
|
},
|
|
@@ -48,7 +44,6 @@ const makeFakeFs = (filesAndFolders) => {
|
|
|
48
44
|
if (!statSync(path).isFile()) {
|
|
49
45
|
callback(new Error(`${entry} is not a file, cannot read`))
|
|
50
46
|
} else {
|
|
51
|
-
// console.log('readFile', path, entry)
|
|
52
47
|
callback(null, entry.source)
|
|
53
48
|
}
|
|
54
49
|
},
|
|
@@ -60,7 +55,6 @@ const makeFakeFs = (filesAndFolders) => {
|
|
|
60
55
|
if (!statSync(path).isFile()) {
|
|
61
56
|
throw new Error(`${entry} is not a file, cannot read`)
|
|
62
57
|
} else {
|
|
63
|
-
// console.log('readFile sync', path, entry)
|
|
64
58
|
return entry.source
|
|
65
59
|
}
|
|
66
60
|
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const modulifySource = (source, apiMainPath) => {
|
|
6
6
|
const getParamsString = source.includes('getParameterDefinitions')
|
|
7
|
-
? 'module.exports.getParameterDefinitions = getParameterDefinitions'
|
|
7
|
+
? 'module.exports.getParameterDefinitions = getParameterDefinitions'
|
|
8
|
+
: ''
|
|
8
9
|
const updatedSource = `
|
|
9
10
|
const {geom2, geom3, path2, pol2, poly3} = require('${apiMainPath}').geometries
|
|
10
11
|
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const normalizeDesignModule = (rootModule) => {
|
|
5
5
|
if (!rootModule) {
|
|
6
|
-
throw new Error('no root module found')
|
|
6
|
+
throw new Error('no root module found, please check the project structure')
|
|
7
7
|
}
|
|
8
8
|
if (typeof (rootModule) === 'function') {
|
|
9
|
-
console.warn('please
|
|
9
|
+
console.warn('please refactor the exports, assigning main() as a property, i.e. module.exports = { main }')
|
|
10
10
|
rootModule = { main: rootModule }
|
|
11
11
|
}
|
|
12
12
|
if (!rootModule.main) {
|
|
13
|
-
throw new Error('no main() function, check the exports')
|
|
13
|
+
throw new Error('no main() function found, please check the module.exports')
|
|
14
14
|
}
|
|
15
|
-
if (
|
|
16
|
-
throw new Error('main is not a function, check the exports')
|
|
15
|
+
if (typeof (rootModule.main) !== 'function') {
|
|
16
|
+
throw new Error('main is not a function, please check the module.exports')
|
|
17
17
|
}
|
|
18
18
|
return rootModule
|
|
19
19
|
}
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
const { deserializers } = require('@jscad/io')
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
/* function to turn old style jscad code with implicit imports
|
|
9
|
-
into code with explicit exports/imports */
|
|
10
|
-
// FIXME wouldn't a javascript error be better then 'hacking' the users code?
|
|
11
|
-
const modulifyTransform = (options, entry) => {
|
|
12
|
-
const { apiMainPath } = options
|
|
13
|
-
const isFileCommonJs = isCommonJsModule(entry.source)
|
|
14
|
-
const source = !isFileCommonJs ? modulifySource(entry.source, apiMainPath) : entry.source
|
|
15
|
-
return Object.assign({}, entry, { source })
|
|
16
|
-
}
|
|
3
|
+
/*
|
|
4
|
+
* Transform the entry into a ready-to-use module.
|
|
5
|
+
*/
|
|
6
|
+
const modulifyTransform = (options, entry) => Object.assign({}, entry, { source: entry.source })
|
|
17
7
|
|
|
18
8
|
/*
|
|
19
9
|
* Create a new entry for a script (JSCAD) from the given entry and source
|
|
@@ -32,8 +22,6 @@ const createJscadEntry = (entry, source) => {
|
|
|
32
22
|
* Transforms are NOT applied to projects.
|
|
33
23
|
*/
|
|
34
24
|
const transformSources = (options, filesAndFolders) => {
|
|
35
|
-
// console.log('***** transformSources', options, filesAndFolders)
|
|
36
|
-
|
|
37
25
|
if (filesAndFolders && filesAndFolders.length > 1) return filesAndFolders // skip projects
|
|
38
26
|
|
|
39
27
|
const codeTransforms = {
|
|
@@ -72,6 +72,7 @@ const makeWebRequire = (filesAndFolders, options) => {
|
|
|
72
72
|
// console.log('*****\n',filesAndFolders,'\n*****')
|
|
73
73
|
|
|
74
74
|
const extensions = {}
|
|
75
|
+
const moduleCache = {}
|
|
75
76
|
|
|
76
77
|
/* Require (obtain) the exports for the given require path, relative to the given current path.
|
|
77
78
|
* The logic is based on the original NODE require() function.
|
|
@@ -105,11 +106,12 @@ const makeWebRequire = (filesAndFolders, options) => {
|
|
|
105
106
|
if (entry.children) return null // directory
|
|
106
107
|
|
|
107
108
|
if (extensions[baseExt]) {
|
|
109
|
+
if (moduleCache[requirePath]) return moduleCache[requirePath]
|
|
108
110
|
// evaluate the content
|
|
109
111
|
const matchingModule = {
|
|
110
112
|
exports: {},
|
|
111
113
|
_compile: (content, fileName) => {
|
|
112
|
-
const moduleMakerFunction = new Function('require', 'module', content)
|
|
114
|
+
const moduleMakerFunction = new Function('require', 'module', content) // eslint-disable-line no-new-func
|
|
113
115
|
moduleMakerFunction(_require.bind(null, entry.fullPath), matchingModule)
|
|
114
116
|
|
|
115
117
|
const paramDefFromSource = content.includes('@jscad-params') ? getParameterDefinitionsFromSource(content, fileName) : []
|
|
@@ -121,7 +123,8 @@ const makeWebRequire = (filesAndFolders, options) => {
|
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
extensions[baseExt](matchingModule, entry.fullPath)
|
|
124
|
-
|
|
126
|
+
moduleCache[requirePath] = matchingModule.exports
|
|
127
|
+
return moduleCache[requirePath]
|
|
125
128
|
}
|
|
126
129
|
return null
|
|
127
130
|
}
|
|
@@ -13,10 +13,14 @@ test('webRequire: should support require, from a single file', (t) => {
|
|
|
13
13
|
|
|
14
14
|
let requireFn = makeWebRequire(singleFileJs, { apiMainPath })
|
|
15
15
|
let designRootModule = requireFn(singleFileJs[0].fullPath)
|
|
16
|
+
const designRootModule2 = requireFn(singleFileJs[0].fullPath)
|
|
16
17
|
|
|
17
18
|
t.true('main' in designRootModule)
|
|
18
19
|
t.true(designRootModule.main instanceof Function)
|
|
19
20
|
|
|
21
|
+
t.is(designRootModule, designRootModule2)
|
|
22
|
+
t.deepEqual(designRootModule, designRootModule2)
|
|
23
|
+
|
|
20
24
|
// NOTE: 'jscad' must be registered as an extension
|
|
21
25
|
const fakeFs = makeFakeFs(singleFileJscad)
|
|
22
26
|
requireFn = makeWebRequire(singleFileJscad, { apiMainPath })
|
|
@@ -32,7 +36,6 @@ test('webRequire: should support require, from a directory with index.js', (t) =
|
|
|
32
36
|
|
|
33
37
|
const requireFn = makeWebRequire(directoryWithIndexJs, { apiMainPath })
|
|
34
38
|
const designRootModule = requireFn('/project')
|
|
35
|
-
|
|
36
39
|
t.true('main' in designRootModule)
|
|
37
40
|
t.true(designRootModule.main instanceof Function)
|
|
38
41
|
})
|
|
@@ -224,5 +224,5 @@ test('multiline error', (t) => {
|
|
|
224
224
|
test('single line /* ...*/ ok', (t) => {
|
|
225
225
|
t.deepEqual(getParameterDefinitionsFromSource(`function main({//@jscad-params
|
|
226
226
|
/* group */
|
|
227
|
-
width=14})`), [{type:'group', caption:'group', name:'_group_1'}
|
|
227
|
+
width=14})`), [{ type: 'group', caption: 'group', name: '_group_1' }, ...sampleParams2])
|
|
228
228
|
})
|
|
@@ -13,14 +13,6 @@ const getParameterValuesFromUIControls = (paramControls, parameterDefinitions, o
|
|
|
13
13
|
switch (control.paramType) {
|
|
14
14
|
case 'choice':
|
|
15
15
|
value = control.options[control.selectedIndex].value
|
|
16
|
-
/* console.log('choice', control, control.paramName)
|
|
17
|
-
// we try to match values against captions, then parse as numbers if applicable, then fallback to original value
|
|
18
|
-
const valueIndex = !definition ? -1 : definition.captions.indexOf(value)
|
|
19
|
-
const valueInDefinition = valueIndex > -1
|
|
20
|
-
// const valueInDefintionCaptionsAndValue = valueInDefinition && definition.values.length >= valueIndex
|
|
21
|
-
value = definition.values.length > 0 && isNumber(definition.values[0]) ? parseFloat(value) : value
|
|
22
|
-
value = definition.values.length > 0 && typeof value === 'boolean' ? !!value : value
|
|
23
|
-
console.log('foo', value) */
|
|
24
16
|
break
|
|
25
17
|
case 'float':
|
|
26
18
|
case 'number':
|
|
@@ -63,7 +55,6 @@ const getParameterValuesFromUIControls = (paramControls, parameterDefinitions, o
|
|
|
63
55
|
}
|
|
64
56
|
}
|
|
65
57
|
parameterValues[control.paramName] = value
|
|
66
|
-
// console.log(control.paramName+":"+parameterValues[control.paramName])
|
|
67
58
|
}
|
|
68
59
|
return parameterValues
|
|
69
60
|
}
|
package/src/web/walkFileTree.js
CHANGED
|
@@ -30,8 +30,6 @@ const binaryMimetypes = {
|
|
|
30
30
|
* @returns {Promise} new promise to read and convert the file
|
|
31
31
|
*/
|
|
32
32
|
const readFileAsync = (file, fileMeta) => {
|
|
33
|
-
// console.log('readFileAsync',file,fileMeta)
|
|
34
|
-
|
|
35
33
|
const fullPath = file.fullPath ? file.fullPath : fileMeta.fullPath ? fileMeta.fullPath : ''
|
|
36
34
|
const ext = getFileExtensionFromString(file.name)
|
|
37
35
|
const mimetype = file.mimetype
|
|
@@ -43,7 +41,7 @@ const readFileAsync = (file, fileMeta) => {
|
|
|
43
41
|
const result = event.target.result
|
|
44
42
|
if (result.byteLength) {
|
|
45
43
|
resolve({ name: file.name, ext, fullPath, mimetype, source: result })
|
|
46
|
-
} else if (typeof
|
|
44
|
+
} else if (typeof result === 'string') {
|
|
47
45
|
resolve({ name: file.name, ext, fullPath, mimetype, source: result })
|
|
48
46
|
}
|
|
49
47
|
}
|
|
@@ -87,7 +85,6 @@ const isEmpty = (x) => x !== null && x !== undefined // skip empty items
|
|
|
87
85
|
* @returns {Promise} one promise to resolve them all
|
|
88
86
|
*/
|
|
89
87
|
const processEntries = (items) => {
|
|
90
|
-
// console.log('processEntries',items)
|
|
91
88
|
const results = pseudoArraytoArray(items.filter(isEmpty))
|
|
92
89
|
.filter(isEmpty) // skip empty items
|
|
93
90
|
.reduce((result, item) => {
|
|
@@ -117,7 +114,6 @@ const processEntries = (items) => {
|
|
|
117
114
|
* @returns {Promise} new promise to read and process the file
|
|
118
115
|
*/
|
|
119
116
|
const processFile = (fileItem) => {
|
|
120
|
-
// console.log('processFile',fileItem)
|
|
121
117
|
const promiseFile = new Promise((resolve, reject) => {
|
|
122
118
|
fileItem.file(
|
|
123
119
|
(fileData) => {
|
|
@@ -138,7 +134,6 @@ const processFile = (fileItem) => {
|
|
|
138
134
|
* @returns {Promise} new promise to read and process the directory
|
|
139
135
|
*/
|
|
140
136
|
const processDirectory = (directory) => {
|
|
141
|
-
// console.log('processDirectory',directory)
|
|
142
137
|
const promiseDirectory = new Promise((resolve, reject) => {
|
|
143
138
|
if (directory.entries) {
|
|
144
139
|
directory.entries.length ? processEntries(directory.entries).then(resolve) : resolve([])
|