├── .editorconfig ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── config ├── development │ ├── test.cert │ └── test.key ├── parcel.config.ts └── parcel.serve.ts ├── package-lock.json ├── package.json ├── postbuild.ts ├── postinstall.ts ├── src ├── crate │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── global.css ├── index.html ├── index.svelte └── index.ts ├── svelte.config.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [{src,scripts}/**.{ts,json,js}] 4 | end_of_line = crlf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Projects 2 | dist/ 3 | logs/ 4 | .cache 5 | .DS_Store 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript v1 declaration files 46 | typings/ 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Optional REPL history 55 | .node_repl_history 56 | 57 | # Output of 'npm pack' 58 | *.tgz 59 | 60 | # Yarn Integrity file 61 | .yarn-integrity 62 | 63 | # dotenv environment variables file 64 | .env 65 | 66 | # next.js build output 67 | .next 68 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": false, 5 | "singleQuote": true, 6 | "svelteSortOrder": "scripts-markup-styles", 7 | "svelteStrictMode": false, 8 | "svelteBracketNewLine": true 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 hmmhmmhm, HugoDaniel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚧 Svelte Template 2 | 3 | > Svelte + Rust WebAsm + Typescript + Parcel + Express 4 | 5 | This repository is a template to allow Svelte to import a rust crate directly in it. 6 | 7 | A change on the rust files on the crate triggers the Hot Module Reloading[HMR] and automatically reflects on the browser the changes done. 8 | 9 | It is based on the awesome work by [hmmhmmhm](https://github.com/hmmhmmhm/svelte-template). 10 | 11 | ## Installation 12 | 13 | You can install this template in at least three different ways: 14 | 15 | 1. Using `degit`: 16 | 17 | `npx degit HugoDaniel/svelte-template my-svelte-project` 18 | 19 | 2. Using the "Use this template" GitHub button above 20 | 21 | 3. Just fork and clone it 22 | 23 | After one of the above steps have been made, you have to: 24 | 25 | - `cd my-svelte-project` 26 | - `npm install` 27 | - `npm start` 28 | 29 | ## Command 30 | 31 | - npm start 32 | 33 | > Run the development server. This command creates a path accessible through HTTP and HTTPS. HTTP is applied with Hot Module Replacement (HMR). HTTPS has a built-in certificate for testing. 34 | 35 | - npm run build 36 | 37 | > Generate production build results. Minify is applied to the result and hmr is excluded. 38 | 39 | - npm run watch 40 | 41 | > Same as the npm start command, but does not serve the code with HTTP and HTTPS. 42 | 43 | - npm run clean 44 | 45 | > This command deletes all files in the 'dist' folder. However, the folder below the list is not deleted. If there is a static resource that should not be deleted, create a folder in the folder and use it. 46 | 47 | ## License 48 | 49 | MIT Licensed 50 | 51 | -------------------------------------------------------------------------------- /config/development/test.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC6zCCAdOgAwIBAgIJAM+W7ZfKBWToMA0GCSqGSIb3DQEBBQUAMAwxCjAIBgNV 3 | BAMMASowHhcNMTkxMDA1MDQwMjQwWhcNMjkxMDAyMDQwMjQwWjAMMQowCAYDVQQD 4 | DAEqMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlLGVb9Z/E/doQBGO 5 | 0LYkjbisA355Ja6r6p1wANUfpzIjNx9PannxE5qzObRsA4A/IQADeAAXQ6RmBhpt 6 | 1/PJf8y5qMGVjO8kUGVPcphgttsson0526M3Cz3IKKILThMYCZ2OxH9eZGM3ptsK 7 | I91rOBbEbUerXsSaejczF9383X3Hvx1JRGWea9/yyqQKZ3nEc7QlyOko3y9eIUm1 8 | F4sYHO9jcJQhDAmUVtjbmClNF8W5sH1uM66h8CvpRs7NPogy6Sajq79bx8WU+xDT 9 | FTZYWHYfhUaUkX4cOGZ2Us35jgamF6e2GJwVwGx47NlMMYnfk98brwDvt+MIV2lv 10 | lpT0lQIDAQABo1AwTjAdBgNVHQ4EFgQUTnXE9J+8G8DmH1MjMUNmlpudeRkwHwYD 11 | VR0jBBgwFoAUTnXE9J+8G8DmH1MjMUNmlpudeRkwDAYDVR0TBAUwAwEB/zANBgkq 12 | hkiG9w0BAQUFAAOCAQEALiH3nHQru/qT9/Rm8ULjjZb0DnVQbyfSUv0mG7sJHn6o 13 | Ox0lQqYIC1kN3jXG6aUVtc97Ig1WT3aLKPN86yST+21JHP7qMf+PIPM/62h7F7cd 14 | GcZaHTd4cJIp68BFYP/oKMTupNORYeerBxLTFWADTAghksE3U5R6GZEeFTv5UjEx 15 | SisHt0pUmSX5PuMQA5uwrGvHfFHCrpi0Lt3pPw2aQhRerigoMpPIrpSYOIlQdXF5 16 | yTF0vB2ctxFOPt1nqxWywnVSW415NOhZn7EH7PKdC7JQm5aSGeR52qfQhx5FxVnl 17 | zAC+gNYmm+9LGLQz1pjMHFDJEChQwZBjK+Z9oS0RVA== 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /config/development/test.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAlLGVb9Z/E/doQBGO0LYkjbisA355Ja6r6p1wANUfpzIjNx9P 3 | annxE5qzObRsA4A/IQADeAAXQ6RmBhpt1/PJf8y5qMGVjO8kUGVPcphgttsson05 4 | 26M3Cz3IKKILThMYCZ2OxH9eZGM3ptsKI91rOBbEbUerXsSaejczF9383X3Hvx1J 5 | RGWea9/yyqQKZ3nEc7QlyOko3y9eIUm1F4sYHO9jcJQhDAmUVtjbmClNF8W5sH1u 6 | M66h8CvpRs7NPogy6Sajq79bx8WU+xDTFTZYWHYfhUaUkX4cOGZ2Us35jgamF6e2 7 | GJwVwGx47NlMMYnfk98brwDvt+MIV2lvlpT0lQIDAQABAoIBAFSgOS+cgViov2Fv 8 | XLu2Xll2WBfo/CQRJHDzx5IBufEbXOV7YWR1IFqK+iQGZk8bx1INwuuiCZuKzjH9 9 | CrUUX4LnzmaYPngmhqFm9299/9UyKlYUNUCmxKYWNHvDtfFqdozKaj21S9CQk1TY 10 | Zw4Ab4xNkN+tIYBfHpgeIGseAVNA67ydqhqH2rHixwBVDSJMe3mn8G7W9uLcurOV 11 | Hhhp+V7x1DrX83ucnuniM/YZxslPwPGYGRKVm5c5L9pjDDHm114fH1E/SCd1VPCT 12 | 5iV4TRYBkANy20Ocn0kx2aLZNuje2wbJauluoaVUy9in6CPP/NmY1RPH5i/lwK40 13 | tIQG64ECgYEAxT0/F9OyQ1Sv9UE92ydSr7GjtyikwMT8C7V1BAGzIUdADUjWz/BP 14 | 9xJs9vDPAQ4fU/KcvaT9x2P4o/zSc6zyCgQSicUkPWDT13mEAQKbE7FXzA7n0km3 15 | bNoyyAfC0NpsqcCZKWqjPnoB0i3LMKKh1hqL21bm/1esgnEsuQphUiECgYEAwP3v 16 | lIbO3q908sKlmYWdC3pMDChW3wiSJoN4RUqG6kZvtgv7gt8QrHPf5LvnWUGQFuYY 17 | 5ZRqylSZ2C7/014vlyZOMMDqIoyn2HdhKf90U/aLdjD+yEacL+24/2vWlGjAElxI 18 | oxN40P0HjjoZE6yOPqeilpfNHBOsEcih5ySL+/UCgYBFMYJDyplb84azBEs96aKh 19 | TjE/3PtHQROmy+acHDiKMSOwRWBOnGCBLa6aRspn9VtaKN+BzDLXUyPz64qs1/wl 20 | NV6HhGh9O821ZsS/UfmzQ+CoDoaXCBNYFYgBEm/usuGx/4X7uJRCI60l3bjNfBBI 21 | OxHbRbZN16UGMcvdsl2H4QKBgQCsu1tQY2wKcZ3JnZ+cDbOmzzn7c6t1CfXNVMQz 22 | uGWSj6JynLzqwH3q6/dLgUaqY3z0kdNcv/7owtnDXSWJ5/XOYfF/v1qPu7aKjya+ 23 | 8S4L7FGcYnPXiyNF3o5CxiETScIHbONyWf47hwzZJnTFYB8cQuvJv2pMI+tRK3KF 24 | L/e+dQKBgD1U9VIr63EWZJu5T+y+Kqj65LgoeKEiBSf6vqR3syYAxKx3OyZko076 25 | IFtcN4RY0mmA2sR72o/hbDtJwL0peiE3qpHtaKV1D8G0Ov8JPl6sA/hpzEdm3MCO 26 | 8FKd+LfsVeFWqBBYe2Jo2h4nK8Ae21q0yE3rIlLWuwv4T+0zw0S/ 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /config/parcel.config.ts: -------------------------------------------------------------------------------- 1 | import Bundler from 'parcel-bundler' 2 | import path from 'path' 3 | import { serve } from './parcel.serve' 4 | import SveltePlugin from 'parcel-plugin-svelte' 5 | 6 | export const template = path.join(process.cwd(), './src/index.html') 7 | 8 | export const options = { 9 | outDir: './dist', 10 | outFile: 'index.html', 11 | publicUrl: './', 12 | watch: false, 13 | cache: true, 14 | minify: false, 15 | target: 'browser', 16 | https: false, 17 | logLevel: 3, 18 | hmrPort: 0, 19 | production: false, 20 | hmrHostname: '', 21 | sourceMaps: false, 22 | detailedReport: true, 23 | } 24 | 25 | export const getBundler = async options => { 26 | let bundler = new Bundler(template, options) 27 | await SveltePlugin(bundler) 28 | return bundler 29 | } 30 | 31 | export const runBundle = async options => { 32 | let bundler = await getBundler(options) 33 | return await bundler.bundle() 34 | } 35 | 36 | if (process.argv[1] == __filename) { 37 | switch (process.argv[2]) { 38 | case '--serve': 39 | serve() 40 | break 41 | case '--watch': 42 | runBundle({ ...options, production: true, watch: true }) 43 | break 44 | case '--build': 45 | runBundle({ 46 | ...options, 47 | production: true, 48 | minify: true, 49 | hmr: false, 50 | }) 51 | break 52 | case '--product-build': 53 | runBundle({ 54 | ...options, 55 | production: true, 56 | minify: true, 57 | outDir: './production', 58 | hmr: false, 59 | }) 60 | break 61 | case '--product-serve': 62 | serve({ isProductMode: true }) 63 | break 64 | } 65 | } 66 | 67 | export default options 68 | -------------------------------------------------------------------------------- /config/parcel.serve.ts: -------------------------------------------------------------------------------- 1 | import Express from 'express' 2 | import CORS from 'cors' 3 | import NestedStatic from 'nested-static' 4 | import FolderLogger from 'folder-logger' 5 | import { options, getBundler } from './parcel.config' 6 | import { readFileSync, mkdir, mkdirSync } from 'fs' 7 | import yargs from 'yargs' 8 | import http from 'http' 9 | import https from 'https' 10 | import PublicIp from 'public-ip' 11 | 12 | // Default Arguments 13 | yargs.default('http-port', 8080).default('https-port', 8443) 14 | let { httpPort, httpsPort } = yargs.argv 15 | 16 | export const testCertificate = { 17 | key: readFileSync('./config/development/test.key', 'utf8'), 18 | cert: readFileSync('./config/development/test.cert', 'utf8'), 19 | } 20 | 21 | export const serve = async ({ isProductMode } = { isProductMode: false }) => { 22 | const Logger = new FolderLogger('./logs') 23 | const expressInstance = Express() 24 | 25 | // Enable CORS 26 | expressInstance.use(CORS()) 27 | 28 | // Publish Path 29 | let publishPath = `${process.cwd()}/dist` 30 | if (isProductMode) { 31 | publishPath = `${process.cwd()}/production` 32 | } 33 | 34 | try { 35 | mkdirSync(publishPath) 36 | } catch (e) {} 37 | 38 | // Register Static Files 39 | NestedStatic(publishPath, folders => { 40 | Logger.debug(`🚧 Registering a static resources path...`) 41 | for (let { staticPath, subPath } of folders) { 42 | expressInstance.use(subPath, Express.static(staticPath)) 43 | Logger.debug(`🚧 Static Path: ${subPath}`) 44 | } 45 | }) 46 | 47 | // Register Parcel 48 | if (!isProductMode) { 49 | expressInstance.use( 50 | (await getBundler({ ...options, watch: true })).middleware() 51 | ) 52 | } 53 | 54 | // Collect Server Handles 55 | let handles = { 56 | httpServer: http.createServer(expressInstance), 57 | httpsServer: https.createServer(testCertificate, expressInstance), 58 | } 59 | 60 | // Binding a Port 61 | console.log('') 62 | Logger.debug(`🚧 HTTP & HTTPS Server Running...`) 63 | handles.httpServer.listen(httpPort, () => { 64 | Logger.debug(`🚧 - http://localhost:${httpPort}`) 65 | }) 66 | handles.httpsServer.listen(httpsPort, () => { 67 | Logger.debug(`🚧 - https://localhost:${httpsPort}`) 68 | }) 69 | 70 | let publicIp: string | undefined = undefined 71 | try { 72 | publicIp = await PublicIp.v4() 73 | } catch (e) {} 74 | if (publicIp) { 75 | console.log('') 76 | Logger.debug(`🚧 External HTTP & HTTPS Server Address`) 77 | Logger.debug(`🚧 - http://${publicIp}:${httpPort}`) 78 | Logger.debug(`🚧 - https://${publicIp}:${httpsPort}`) 79 | } 80 | 81 | return handles 82 | } 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-template", 3 | "version": "1.0.3", 4 | "main": "src/index.ts", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "npm run clean && ts-node ./config/parcel.config.ts --serve --http-port 8080 --https-port 8443", 8 | "build": "npm run clean && ts-node ./config/parcel.config.ts --build && npm run postbuild", 9 | "watch": "npm run clean && ts-node ./config/parcel.config.ts --watch", 10 | "clean": "rm -rf ./dist/*.*", 11 | "production": "node ./production-ts/config/parcel.config.js --product-serve --http-port 80 --https-port 442", 12 | "production-build": "npm run production-clean && tsc && ts-node ./config/parcel.config.ts --product-build && node ./postbuild.ts ./production", 13 | "production-clean": "rm -rf ./production/*.* && rm -rf ./production-ts/*.*", 14 | "postinstall": "rm -rf ./.cache && node ./postinstall.ts", 15 | "postbuild": "node ./postbuild.ts ./dist", 16 | "lint": "prettier --write ./src/**/*.{ts,js,css,html,svelte}" 17 | }, 18 | "dependencies": { 19 | "autoprefixer": "^9.7.6", 20 | "caniuse-lite": "^1.0.30001051", 21 | "core-js": "^3.6.5", 22 | "cors": "^2.8.5", 23 | "express": "^4.17.1", 24 | "folder-logger": "^1.0.7", 25 | "nested-static": "^1.1.0", 26 | "node-sass": "^4.14.1", 27 | "parcel-bundler": "^1.12.4", 28 | "parcel-plugin-svelte": "^4.0.6", 29 | "parcel-plugin-wasm.rs": "^1.2.16", 30 | "postcss": "^7.0.29", 31 | "postcss-load-config": "^2.1.0", 32 | "public-ip": "^4.0.1", 33 | "svelte": "^3.22.2", 34 | "svelte-preprocess": "^3.7.4", 35 | "svelte-preprocess-sass": "^0.2.0", 36 | "svelte-ts-preprocess": "^1.1.3", 37 | "temp-dir": "^2.0.0", 38 | "ts-node": "^8.10.1", 39 | "tslib": "^1.11.1", 40 | "typescript": "^3.8.3", 41 | "yargs": "^15.3.1" 42 | }, 43 | "devDependencies": { 44 | "@pyoner/svelte-ts-preprocess": "^1.2.1", 45 | "@types/express": "^4.17.6", 46 | "@types/node": "^13.13.4", 47 | "prettier": "^2.0.5", 48 | "prettier-plugin-svelte": "^1.1.0" 49 | }, 50 | "browserslist": [ 51 | "cover 99.5%" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /postbuild.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const fs = require('fs') 3 | 4 | const getExtension = fileName => { 5 | let extensionArr = fileName.split('.') 6 | return extensionArr[extensionArr.length - 1] 7 | } 8 | 9 | const postBuild = targetPath => { 10 | let fileNames = fs.readdirSync(targetPath) 11 | // console.log(targetPath, files) 12 | 13 | let scripts = [] 14 | let resources = [] 15 | 16 | let resourceExts = ['css', 'png', 'jpg', 'jpeg', 'gif'] 17 | 18 | // Collection and Classification 19 | for (let fileName of fileNames) { 20 | // console.log(fileName) 21 | if (getExtension(fileName) == 'js') scripts.push(fileName) 22 | else { 23 | for (let resourceExt of resourceExts) { 24 | if (getExtension(fileName) == resourceExt) { 25 | resources.push(fileName) 26 | break 27 | } 28 | } 29 | } 30 | } 31 | 32 | // Exclude targets already scheduled to load 33 | let indexHtmlPath = targetPath + '/index.html' 34 | let indexHtml = fs.readFileSync(indexHtmlPath) 35 | let needToPrefetchScripts = [] 36 | let needToPrefetchResources = [] 37 | for (let script of scripts) { 38 | let isExistInIndexHtml = String(indexHtml).indexOf(script) != -1 39 | if (!isExistInIndexHtml) needToPrefetchScripts.push(script) 40 | } 41 | for (let resource of resources) { 42 | let isExistInIndexHtml = String(indexHtml).indexOf(resource) != -1 43 | if (!isExistInIndexHtml) needToPrefetchResources.push(resource) 44 | } 45 | //console.log('scripts:', needToPrefetchScripts) 46 | //console.log('resources:', needToPrefetchResources) 47 | //console.log('origina HTML', indexHtml) 48 | 49 | // Create Prefetch Inejct Code 50 | let injectPrefetchList = '' 51 | for (let needToPrefetchScript of needToPrefetchScripts) 52 | injectPrefetchList += `` 53 | for (let needToPrefetchResource of needToPrefetchResources) 54 | injectPrefetchList += `` 55 | 56 | let changedHtml = String(indexHtml).replace( 57 | '', 58 | injectPrefetchList + '' 59 | ) 60 | fs.writeFileSync(indexHtmlPath, changedHtml) 61 | console.log( 62 | `${needToPrefetchScripts.length + 63 | needToPrefetchResources.length}'s prefetch registrations completed.` 64 | ) 65 | } 66 | 67 | // @ts-ignore 68 | const targetPath = String(process.argv[2]) 69 | 70 | // @ts-ignore 71 | if (process.argv[1].indexOf('postbuild.ts') !== -1 && targetPath.length != 0) 72 | postBuild(targetPath) 73 | 74 | // @ts-ignore 75 | module.exports = postBuild 76 | -------------------------------------------------------------------------------- /postinstall.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | const fs = require('fs') 3 | const nodeVersion = 'node 10.11' 4 | 5 | const exceptionList = [ 6 | './node_modules/core-js', 7 | './node_modules/core-js-compat', 8 | ] 9 | 10 | const collect = (staticPath, subPath = '/') => { 11 | let files = fs.readdirSync(staticPath) 12 | let folders = [{subPath,staticPath}] 13 | 14 | for(let file of files){ 15 | let checkPath = staticPath + '/' + file 16 | let stats = fs.statSync(checkPath) 17 | if(! stats.isDirectory()) continue 18 | 19 | if(exceptionList.indexOf(checkPath) != -1) continue 20 | let collectedDatas = collect(checkPath, subPath + file + '/') 21 | 22 | for(let collectedData of collectedDatas) 23 | folders.push(collectedData) 24 | } 25 | 26 | return folders 27 | } 28 | 29 | const find = staticPath => { 30 | let folders = [] 31 | 32 | for(let folder of collect(staticPath)) 33 | if(fs.existsSync(folder.staticPath + `/package.json`)) 34 | folders.push(folder.staticPath) 35 | 36 | return folders 37 | } 38 | 39 | const patch = staticPath => { 40 | let folders = find(staticPath) 41 | 42 | for (let folderName of folders) { 43 | let stats = fs.statSync(folderName) 44 | if (!stats.isDirectory()) continue 45 | 46 | try { 47 | let packageFilePath = `${folderName}/package.json` 48 | let browserListFilePath = `${folderName}/.browserslistrc` 49 | let packageFileData = JSON.parse(fs.readFileSync(packageFilePath)) 50 | 51 | delete packageFileData['browserslist'] 52 | fs.writeFileSync(browserListFilePath, nodeVersion) 53 | fs.writeFileSync( 54 | packageFilePath, 55 | JSON.stringify(packageFileData, null, 2) 56 | ) 57 | // console.log(`Fixed browserlist in ${packageFilePath}`) 58 | } catch (e) {} 59 | } 60 | } 61 | 62 | patch('./node_modules') 63 | console.log(`All browserlist has been updated.`) 64 | -------------------------------------------------------------------------------- /src/crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The RustWasm Developers"] 3 | categories = ["wasm"] 4 | description = "My super awesome Rust, WebAssembly, and Svelte project!" 5 | license = "MIT" 6 | name = "rust-parcel" 7 | readme = "./README.md" 8 | repository = "https://github.com/rustwasm/rust-parcel-template" 9 | version = "0.1.0" 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [dependencies] 15 | cfg-if = "0.1.5" 16 | wasm-bindgen = "0.2.29" 17 | 18 | # The `console_error_panic_hook` crate provides better debugging of panics by 19 | # logging them with `console.error`. This is great for development, but requires 20 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 21 | # code size when deploying. 22 | console_error_panic_hook = { version = "0.1.5", optional = true } 23 | 24 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 25 | # compared to the default allocator's ~10K. It is slower than the default 26 | # allocator, however. Also as of wee_alloc v0.4.2, does not yet work on stable 27 | # (tested with rust v1.31.1). 28 | wee_alloc = { version = "0.4.2", optional = true } 29 | 30 | [dependencies.web-sys] 31 | version = "0.3.6" 32 | features = [ 33 | 'Document', 34 | 'Element', 35 | 'HtmlElement', 36 | 'Node', 37 | 'Window', 38 | ] 39 | 40 | [features] 41 | default = ["console_error_panic_hook"] 42 | -------------------------------------------------------------------------------- /src/crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate cfg_if; 3 | 4 | extern crate wasm_bindgen; 5 | extern crate web_sys; 6 | use wasm_bindgen::prelude::*; 7 | 8 | cfg_if! { 9 | // When the `console_error_panic_hook` feature is enabled, we can call the 10 | // `set_panic_hook` function to get better error messages if we ever panic. 11 | if #[cfg(feature = "console_error_panic_hook")] { 12 | extern crate console_error_panic_hook; 13 | use console_error_panic_hook::set_once as set_panic_hook; 14 | } else { 15 | #[inline] 16 | fn set_panic_hook() {} 17 | } 18 | } 19 | 20 | cfg_if! { 21 | // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global 22 | // allocator. 23 | if #[cfg(feature = "wee_alloc")] { 24 | extern crate wee_alloc; 25 | #[global_allocator] 26 | static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 27 | } 28 | } 29 | 30 | // Called by our JS entry point to run the example 31 | #[wasm_bindgen] 32 | pub fn run() -> Result { 33 | // If the `console_error_panic_hook` feature is enabled this will set a panic hook, otherwise 34 | // it will do nothing. 35 | set_panic_hook(); 36 | 37 | Ok(JsValue::from_str("Rust from WebAsm <3")) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/global.css: -------------------------------------------------------------------------------- 1 | :global(body) { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | } 6 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | Svelte Is Awesome! 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/index.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |

