├── .gitignore ├── README.md ├── app.code-workspace ├── index.js ├── intrinsic-scale.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gcode-file 2 | 3 | Create and save a gcode file in browser via javascript 4 | 5 | ### Installation 6 | 7 | You can grab it as an `npm` package 8 | ```bash 9 | npm i --save @gcode-file 10 | ``` 11 | 12 | ### Example 13 | 14 | ``` 15 | const { createPath, pathsToPolylines } = require('canvas-sketch-util/penplot'); 16 | const GCodeFile = require('gcode-file'); 17 | const gCode = new GCodeFile({ 18 | feedRate: 8000, // G1 movement (drawing speed) 19 | seekRate: 8000, // G0 movement (no drawing speed) 20 | onCommand: 'M03S20', 21 | offCommand: 'M03S0', 22 | powerDelay: 0.2, 23 | fileName: 'sketch', 24 | paperSize: [210, 297], // A4 size in mm 25 | margin: 10, // or [10, 10] (top/bottom and left/right margin) or [10,10,10,10] (top/left/bottom/right) 26 | flipX: false, 27 | flipY: false 28 | }) 29 | 30 | // ... your canvas setup ... 31 | gCode.updateCoordsArea(canvas.width, canvas.height); 32 | 33 | const p = createPath(); 34 | p.moveTo(10, 10); 35 | p.lineTo(100, 100); 36 | 37 | // Converting path to polylines...') 38 | const lines = pathsToPolylines([p]); 39 | 40 | console.log('Add data to gcode file...') 41 | gCode.addPolylines(lines) 42 | 43 | window.addEventListener('keydown', function(){ 44 | if((event.ctrlKey || event.metaKey) && event.which == 83) { 45 | event.preventDefault(); 46 | 47 | console.log('Download file...') 48 | gCode.downloadFile() 49 | return false; 50 | } 51 | }) 52 | ``` 53 | 54 | ## Methods 55 | 56 | ### updateConfig(newConfig) 57 | Accepts an object with the new config (or a part of it). It is useful if you modify your sketch size or print settings at runtime with a gui for example. 58 | 59 | ### updateCoordsArea(width, height) 60 | Update the dimension of your drawing area. It is necessary to know how map the coordinates of your paths to the paper dimension. 61 | 62 | ### moveTo(x, y) 63 | Wrap all the command to move the plot without draw 64 | 65 | ### drawLine(x, y) 66 | Wrap all the command to move the plot drawing 67 | 68 | ### addPolylines(polylines) 69 | Accepts an array on polylines and generate all the commands to draw the polylines. 70 | 71 | ### addLayer(name) 72 | Add layer that will be saved on separate file. 73 | 74 | ### downloadFile() 75 | Generate and download the gcode file 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /app.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./" 5 | } 6 | ], 7 | "settings": { 8 | "cSpell.enabled": true, 9 | "cSpell.language": "en", 10 | "vscode-php-cs-fixer.allowRisky": true, 11 | "vscode-php-cs-fixer.fixOnSave": true, 12 | "eslint.autoFixOnSave": true, 13 | "eslint.alwaysShowStatus": true, 14 | "javascript.format.enable": false, 15 | "javascript.implicitProjectConfig.experimentalDecorators": true, 16 | "javascript.preferences.importModuleSpecifier": "non-relative", 17 | "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 18 | "csscomb.formatOnSave": true, 19 | "csscomb.preset": { 20 | "preset": "yandex", 21 | "always-semicolon": true, 22 | "color-case": "lower", 23 | "block-indent": " ", 24 | "color-shorthand": false, 25 | "element-case": "lower", 26 | "eof-newline": true, 27 | "leading-zero": true, 28 | "quotes": "double", 29 | "space-before-colon": "", 30 | "space-after-colon": " ", 31 | "space-before-combinator": " ", 32 | "space-after-combinator": " ", 33 | "space-between-declarations": "\n", 34 | "space-before-opening-brace": " ", 35 | "space-after-opening-brace": "\n", 36 | "space-after-selector-delimiter": "\n", 37 | "space-before-selector-delimiter": "", 38 | "space-before-closing-brace": "\n", 39 | "strip-spaces": true, 40 | "tab-size": true, 41 | "unitless-zero": true, 42 | "vendor-prefix-align": true, 43 | "sort-order-fallback": "yandex", 44 | "sort-order": [ 45 | [ 46 | "$variable", 47 | "$extend", 48 | "$include", 49 | ], 50 | [ 51 | "content" 52 | ], 53 | [ 54 | "position", 55 | "z-index", 56 | "top", 57 | "right", 58 | "bottom", 59 | "left" 60 | ], 61 | [ 62 | "display", 63 | "visibility", 64 | "opacity", 65 | "float", 66 | "clear", 67 | "overflow", 68 | "overflow-x", 69 | "overflow-y", 70 | "clip", 71 | "zoom", 72 | ], 73 | [ 74 | "flex-direction", 75 | "flex-order", 76 | "flex-pack", 77 | "flex-align", 78 | "justify-content", 79 | "align-items", 80 | "align-content", 81 | "flex", 82 | "flex-basis", 83 | "flex-shrink", 84 | "flex-grow", 85 | "flex-direction", 86 | "flex-flow", 87 | "flex-wrap" 88 | ], 89 | [ 90 | "box-sizing", 91 | "width", 92 | "height", 93 | "min-width", 94 | "min-height", 95 | "max-width", 96 | "max-height", 97 | "margin", 98 | "margin-top", 99 | "margin-right", 100 | "margin-bottom", 101 | "margin-left", 102 | "padding", 103 | "padding-top", 104 | "padding-right", 105 | "padding-bottom", 106 | "padding-left" 107 | ], 108 | [ 109 | "table-layout", 110 | "empty-cells", 111 | "caption-side", 112 | "border-spacing", 113 | "border-collapse", 114 | "list-style", 115 | "list-style-position", 116 | "list-style-type", 117 | "list-style-image" 118 | ], 119 | [ 120 | "content", 121 | "quotes", 122 | "counter-reset", 123 | "counter-increment", 124 | "resize", 125 | "cursor", 126 | "nav-index", 127 | "nav-up", 128 | "nav-right", 129 | "nav-down", 130 | "nav-left", 131 | "transition", 132 | "transition-delay", 133 | "transition-duration", 134 | "transition-property", 135 | "transform", 136 | "transform-origin", 137 | "animation", 138 | "animation-name", 139 | "animation-duration", 140 | "animation-play-state", 141 | "animation-timing-function", 142 | "animation-delay", 143 | "animation-iteration-count", 144 | "animation-iteration-count", 145 | "animation-direction", 146 | "text-align", 147 | "text-align-last", 148 | "vertical-align", 149 | "white-space", 150 | "text-decoration", 151 | "text-emphasis", 152 | "text-emphasis-color", 153 | "text-emphasis-style", 154 | "text-emphasis-position", 155 | "text-indent", 156 | "text-justify", 157 | "text-transform", 158 | "letter-spacing", 159 | "word-spacing", 160 | "text-outline", 161 | "text-transform", 162 | "text-wrap", 163 | "text-overflow", 164 | "text-overflow-ellipsis", 165 | "text-overflow-mode", 166 | "word-wrap", 167 | "word-break", 168 | "tab-size", 169 | "hyphens", 170 | "pointer-events" 171 | ], 172 | [ 173 | "color", 174 | "border", 175 | "border-collapse", 176 | "border-width", 177 | "border-style", 178 | "border-color", 179 | "border-top", 180 | "border-top-width", 181 | "border-top-style", 182 | "border-top-color", 183 | "border-right", 184 | "border-right-width", 185 | "border-right-style", 186 | "border-right-color", 187 | "border-bottom", 188 | "border-bottom-width", 189 | "border-bottom-style", 190 | "border-bottom-color", 191 | "border-left", 192 | "border-left-width", 193 | "border-left-style", 194 | "border-left-color", 195 | "border-radius", 196 | "border-top-left-radius", 197 | "border-top-right-radius", 198 | "border-bottom-right-radius", 199 | "border-bottom-left-radius", 200 | "border-image", 201 | "border-image-source", 202 | "border-image-slice", 203 | "border-image-width", 204 | "border-image-outset", 205 | "border-image-repeat", 206 | "outline", 207 | "outline-width", 208 | "outline-style", 209 | "outline-color", 210 | "outline-offset", 211 | "background", 212 | "background-color", 213 | "background-image", 214 | "background-repeat", 215 | "background-attachment", 216 | "background-position", 217 | "background-position-x", 218 | "background-position-y", 219 | "background-clip", 220 | "background-origin", 221 | "background-size", 222 | "box-decoration-break", 223 | "box-shadow", 224 | "text-shadow" 225 | ], 226 | [ 227 | "font", 228 | "font-family", 229 | "font-size", 230 | "font-weight", 231 | "font-style", 232 | "font-variant", 233 | "font-size-adjust", 234 | "font-stretch", 235 | "font-effect", 236 | "font-emphasize", 237 | "font-emphasize-position", 238 | "font-emphasize-style", 239 | "font-smooth", 240 | "line-height" 241 | ], 242 | [ 243 | "$include mq" 244 | ] 245 | ] 246 | }, 247 | "editor.codeActionsOnSave": { 248 | "source.fixAll.eslint": true 249 | } 250 | }, 251 | "extensions": { 252 | "recommendations": [ 253 | "dbaeumer.vscode-eslint", 254 | "mrmlnc.vscode-csscomb", 255 | "ronnidc.nunjucks", 256 | "editorconfig.editorconfig", 257 | "fterrag.vscode-php-cs-fixer", 258 | "streetsidesoftware.code-spell-checker", 259 | "ms-azuretools.vscode-docker", 260 | "mikestead.dotenv", 261 | "felixfbecker.php-pack", 262 | "felixfbecker.php-debug", 263 | "hangxingliu.vscode-nginx-conf-hint", 264 | "ronnidc.nunjucks", 265 | "wayou.vscode-todo-highlight", 266 | "redhat.vscode-yaml", 267 | "mehedidracula.php-namespace-resolver" 268 | ] 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { mapRange } = require('canvas-sketch-util/math') 2 | const { clipPolylinesToBox } = require('canvas-sketch-util/geometry') 3 | const { contain } = require('./intrinsic-scale') 4 | 5 | const defaultConfig = { 6 | feedRate: 8000, // G1 movement (drawing speed) 7 | seekRate: 8000, // G0 movement (no drawing speed) 8 | onCommand: 'M03S20', 9 | offCommand: 'M03S0', 10 | powerDelay: 0.2, 11 | fileName: 'sketch', 12 | paperSize: [210, 297], 13 | margin: 10, 14 | flipX: false, 15 | flipY: false 16 | } 17 | 18 | class GCodeFile { 19 | constructor(config) { 20 | this.config = { 21 | ...defaultConfig, 22 | ...config 23 | } 24 | this.normalizeMargin() 25 | this.updateDrawArea() 26 | this.clear() 27 | } 28 | 29 | clear(){ 30 | this.layers = [] 31 | this.addLayer() 32 | } 33 | 34 | addLayer(name = ''){ 35 | this.layers.push({ 36 | name, 37 | gcode: '' 38 | }) 39 | this.currentLayer = this.layers.length - 1 40 | } 41 | 42 | normalizeMargin() { 43 | if (typeof this.config.margin === 'number') { 44 | this.config.margin = [this.config.margin, this.config.margin, this.config.margin, this.config.margin] 45 | } else if (Array.isArray(this.config.margin)) { 46 | if (this.config.margin.length === 2) { 47 | this.config.margin[2] = this.config.margin[0] 48 | this.config.margin[3] = this.config.margin[1] 49 | } 50 | } else { 51 | throw new Error('Margin option can be a number or an array.') 52 | } 53 | } 54 | 55 | updateConfig(config = {}) { 56 | this.config = { 57 | ...this.config, 58 | ...config 59 | } 60 | 61 | this.normalizeMargin() 62 | this.updateDrawArea() 63 | } 64 | 65 | updateDrawArea() { 66 | this.drawArea = [ 67 | this.config.paperSize[0] - this.config.margin[0] - this.config.margin[2], 68 | this.config.paperSize[1] - this.config.margin[1] - this.config.margin[3] 69 | ] 70 | } 71 | 72 | updateCoordsArea(width, height) { 73 | this.coordsWidth = width 74 | this.coordsHeight = height 75 | this.updateDrawCoords() 76 | } 77 | 78 | updateDrawCoords() { 79 | const { 80 | offsetX, 81 | offsetY, 82 | width, 83 | height 84 | } = contain(this.drawArea[0], this.drawArea[1], this.coordsWidth, this.coordsHeight) 85 | this.offsetX = offsetX 86 | this.offsetY = offsetY 87 | this.drawWidth = width 88 | this.drawHeight = height 89 | } 90 | 91 | mapCoordsToDrawArea(x, y) { 92 | if (!this.coordsWidth) { 93 | throw new Error('Must call "updateCoordsArea" passing width and height of your coordinate system!') 94 | } 95 | if (!this.coordsHeight) { 96 | throw new Error('Must call "updateCoordsArea" passing width and height of your coordinate system!') 97 | } 98 | 99 | const coords = { 100 | x: this.config.margin[0] + this.offsetX + mapRange(x, 0, this.coordsWidth, 0, this.drawWidth, true), 101 | y: this.config.margin[1] + this.offsetY + mapRange(y, 0, this.coordsHeight, 0, this.drawHeight, true) 102 | } 103 | 104 | if (this.config.flipX) { 105 | coords.x = this.config.paperSize[0] - coords.x 106 | } 107 | 108 | if (this.config.flipY) { 109 | coords.y = this.config.paperSize[1] - coords.y 110 | } 111 | 112 | coords.x = parseFloat(coords.x.toFixed(3)) 113 | coords.y = parseFloat(coords.y.toFixed(3)) 114 | 115 | return coords 116 | } 117 | 118 | moveTo(x, y) { 119 | const coords = this.mapCoordsToDrawArea(x, y) 120 | this.layers[this.currentLayer].gcode += `\n${this.config.offCommand}\nG4 P${this.config.powerDelay}\nG0 X${coords.x} Y${coords.y}\n${this.config.onCommand}\nG4 P${this.config.powerDelay}` 121 | } 122 | 123 | drawLine(x, y) { 124 | const coords = this.mapCoordsToDrawArea(x, y) 125 | this.layers[this.currentLayer].gcode += `\nG1 X${coords.x} Y${coords.y}` 126 | } 127 | 128 | addPolylines(polylines) { 129 | const lines = clipPolylinesToBox( 130 | polylines, 131 | [0, 0, this.coordsWidth, this.coordsHeight] 132 | ) 133 | 134 | lines.forEach(l => { 135 | l.forEach((point, i) => { 136 | if (i == 0) { 137 | this.moveTo(point[0], point[1]) 138 | } else { 139 | this.drawLine(point[0], point[1]) 140 | } 141 | }) 142 | }) 143 | } 144 | 145 | beginFile() { 146 | return `G0 F${this.config.seekRate}\nG1 F${this.config.feedRate}\nG90\nG21` 147 | } 148 | 149 | closeFile() { 150 | return `\n${this.config.offCommand}\nG4 P1\nG0 X0 Y0\nG4 P1` 151 | } 152 | 153 | downloadFile() { 154 | this.layers.forEach(layer => { 155 | // from https://stackoverflow.com/a/38019175 156 | const gcodeBlob = new Blob([this.beginFile()+layer.gcode+this.closeFile()], { type: 'text/plain;charset=utf-8' }) 157 | const gcodeUrl = URL.createObjectURL(gcodeBlob) 158 | const downloadLink = document.createElement('a') 159 | downloadLink.href = gcodeUrl 160 | downloadLink.download = this.config.fileName + (layer.name ? `-${layer.name}` : '') + '.gcode' 161 | document.body.appendChild(downloadLink) 162 | downloadLink.click() 163 | document.body.removeChild(downloadLink) 164 | }) 165 | } 166 | } 167 | 168 | module.exports = GCodeFile 169 | -------------------------------------------------------------------------------- /intrinsic-scale.js: -------------------------------------------------------------------------------- 1 | function fit(contains) { 2 | return (parentWidth, parentHeight, childWidth, childHeight, scale = 1, offsetX = 0.5, offsetY = 0.5) => { 3 | const childRatio = childWidth / childHeight 4 | const parentRatio = parentWidth / parentHeight 5 | let width = parentWidth * scale 6 | let height = parentHeight * scale 7 | 8 | if (contains ? (childRatio > parentRatio) : (childRatio < parentRatio)) { 9 | height = width / childRatio 10 | } else { 11 | width = height * childRatio 12 | } 13 | 14 | return { 15 | width, 16 | height, 17 | offsetX: (parentWidth - width) * offsetX, 18 | offsetY: (parentHeight - height) * offsetY 19 | } 20 | } 21 | } 22 | module.exports = { 23 | contain: fit(true), 24 | cover: fit(false) 25 | } 26 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcode-file", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abs-svg-path": { 8 | "version": "0.1.1", 9 | "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", 10 | "integrity": "sha1-32Acjo0roQ1KdtYl4japo5wnI78=" 11 | }, 12 | "adaptive-bezier-curve": { 13 | "version": "1.0.3", 14 | "resolved": "https://registry.npmjs.org/adaptive-bezier-curve/-/adaptive-bezier-curve-1.0.3.tgz", 15 | "integrity": "sha1-R3V3q+h9coDUbKQWSfbCJkb+gic=" 16 | }, 17 | "almost-equal": { 18 | "version": "1.1.0", 19 | "resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz", 20 | "integrity": "sha1-+FHGMROHV5lCdqou++jfowZszN0=" 21 | }, 22 | "an-array": { 23 | "version": "1.0.0", 24 | "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz", 25 | "integrity": "sha1-wSWlu4JXd4419LT2qpx9D6nkJmU=" 26 | }, 27 | "array-almost-equal": { 28 | "version": "1.0.0", 29 | "resolved": "https://registry.npmjs.org/array-almost-equal/-/array-almost-equal-1.0.0.tgz", 30 | "integrity": "sha1-Q8VP9DUELpy/pCEqxJraX8c1n8U=", 31 | "requires": { 32 | "almost-equal": "0.0.0", 33 | "an-array": "1.0.0" 34 | }, 35 | "dependencies": { 36 | "almost-equal": { 37 | "version": "0.0.0", 38 | "resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-0.0.0.tgz", 39 | "integrity": "sha1-56Wms0V7Z8g+4ARPmo0HY3NV8C0=" 40 | } 41 | } 42 | }, 43 | "canvas-sketch-util": { 44 | "version": "1.10.0", 45 | "resolved": "https://registry.npmjs.org/canvas-sketch-util/-/canvas-sketch-util-1.10.0.tgz", 46 | "integrity": "sha512-IiJWEQDBinl6KZVLYcdp79ZJXXKsS1HuDUoWtwWh0NJMVUA6jaM0pxcBRYiaujBXjQFPT91pl8L9iFFmma3+zA==", 47 | "requires": { 48 | "abs-svg-path": "0.1.1", 49 | "almost-equal": "1.1.0", 50 | "array-almost-equal": "1.0.0", 51 | "clone": "2.1.2", 52 | "color-luminance": "2.1.0", 53 | "convert-length": "1.0.1", 54 | "d3-path": "1.0.9", 55 | "defined": "1.0.0", 56 | "float-hsl2rgb": "1.0.2", 57 | "float-rgb2hsl": "1.0.1", 58 | "lineclip": "1.1.5", 59 | "normalize-svg-path": "1.0.1", 60 | "parse-color": "1.0.0", 61 | "parse-svg-path": "0.1.2", 62 | "primitive-quad": "2.0.0", 63 | "regl": "1.3.13", 64 | "seed-random": "2.2.0", 65 | "simplex-noise": "2.4.0", 66 | "svg-path-contours": "2.0.0" 67 | } 68 | }, 69 | "clone": { 70 | "version": "2.1.2", 71 | "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", 72 | "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" 73 | }, 74 | "color-convert": { 75 | "version": "0.5.3", 76 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", 77 | "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" 78 | }, 79 | "color-luminance": { 80 | "version": "2.1.0", 81 | "resolved": "https://registry.npmjs.org/color-luminance/-/color-luminance-2.1.0.tgz", 82 | "integrity": "sha1-WP8uvTK1LQf1N47v5aDnnWsxitc=" 83 | }, 84 | "convert-length": { 85 | "version": "1.0.1", 86 | "resolved": "https://registry.npmjs.org/convert-length/-/convert-length-1.0.1.tgz", 87 | "integrity": "sha512-w94Vge3sck6J1NHuA0du367/JTbj1zfjTapX7ixR2W+KlU4zb+NRTbou3x9nTpm5vlcXmjoaUJQpVN9pULCdxQ==", 88 | "requires": { 89 | "defined": "1.0.0" 90 | } 91 | }, 92 | "d3-path": { 93 | "version": "1.0.9", 94 | "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", 95 | "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" 96 | }, 97 | "defined": { 98 | "version": "1.0.0", 99 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 100 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" 101 | }, 102 | "float-hsl2rgb": { 103 | "version": "1.0.2", 104 | "resolved": "https://registry.npmjs.org/float-hsl2rgb/-/float-hsl2rgb-1.0.2.tgz", 105 | "integrity": "sha1-7PNQnECsZWfJaiBGIrDExL9DyKE=" 106 | }, 107 | "float-rgb2hsl": { 108 | "version": "1.0.1", 109 | "resolved": "https://registry.npmjs.org/float-rgb2hsl/-/float-rgb2hsl-1.0.1.tgz", 110 | "integrity": "sha1-jv6qD8cm5TNjp5vz9jYIIFXBDA4=" 111 | }, 112 | "lineclip": { 113 | "version": "1.1.5", 114 | "resolved": "https://registry.npmjs.org/lineclip/-/lineclip-1.1.5.tgz", 115 | "integrity": "sha1-K/JgZ9lDVP6r+R5CdoI221YW/RM=" 116 | }, 117 | "normalize-svg-path": { 118 | "version": "1.0.1", 119 | "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.0.1.tgz", 120 | "integrity": "sha1-b3Ka1rcLtMpO/y/ksQdInv4dVv4=", 121 | "requires": { 122 | "svg-arc-to-cubic-bezier": "3.2.0" 123 | } 124 | }, 125 | "parse-color": { 126 | "version": "1.0.0", 127 | "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", 128 | "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", 129 | "requires": { 130 | "color-convert": "0.5.3" 131 | } 132 | }, 133 | "parse-svg-path": { 134 | "version": "0.1.2", 135 | "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", 136 | "integrity": "sha1-en7A0esG+lMlx9PgCbhZoJtdSes=" 137 | }, 138 | "primitive-quad": { 139 | "version": "2.0.0", 140 | "resolved": "https://registry.npmjs.org/primitive-quad/-/primitive-quad-2.0.0.tgz", 141 | "integrity": "sha1-wgmT5PlgAjiSa7UA5SkFMEPvius=" 142 | }, 143 | "regl": { 144 | "version": "1.3.13", 145 | "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.13.tgz", 146 | "integrity": "sha512-TTiCabJbbUykCL4otjqOvKqDFJhvJOT7xB51JxcDeSHGrEJl1zz4RthPcoOogqfuR3ECN4Te790DfHCXzli5WQ==" 147 | }, 148 | "seed-random": { 149 | "version": "2.2.0", 150 | "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", 151 | "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=" 152 | }, 153 | "simplex-noise": { 154 | "version": "2.4.0", 155 | "resolved": "https://registry.npmjs.org/simplex-noise/-/simplex-noise-2.4.0.tgz", 156 | "integrity": "sha512-OjyDWm/QZjVbMrPxDVi9b2as+SeNn9EBXlrWVRlFW+TSyWMSXouDryXkQN0vf5YP+QZKobrmkvx1eQYPLtuqfw==" 157 | }, 158 | "svg-arc-to-cubic-bezier": { 159 | "version": "3.2.0", 160 | "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", 161 | "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==" 162 | }, 163 | "svg-path-contours": { 164 | "version": "2.0.0", 165 | "resolved": "https://registry.npmjs.org/svg-path-contours/-/svg-path-contours-2.0.0.tgz", 166 | "integrity": "sha1-x2oSlCnbBette2Hk0cWNEUqJOKI=", 167 | "requires": { 168 | "abs-svg-path": "0.1.1", 169 | "adaptive-bezier-curve": "1.0.3", 170 | "normalize-svg-path": "0.1.0", 171 | "vec2-copy": "1.0.0" 172 | }, 173 | "dependencies": { 174 | "normalize-svg-path": { 175 | "version": "0.1.0", 176 | "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz", 177 | "integrity": "sha1-RWNg5g7Odfvve11+FgSA5//Rb+U=" 178 | } 179 | } 180 | }, 181 | "vec2-copy": { 182 | "version": "1.0.0", 183 | "resolved": "https://registry.npmjs.org/vec2-copy/-/vec2-copy-1.0.0.tgz", 184 | "integrity": "sha1-xu7B2NrVRiUZTl9x+EM7YtLyCno=" 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gcode-file", 3 | "version": "1.0.6", 4 | "description": "Create and save a gcode file in browser via javascript", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/lavolpecheprogramma/gcode-file.git" 9 | }, 10 | "keywords": [ 11 | "gcode", 12 | "penplotter" 13 | ], 14 | "author": "Alberto Parziale", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/lavolpecheprogramma/gcode-file/issues" 18 | }, 19 | "homepage": "https://github.com/lavolpecheprogramma/gcode-file#readme", 20 | "dependencies": { 21 | "canvas-sketch-util": "^1.10.0" 22 | } 23 | } 24 | --------------------------------------------------------------------------------