{a} + {b} + {c} + {d}

13 | 14 | 21 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/stable' 2 | import 'regenerator-runtime/runtime' 3 | 4 | // @ts-ignore 5 | import Svelte from './index.svelte' 6 | 7 | new Svelte({ 8 | target: document.body, 9 | }) 10 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | const pyoner = require("@pyoner/svelte-ts-preprocess") 2 | const { scss, postcss } = require('svelte-preprocess') 3 | const autoprefixer = require('autoprefixer') 4 | 5 | // For svelte-vscode 6 | let configJs = { preprocess: pyoner.preprocess() } 7 | 8 | // Check svelte-vscode 9 | let isSvelteLanguageServer = false 10 | for (let argv of process.argv) { 11 | if (argv.indexOf('svelte-language-server') != -1) { 12 | isSvelteLanguageServer = true 13 | break 14 | } 15 | } 16 | 17 | // If the call is by an instance, not by svelte-vscode. 18 | if (!isSvelteLanguageServer) { 19 | configJs = { 20 | preprocess: [ 21 | scss(), 22 | postcss({ 23 | plugins: [ 24 | autoprefixer() 25 | ] 26 | }), 27 | pyoner.preprocess() 28 | ], 29 | compilerOptions: { 30 | css: false 31 | } 32 | } 33 | } 34 | 35 | module.exports = configJs -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./production-ts", 4 | "importHelpers": true, 5 | "sourceMap": false, 6 | "inlineSourceMap": false, 7 | "noImplicitAny": false, 8 | "module": "commonjs", 9 | "target": "ES3", 10 | "types": ["node"], 11 | "lib": ["dom"], 12 | "moduleResolution": "node", 13 | "forceConsistentCasingInFileNames": true, 14 | "noImplicitReturns": true, 15 | "noImplicitThis": true, 16 | "strictNullChecks": true, 17 | "suppressImplicitAnyIndexErrors": true, 18 | "resolveJsonModule": true, 19 | "allowSyntheticDefaultImports": true, 20 | "esModuleInterop": true, 21 | "emitDecoratorMetadata": true, 22 | "experimentalDecorators": true, 23 | "baseUrl": "." 24 | }, 25 | "include": [ 26 | "./src/**/*", 27 | "./config/**/*" 28 | ] 29 | } --------------------------------------------------------------------------------