├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── README.md ├── package.json ├── packages ├── app │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── global.css │ │ └── index.html │ ├── rollup.config.js │ ├── src │ │ ├── App.svelte │ │ ├── Form.svelte │ │ ├── funcs.ts │ │ ├── main.js │ │ └── types.ts │ └── tsconfig.json ├── nossr │ ├── .gitignore │ ├── README.md │ ├── package.json │ └── src │ │ └── index.ts ├── preprocess │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package.json │ ├── src │ │ └── svelte-ts-preprocess.ts │ ├── test │ │ └── svelte-ts-preprocess.test.ts │ ├── tools │ │ ├── gh-pages-publish.ts │ │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ └── tslint.json ├── sapper-template │ ├── .gitignore │ ├── README.md │ ├── appveyor.yml │ ├── cypress.json │ ├── cypress │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── spec.js │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── commands.js │ │ │ └── index.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── client.js │ │ ├── components │ │ │ ├── Counter.svelte │ │ │ └── Nav.svelte │ │ ├── routes │ │ │ ├── _error.svelte │ │ │ ├── _layout.svelte │ │ │ ├── about.svelte │ │ │ ├── blog │ │ │ │ ├── [slug].json.ts │ │ │ │ ├── [slug].svelte │ │ │ │ ├── _posts.ts │ │ │ │ ├── index.json.ts │ │ │ │ └── index.svelte │ │ │ ├── index.svelte │ │ │ └── nossr.svelte │ │ ├── server.js │ │ ├── service-worker.js │ │ └── template.html │ ├── static │ │ ├── favicon.png │ │ ├── global.css │ │ ├── great-success.png │ │ ├── logo-192.png │ │ ├── logo-512.png │ │ └── manifest.json │ ├── svelte.config.js │ └── tsconfig.json ├── template │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── global.css │ │ └── index.html │ ├── rollup.config.js │ ├── src │ │ ├── App.svelte │ │ ├── Counter.svelte │ │ ├── main.ts │ │ ├── store.ts │ │ └── types.ts │ ├── svelte.config.js │ └── tsconfig.json └── types │ ├── .gitignore │ ├── README.md │ ├── package.json │ └── types │ └── svelte │ ├── index.d.ts │ ├── svelte-tests.ts │ ├── svelte.d.ts │ ├── tsconfig.json │ └── tslint.json ├── pnpm-lock.yaml └── pnpm-workspace.yaml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | node_modules 4 | *.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Typescript monorepo for Svelte v3 includes 2 | 3 | - [preprocess](https://github.com/pyoner/svelte-typescript/tree/master/packages/preprocess) 4 | - [template](https://github.com/pyoner/svelte-typescript/tree/master/packages/template) 5 | - [types](https://github.com/pyoner/svelte-typescript/tree/master/packages/types) 6 | - [Sapper template](https://github.com/pyoner/svelte-typescript/tree/master/packages/sapper-template) 7 | 8 | # For Contributors 9 | 10 | To install this monorepo you can use `pnpm` 11 | 12 | ```bash 13 | cd svelte-typescript 14 | pnpm i -r 15 | ``` 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-typescript-monorepo", 3 | "private": "true", 4 | "version": "1.0.0", 5 | "description": "A monorepo for Svelte Typescript", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/pyoner/svelte-typescript.git" 12 | }, 13 | "keywords": [ 14 | "svelte", 15 | "typescript", 16 | "preprocess" 17 | ], 18 | "author": "Jungle ", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/pyoner/svelte-typescript/issues" 22 | }, 23 | "homepage": "https://github.com/pyoner/svelte-typescript#readme", 24 | "devDependencies": { 25 | "husky": "^4.2.3", 26 | "pretty-quick": "^2.0.1" 27 | }, 28 | "husky": { 29 | "hooks": { 30 | "pre-commit": "pretty-quick --staged" 31 | } 32 | }, 33 | "dependencies": { 34 | "typescript": "^3.9.6" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public/bundle.* 4 | package-lock.json 5 | yarn.lock 6 | .rpt2_cache -------------------------------------------------------------------------------- /packages/app/README.md: -------------------------------------------------------------------------------- 1 | *Psst — looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)* 2 | 3 | --- 4 | 5 | # svelte app 6 | 7 | This is a project template for [Svelte](https://svelte.technology) apps. It lives at https://github.com/sveltejs/template. 8 | 9 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): 10 | 11 | ```bash 12 | npm install -g degit # you only need to do this once 13 | 14 | degit sveltejs/template svelte-app 15 | cd svelte-app 16 | ``` 17 | 18 | *Note that you will need to have [Node.js](https://nodejs.org) installed.* 19 | 20 | 21 | ## Get started 22 | 23 | Install the dependencies... 24 | 25 | ```bash 26 | cd svelte-app 27 | npm install 28 | ``` 29 | 30 | ...then start [Rollup](https://rollupjs.org): 31 | 32 | ```bash 33 | npm run dev 34 | ``` 35 | 36 | Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. 37 | 38 | 39 | ## Deploying to the web 40 | 41 | ### With [now](https://zeit.co/now) 42 | 43 | Install `now` if you haven't already: 44 | 45 | ```bash 46 | npm install -g now 47 | ``` 48 | 49 | Then, from within your project folder: 50 | 51 | ```bash 52 | now 53 | ``` 54 | 55 | As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon. 56 | 57 | ### With [surge](https://surge.sh/) 58 | 59 | Install `surge` if you haven't already: 60 | 61 | ```bash 62 | npm install -g surge 63 | ``` 64 | 65 | Then, from within your project folder: 66 | 67 | ```bash 68 | npm run build 69 | surge public 70 | ``` 71 | -------------------------------------------------------------------------------- /packages/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "svelte-app", 4 | "version": "1.0.0", 5 | "devDependencies": { 6 | "@pyoner/svelte-ts-preprocess": "workspace:^1.3.0", 7 | "@rollup/plugin-commonjs": "^13.0.0", 8 | "@rollup/plugin-json": "^4.0.2", 9 | "@rollup/plugin-node-resolve": "^7.1.1", 10 | "@wessberg/rollup-plugin-ts": "^1.2.21", 11 | "npm-run-all": "^4.1.5", 12 | "rollup": "^2.19.0", 13 | "rollup-plugin-svelte": "^5.0.3", 14 | "rollup-plugin-terser": "^4.0.4", 15 | "sirv-cli": "^0.3.1", 16 | "svelte": "3.0.0", 17 | "typescript": "^3.8" 18 | }, 19 | "scripts": { 20 | "build": "rollup -c", 21 | "autobuild": "rollup -c -w", 22 | "dev": "run-p start:dev autobuild", 23 | "start": "sirv public", 24 | "start:dev": "sirv public --dev" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/app/public/global.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body { 8 | color: #333; 9 | margin: 0; 10 | padding: 8px; 11 | box-sizing: border-box; 12 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 13 | } 14 | 15 | a { 16 | color: rgb(0,100,200); 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | a:visited { 25 | color: rgb(0,80,160); 26 | } 27 | 28 | label { 29 | display: block; 30 | } 31 | 32 | input, button, select, textarea { 33 | font-family: inherit; 34 | font-size: inherit; 35 | padding: 0.4em; 36 | margin: 0 0 0.5em 0; 37 | box-sizing: border-box; 38 | border: 1px solid #ccc; 39 | border-radius: 2px; 40 | } 41 | 42 | input:disabled { 43 | color: #ccc; 44 | } 45 | 46 | input[type="range"] { 47 | height: 0; 48 | } 49 | 50 | button { 51 | background-color: #f4f4f4; 52 | outline: none; 53 | } 54 | 55 | button:active { 56 | background-color: #ddd; 57 | } 58 | 59 | button:focus { 60 | border-color: #666; 61 | } -------------------------------------------------------------------------------- /packages/app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Svelte app 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/app/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from "rollup-plugin-svelte"; 2 | import resolve from "@rollup/plugin-node-resolve"; 3 | import commonjs from "@rollup/plugin-commonjs"; 4 | import json from "@rollup/plugin-json"; 5 | import { terser } from "rollup-plugin-terser"; 6 | import typescript from "@wessberg/rollup-plugin-ts"; 7 | 8 | import { 9 | preprocess, 10 | createEnv, 11 | readConfigFile 12 | } from "@pyoner/svelte-ts-preprocess"; 13 | 14 | const production = !process.env.ROLLUP_WATCH; 15 | 16 | const env = createEnv(); 17 | const compilerOptions = readConfigFile(env); 18 | const opts = { 19 | env, 20 | compilerOptions: { 21 | ...compilerOptions, 22 | allowNonTsExtensions: true 23 | } 24 | }; 25 | 26 | export default { 27 | input: "src/main.js", 28 | output: { 29 | sourcemap: true, 30 | format: "iife", 31 | name: "app", 32 | file: "public/bundle.js" 33 | }, 34 | plugins: [ 35 | json(), 36 | svelte({ 37 | // enable run-time checks when not in production 38 | dev: !production, 39 | // we'll extract any component CSS out into 40 | // a separate file — better for performance 41 | css: css => { 42 | css.write("public/bundle.css"); 43 | }, 44 | preprocess: preprocess(opts) 45 | }), 46 | 47 | // If you have external dependencies installed from 48 | // npm, you'll most likely need these plugins. In 49 | // some cases you'll need additional configuration — 50 | // consult the documentation for details: 51 | // https://github.com/rollup/rollup-plugin-commonjs 52 | resolve(), 53 | commonjs(), 54 | typescript(), 55 | 56 | // If we're building for production (npm run build 57 | // instead of npm run dev), minify 58 | production && terser() 59 | ] 60 | }; 61 | -------------------------------------------------------------------------------- /packages/app/src/App.svelte: -------------------------------------------------------------------------------- 1 |

Hello {name}!

2 |
3 | 4 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /packages/app/src/Form.svelte: -------------------------------------------------------------------------------- 1 |
2 |

A Form component

3 |

Person

4 |
    5 |
  • name: {p.name}
  • 6 |
  • age: {p.age}
  • 7 |
  • phone: {p.phone}
  • 8 |
9 | 10 |

Sum

11 |

1 + 2 = {sum}

12 |
13 | 14 | 25 | -------------------------------------------------------------------------------- /packages/app/src/funcs.ts: -------------------------------------------------------------------------------- 1 | export const add = (a: number, b: number) => a + b; 2 | -------------------------------------------------------------------------------- /packages/app/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: { 6 | name: 'world' 7 | } 8 | }); 9 | 10 | export default app; -------------------------------------------------------------------------------- /packages/app/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Person { 2 | name: string; 3 | age: number; 4 | phone?: string; 5 | } 6 | -------------------------------------------------------------------------------- /packages/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "ESNEXT", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | 39 | /* Module Resolution Options */ 40 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/nossr/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | -------------------------------------------------------------------------------- /packages/nossr/README.md: -------------------------------------------------------------------------------- 1 | # No SSR preprocessor for Svelte 2 | 3 | This `preprocessor` remove a code from the `script` tag, see example: 4 | 5 | ```html 6 | 11 | 12 | 13 | 14 |

No SSR

15 | {x} 16 |
17 | ``` 18 | 19 | ## Installation 20 | 21 | ```bash 22 | npm i -D @pyoner/svelte-nossr-preprocess 23 | ``` 24 | 25 | ## How to use the preprocessor? 26 | 27 | See the [rollup config](https://github.com/pyoner/svelte-typescript/blob/master/packages/sapper-template/rollup.config.js) for Sapper 28 | -------------------------------------------------------------------------------- /packages/nossr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pyoner/svelte-nossr-preprocess", 3 | "version": "1.0.1", 4 | "description": "No SSR preprocessor for Svelte", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "build": "tsc -t esnext -m commonjs -d --outDir ./dist ./src/index.ts" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/pyoner/svelte-typescript.git" 14 | }, 15 | "keywords": [ 16 | "svelte", 17 | "sapper", 18 | "nossr", 19 | "ssr", 20 | "preprocess" 21 | ], 22 | "author": "Jungle ", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/pyoner/svelte-typescript/issues" 26 | }, 27 | "homepage": "https://github.com/pyoner/svelte-typescript/tree/master/packages/nossr#readme", 28 | "peerDependencies": { 29 | "typescript": "^3.8" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/nossr/src/index.ts: -------------------------------------------------------------------------------- 1 | interface Script { 2 | filename: string; 3 | content: string; 4 | attributes: { 5 | nossr?: string; 6 | }; 7 | } 8 | 9 | interface Markup { 10 | content: string; 11 | filename: string; 12 | } 13 | 14 | function script({ attributes }: Script) { 15 | const { nossr } = attributes; 16 | if (nossr !== undefined) { 17 | return { 18 | code: "" 19 | }; 20 | } 21 | } 22 | 23 | const p = /\(.|\n)*?\<\/nossr\>/gim; 24 | function markup({ content }: Markup) { 25 | const code = content.replace(p, ""); 26 | return { code }; 27 | } 28 | 29 | export function nossr() { 30 | return { 31 | script, 32 | markup 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /packages/preprocess/.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/preprocess/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | -------------------------------------------------------------------------------- /packages/preprocess/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - ~/.npm 5 | notifications: 6 | email: false 7 | node_js: 8 | - '10' 9 | - '11' 10 | - '8' 11 | - '6' 12 | script: 13 | - npm run test:prod && npm run build 14 | after_success: 15 | - npm run travis-deploy-once "npm run report-coverage" 16 | - if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then npm run travis-deploy-once "npm run deploy-docs"; fi 17 | - if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then npm run travis-deploy-once "npm run semantic-release"; fi 18 | branches: 19 | except: 20 | - /^v\d+\.\d+\.\d+$/ 21 | -------------------------------------------------------------------------------- /packages/preprocess/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/pyoner/svelte-typescript 11 | yarn install 12 | 13 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 14 | 15 | Finally send a [GitHub Pull Request](https://github.com/pyoner/svelte-typescript/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 16 | -------------------------------------------------------------------------------- /packages/preprocess/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Jungle 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/preprocess/README.md: -------------------------------------------------------------------------------- 1 | # Typescript preprocessor for Svelte 3 2 | 3 | ## Install 4 | 5 | ```bash 6 | npm i @pyoner/svelte-ts-preprocess 7 | ``` 8 | 9 | ## Rollup config 10 | 11 | ```javascript 12 | import svelte from "rollup-plugin-svelte"; 13 | import resolve from "rollup-plugin-node-resolve"; 14 | import commonjs from "rollup-plugin-commonjs"; 15 | import { terser } from "rollup-plugin-terser"; 16 | import typescript from "rollup-plugin-typescript2"; 17 | 18 | import { 19 | preprocess, 20 | createEnv, 21 | readConfigFile 22 | } from "@pyoner/svelte-ts-preprocess"; 23 | 24 | const production = !process.env.ROLLUP_WATCH; 25 | 26 | const env = createEnv(); 27 | const compilerOptions = readConfigFile(env); 28 | const opts = { 29 | env, 30 | compilerOptions: { 31 | ...compilerOptions, 32 | allowNonTsExtensions: true 33 | } 34 | }; 35 | 36 | export default { 37 | input: "src/main.js", 38 | output: { 39 | sourcemap: true, 40 | format: "iife", 41 | name: "app", 42 | file: "public/bundle.js" 43 | }, 44 | plugins: [ 45 | svelte({ 46 | // enable run-time checks when not in production 47 | dev: !production, 48 | // we'll extract any component CSS out into 49 | // a separate file — better for performance 50 | css: css => { 51 | css.write("public/bundle.css"); 52 | }, 53 | preprocess: preprocess(opts) 54 | }), 55 | 56 | // If you have external dependencies installed from 57 | // npm, you'll most likely need these plugins. In 58 | // some cases you'll need additional configuration — 59 | // consult the documentation for details: 60 | // https://github.com/rollup/rollup-plugin-commonjs 61 | resolve(), 62 | commonjs(), 63 | typescript(), 64 | 65 | // If we're building for production (npm run build 66 | // instead of npm run dev), minify 67 | production && terser() 68 | ] 69 | }; 70 | ``` 71 | -------------------------------------------------------------------------------- /packages/preprocess/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/preprocess/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pyoner/svelte-ts-preprocess", 3 | "version": "1.3.0", 4 | "description": "Typescript preprocessor for Svelte 3", 5 | "keywords": [ 6 | "svelte", 7 | "svelte3", 8 | "preprocess", 9 | "typescript" 10 | ], 11 | "main": "dist/lib/svelte-ts-preprocess.js", 12 | "typings": "dist/types/svelte-ts-preprocess.d.ts", 13 | "files": [ 14 | "dist" 15 | ], 16 | "author": "Jungle ", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/pyoner/svelte-typescript" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/pyoner/svelte-typescript/issues" 23 | }, 24 | "homepage": "https://github.com/pyoner/svelte-typescript", 25 | "license": "MIT", 26 | "engines": { 27 | "node": ">=6.0.0" 28 | }, 29 | "scripts": { 30 | "lint": "tslint --project tsconfig.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'", 31 | "prebuild": "rimraf dist", 32 | "build": "tsc -p ./tsconfig.json", 33 | "start": "tsc -w", 34 | "test": "jest --coverage", 35 | "test:watch": "jest --coverage --watch", 36 | "test:prod": "npm run lint && npm run test -- --no-cache", 37 | "deploy-docs": "ts-node tools/gh-pages-publish", 38 | "report-coverage": "cat ./coverage/lcov.info | coveralls", 39 | "commit": "git-cz", 40 | "semantic-release": "semantic-release", 41 | "semantic-release-prepare": "ts-node tools/semantic-release-prepare", 42 | "precommit": "lint-staged", 43 | "travis-deploy-once": "travis-deploy-once" 44 | }, 45 | "lint-staged": { 46 | "{src,test}/**/*.ts": [ 47 | "prettier --write", 48 | "git add" 49 | ] 50 | }, 51 | "config": {}, 52 | "jest": { 53 | "globals": { 54 | "ts-jest": { 55 | "tsConfig": "tsconfig.json" 56 | } 57 | }, 58 | "transform": { 59 | ".(ts|tsx)": "ts-jest" 60 | }, 61 | "testEnvironment": "node", 62 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", 63 | "moduleFileExtensions": [ 64 | "ts", 65 | "tsx", 66 | "js" 67 | ], 68 | "coveragePathIgnorePatterns": [ 69 | "/node_modules/", 70 | "/test/" 71 | ], 72 | "coverageThreshold": { 73 | "global": { 74 | "branches": 90, 75 | "functions": 95, 76 | "lines": 95, 77 | "statements": 95 78 | } 79 | }, 80 | "collectCoverageFrom": [ 81 | "src/*.{js,ts}" 82 | ] 83 | }, 84 | "prettier": { 85 | "semi": false, 86 | "singleQuote": true 87 | }, 88 | "commitlint": { 89 | "extends": [ 90 | "@commitlint/config-conventional" 91 | ] 92 | }, 93 | "devDependencies": { 94 | "@commitlint/cli": "^7.1.2", 95 | "@commitlint/config-conventional": "^7.1.2", 96 | "@types/node": "^11.13.6", 97 | "colors": "^1.3.2", 98 | "commitizen": "^3.0.0", 99 | "coveralls": "^3.0.2", 100 | "cross-env": "^5.2.0", 101 | "cz-conventional-changelog": "^2.1.0", 102 | "jest": "^24.9.0", 103 | "jest-config": "^24.9.0", 104 | "lint-staged": "^8.0.0", 105 | "lodash.camelcase": "^4.3.0", 106 | "prettier": "^1.14.3", 107 | "prompt": "^1.0.0", 108 | "replace-in-file": "^4.0.0", 109 | "rimraf": "^2.6.2", 110 | "semantic-release": "^15.9.16", 111 | "shelljs": "^0.8.3", 112 | "travis-deploy-once": "^5.0.9", 113 | "ts-jest": "^24.1.0", 114 | "ts-node": "^8.1.0", 115 | "tslint": "^5.11.0", 116 | "tslint-config-prettier": "^1.15.0", 117 | "tslint-config-standard": "^8.0.1", 118 | "typedoc": "^0.14.2" 119 | }, 120 | "peerDependencies": { 121 | "typescript": "^3.8" 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /packages/preprocess/src/svelte-ts-preprocess.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | import ts from 'typescript' 4 | 5 | const LANGS = ['ts', 'typescript'] 6 | 7 | function importTransformer(): ts.TransformerFactory { 8 | return context => { 9 | const visit: ts.Visitor = node => { 10 | if (ts.isImportDeclaration(node)) { 11 | if (node.importClause?.isTypeOnly) { 12 | return node 13 | } 14 | 15 | return ts.createImportDeclaration( 16 | node.decorators, 17 | node.modifiers, 18 | node.importClause, 19 | node.moduleSpecifier 20 | ) 21 | } 22 | return ts.visitEachChild(node, child => visit(child), context) 23 | } 24 | 25 | return node => ts.visitNode(node, visit) 26 | } 27 | } 28 | 29 | function isSvelteImport(d: ts.Diagnostic) { 30 | return ( 31 | d.code === 2307 && typeof d.messageText === 'string' && /\.svelte['"]\.$/.test(d.messageText) 32 | ) 33 | } 34 | 35 | function clearDiagnostics(diagnostics: ReadonlyArray) { 36 | return diagnostics.filter(d => !isSvelteImport(d)) 37 | } 38 | 39 | function createFormatDiagnosticsHost(cwd: string): ts.FormatDiagnosticsHost { 40 | return { 41 | getCanonicalFileName: fileName => fileName, 42 | getCurrentDirectory: () => cwd, 43 | getNewLine: () => ts.sys.newLine 44 | } 45 | } 46 | 47 | interface File { 48 | name: string 49 | content: string 50 | } 51 | 52 | function createProxyHost(host: ts.CompilerHost, file: File) { 53 | const proxy: ts.CompilerHost = { 54 | getSourceFile( 55 | filename: string, 56 | languageVersion: ts.ScriptTarget, 57 | _onError?: (message: string) => void 58 | ) { 59 | filename = ts.sys.resolvePath(filename) 60 | return filename === file.name 61 | ? ts.createSourceFile(file.name, file.content, languageVersion) 62 | : host.getSourceFile(filename, languageVersion, _onError) 63 | }, 64 | 65 | writeFile: (_filename, _content) => { 66 | throw new Error('unsupported') 67 | }, 68 | 69 | getCanonicalFileName(filename) { 70 | filename = ts.sys.resolvePath(filename) 71 | return filename === file.name 72 | ? ts.sys.useCaseSensitiveFileNames 73 | ? filename 74 | : filename.toLowerCase() 75 | : host.getCanonicalFileName(filename) 76 | }, 77 | 78 | fileExists(filename) { 79 | filename = ts.sys.resolvePath(filename) 80 | return filename === file.name ? true : host.fileExists(filename) 81 | }, 82 | 83 | readFile(filename) { 84 | filename = ts.sys.resolvePath(filename) 85 | return filename === file.name ? file.content : host.readFile(filename) 86 | }, 87 | 88 | getDefaultLibFileName: host.getDefaultLibFileName.bind(host), 89 | getCurrentDirectory: host.getCurrentDirectory.bind(host), 90 | getNewLine: host.getNewLine.bind(host), 91 | useCaseSensitiveFileNames: host.useCaseSensitiveFileNames.bind(host), 92 | resolveModuleNames: host.resolveModuleNames && host.resolveModuleNames.bind(host), 93 | getDirectories: host.getDirectories && host.getDirectories.bind(host) 94 | } 95 | return proxy 96 | } 97 | 98 | interface Script { 99 | filename: string 100 | content: string 101 | attributes: { 102 | lang?: string 103 | src?: string 104 | } 105 | } 106 | 107 | export const defaultCompilerOptions: ts.CompilerOptions = { 108 | target: ts.ScriptTarget.ESNext, 109 | module: ts.ModuleKind.ESNext, 110 | moduleResolution: ts.ModuleResolutionKind.NodeJs, 111 | allowNonTsExtensions: true, 112 | alwaysStrict: false 113 | } 114 | 115 | export interface Env { 116 | basePath: string 117 | formatDiagnosticHost: ts.FormatDiagnosticsHost 118 | } 119 | 120 | export function createEnv(basePath?: string): Env { 121 | basePath = basePath ? basePath : process.cwd() 122 | const formatDiagnosticHost = createFormatDiagnosticsHost(basePath) 123 | return { basePath, formatDiagnosticHost } 124 | } 125 | 126 | export function readConfigFile(env: Env, path?: string) { 127 | const configPath = path ? path : ts.findConfigFile(env.basePath, ts.sys.fileExists) 128 | if (!configPath) { 129 | throw new Error("Could not find a valid 'tsconfig.json'.") 130 | } 131 | 132 | // read config 133 | const result = ts.readConfigFile(configPath, ts.sys.readFile) 134 | if (result.error) { 135 | const msg = ts.formatDiagnostics([result.error], env.formatDiagnosticHost) 136 | throw new Error(msg) 137 | } 138 | 139 | const { config } = result 140 | const settings = ts.convertCompilerOptionsFromJson(config.compilerOptions, env.basePath) 141 | if (!settings.options) { 142 | const msg = ts.formatDiagnostics(settings.errors, env.formatDiagnosticHost) 143 | throw new Error(msg) 144 | } 145 | 146 | return settings.options 147 | } 148 | 149 | export interface PreprocessOptions { 150 | compilerOptions: ts.CompilerOptions 151 | env: Env 152 | hideErrors: boolean 153 | } 154 | 155 | export function createPreprocessOptions(opts?: Partial): PreprocessOptions { 156 | opts = opts ? opts : {} 157 | 158 | return { 159 | compilerOptions: opts.compilerOptions ? opts.compilerOptions : defaultCompilerOptions, 160 | env: opts.env ? opts.env : createEnv(), 161 | hideErrors: !!opts.hideErrors 162 | } 163 | } 164 | 165 | export function preprocess(opts?: Partial) { 166 | function script({ content, attributes, filename }: Script) { 167 | if (!attributes.lang) { 168 | return 169 | } 170 | 171 | const lang = attributes.lang.toLowerCase() 172 | if (!LANGS.includes(lang)) { 173 | return 174 | } 175 | 176 | if (attributes.src) { 177 | const dir = path.parse(filename).dir 178 | filename = path.join(dir, attributes.src) 179 | content = fs.readFileSync(filename).toString() 180 | } 181 | 182 | filename = ts.sys.resolvePath(filename) 183 | const options = createPreprocessOptions(opts) 184 | 185 | const rootFiles = [filename] 186 | const proxyHost = createProxyHost(ts.createCompilerHost(options.compilerOptions), { 187 | name: filename, 188 | content 189 | }) 190 | 191 | let code = '' 192 | const writeFile: ts.WriteFileCallback = (fileName, data) => { 193 | // console.log(fileName) 194 | // console.log(data) 195 | if (fileName.endsWith('.js')) { 196 | code = data 197 | } 198 | } 199 | 200 | const customTransformers: ts.CustomTransformers = { 201 | before: [importTransformer()] 202 | } 203 | 204 | const program = ts.createProgram(rootFiles, options.compilerOptions, proxyHost) 205 | program.emit(undefined, writeFile, undefined, undefined, customTransformers) 206 | 207 | if (!options.hideErrors) { 208 | const diagnostics = clearDiagnostics(ts.getPreEmitDiagnostics(program)) 209 | if (diagnostics.length) { 210 | const s = ts.formatDiagnosticsWithColorAndContext( 211 | diagnostics, 212 | options.env.formatDiagnosticHost 213 | ) 214 | console.log(s) 215 | } 216 | } 217 | 218 | return { code } 219 | } 220 | return { script } 221 | } 222 | -------------------------------------------------------------------------------- /packages/preprocess/test/svelte-ts-preprocess.test.ts: -------------------------------------------------------------------------------- 1 | import { preprocess } from '../src/svelte-ts-preprocess' 2 | 3 | describe('preprocess test', () => { 4 | const opts = { hideErrors: true } 5 | 6 | it('should be function', () => { 7 | expect(preprocess).toBeInstanceOf(Function) 8 | }) 9 | 10 | it('returns object with "script" property', () => { 11 | expect(preprocess(opts)).toHaveProperty('script') 12 | }) 13 | 14 | it('run preprocess', () => { 15 | // const code = `` 16 | const content = `//comment 17 | import Form from './Form.svelte'; 18 | 19 | function x(){return 5;} 20 | console.log(x()) 21 | let c: number = 5; 22 | ` 23 | const filename = 'Component.svelte' 24 | const attributes = { 25 | lang: 'ts' 26 | } 27 | const result = preprocess(opts).script({ 28 | content, 29 | filename, 30 | attributes 31 | }) 32 | expect(result).toHaveProperty('code') 33 | }) 34 | 35 | it('should preserve all imports', () => { 36 | const content = `import Form from './Form.svelte'; 37 | import x from 'x-lib'; 38 | ` 39 | const filename = 'Component.svelte' 40 | const attributes = { 41 | lang: 'ts' 42 | } 43 | const result = preprocess(opts).script({ 44 | content, 45 | filename, 46 | attributes 47 | }) 48 | expect(result).toHaveProperty('code', content) 49 | }) 50 | 51 | it('should remove types imports', () => { 52 | const content = `import Form from './Form.svelte'; 53 | import type x from 'x-lib'; 54 | let a: x = 5; 55 | ` 56 | const expected = `import Form from './Form.svelte'; 57 | let a = 5; 58 | ` 59 | const filename = 'Component.svelte' 60 | const attributes = { 61 | lang: 'ts' 62 | } 63 | const result = preprocess(opts).script({ 64 | content, 65 | filename, 66 | attributes 67 | }) 68 | expect(result).toHaveProperty('code', expected) 69 | }) 70 | 71 | it('should hide errors', () => { 72 | const content = `import Form from './Form.svelte'; 73 | import x from 'x-lib'; 74 | ` 75 | const filename = 'Component.svelte' 76 | const attributes = { 77 | lang: 'ts' 78 | } 79 | const opts = { hideErrors: true } 80 | const result = preprocess(opts).script({ 81 | content, 82 | filename, 83 | attributes 84 | }) 85 | expect(result).toHaveProperty('code', content) 86 | }) 87 | 88 | it('should support external .ts files', () => { 89 | const content = '' 90 | const filename = 'Component.svelte' 91 | const attributes = { 92 | lang: 'ts', 93 | src: 'src/svelte-ts-preprocess.ts' 94 | } 95 | const result = preprocess(opts).script({ 96 | content, 97 | filename, 98 | attributes 99 | }) 100 | expect(result).toHaveProperty('code') 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /packages/preprocess/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name "Jungle"') 26 | exec('git config user.email "devex.soft@gmail.com"') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/preprocess/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "commitlint -E HUSKY_GIT_PARAMS" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "lib", "installer", 'bin'), ['install']) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/preprocess/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"commonjs", 6 | "strict": true, 7 | "sourceMap": true, 8 | "declaration": true, 9 | "allowSyntheticDefaultImports": true, 10 | "experimentalDecorators": true, 11 | "emitDecoratorMetadata": true, 12 | "esModuleInterop": true, 13 | "declarationDir": "dist/types", 14 | "outDir": "dist/lib", 15 | "typeRoots": [ 16 | "node_modules/@types", 17 | "../../node_modules/@types" 18 | ] 19 | }, 20 | "include": [ 21 | "src" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/preprocess/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/sapper-template/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules/ 3 | /src/node_modules/@sapper/ 4 | yarn-error.log 5 | /cypress/screenshots/ 6 | /__sapper__/ 7 | .rpt2_cache 8 | -------------------------------------------------------------------------------- /packages/sapper-template/README.md: -------------------------------------------------------------------------------- 1 | # sapper-template 2 | 3 | ## Install 4 | 5 | ### For Linux users 6 | ```bash 7 | mkdir sapper-app 8 | curl -L https://github.com/pyoner/svelte-typescript/tarball/master > svelte-typescript.tar 9 | tar --strip-components=3 --wildcards --one-top-level=sapper-app -xf svelte-typescript.tar */packages/sapper-template 10 | ``` 11 | 12 | ### For Mac users 13 | ```zsh 14 | mkdir sapper-app 15 | curl -L https://github.com/pyoner/svelte-typescript/tarball/master > svelte-typescript.tar 16 | tar --strip-components=3 -C sapper-app -xf svelte-typescript.tar '*/packages/sapper-template/' 17 | ``` 18 | 19 | ### For Windows users 20 | Download https://github.com/pyoner/svelte-typescript/archive/master.zip and extract template from `packages/sapper-template` 21 | 22 | ## Usage 23 | 24 | ```bash 25 | cd sapper-app 26 | npm install # or yarn! 27 | npm run dev 28 | ``` 29 | 30 | Open up [localhost:3000](http://localhost:3000) and start clicking around. 31 | 32 | Consult [sapper.svelte.dev](https://sapper.svelte.dev) for help getting started. 33 | 34 | 35 | ## Structure 36 | 37 | Sapper expects to find two directories in the root of your project — `src` and `static`. 38 | 39 | 40 | ### src 41 | 42 | The [src](src) directory contains the entry points for your app — `client.js`, `server.js` and (optionally) a `service-worker.js` — along with a `template.html` file and a `routes` directory. 43 | 44 | 45 | #### src/routes 46 | 47 | This is the heart of your Sapper app. There are two kinds of routes — *pages*, and *server routes*. 48 | 49 | **Pages** are Svelte components written in `.svelte` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel. (Sapper will preload and cache the code for these subsequent pages, so that navigation is instantaneous.) 50 | 51 | **Server routes** are modules written in `.js` files, that export functions corresponding to HTTP methods. Each function receives Express `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API, for example. 52 | 53 | There are three simple rules for naming the files that define your routes: 54 | 55 | * A file called `src/routes/about.svelte` corresponds to the `/about` route. A file called `src/routes/blog/[slug].svelte` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to the route 56 | * The file `src/routes/index.svelte` (or `src/routes/index.js`) corresponds to the root of your app. `src/routes/about/index.svelte` is treated the same as `src/routes/about.svelte`. 57 | * Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `src/routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route 58 | 59 | 60 | ### static 61 | 62 | The [static](static) directory contains any static assets that should be available. These are served using [sirv](https://github.com/lukeed/sirv). 63 | 64 | In your [service-worker.js](app/service-worker.js) file, you can import these as `files` from the generated manifest... 65 | 66 | ```js 67 | import { files } from '@sapper/service-worker'; 68 | ``` 69 | 70 | ...so that you can cache them (though you can choose not to, for example if you don't want to cache very large files). 71 | 72 | 73 | ## Bundler config 74 | 75 | Sapper uses Rollup or webpack to provide code-splitting and dynamic imports, as well as compiling your Svelte components. With webpack, it also provides hot module reloading. As long as you don't do anything daft, you can edit the configuration files to add whatever plugins you'd like. 76 | 77 | 78 | ## Production mode and deployment 79 | 80 | To start a production version of your app, run `npm run build && npm start`. This will disable live reloading, and activate the appropriate bundler plugins. 81 | 82 | You can deploy your application to any environment that supports Node 8 or above. As an example, to deploy to [Now](https://zeit.co/now), run these commands: 83 | 84 | ```bash 85 | npm install -g now 86 | now 87 | ``` 88 | 89 | 90 | ## Using external components with webpack 91 | 92 | When using Svelte components installed from npm, such as [@sveltejs/svelte-virtual-list](https://github.com/sveltejs/svelte-virtual-list), Svelte needs the original component source (rather than any precompiled JavaScript that ships with the component). This allows the component to be rendered server-side, and also keeps your client-side app smaller. 93 | 94 | Because of that, it's essential that webpack doesn't treat the package as an *external dependency*. You can either modify the `externals` option under `server` in [webpack.config.js](webpack.config.js), or simply install the package to `devDependencies` rather than `dependencies`, which will cause it to get bundled (and therefore compiled) with your app: 95 | 96 | ```bash 97 | npm install -D @sveltejs/svelte-virtual-list 98 | ``` 99 | 100 | 101 | ## Bugs and feedback 102 | 103 | Sapper is in early development, and may have the odd rough edge here and there. Please be vocal over on the [Sapper issue tracker](https://github.com/sveltejs/sapper/issues). 104 | -------------------------------------------------------------------------------- /packages/sapper-template/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | shallow_clone: true 4 | 5 | init: 6 | - git config --global core.autocrlf false 7 | 8 | build: off 9 | 10 | environment: 11 | matrix: 12 | # node.js 13 | - nodejs_version: stable 14 | 15 | install: 16 | - ps: Install-Product node $env:nodejs_version 17 | - npm install cypress 18 | - npm install 19 | -------------------------------------------------------------------------------- /packages/sapper-template/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:3000", 3 | "video": false 4 | } -------------------------------------------------------------------------------- /packages/sapper-template/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } -------------------------------------------------------------------------------- /packages/sapper-template/cypress/integration/spec.js: -------------------------------------------------------------------------------- 1 | describe('Sapper template app', () => { 2 | beforeEach(() => { 3 | cy.visit('/') 4 | }); 5 | 6 | it('has the correct

', () => { 7 | cy.contains('h1', 'Great success!') 8 | }); 9 | 10 | it('navigates to /about', () => { 11 | cy.get('nav a').contains('about').click(); 12 | cy.url().should('include', '/about'); 13 | }); 14 | 15 | it('navigates to /blog', () => { 16 | cy.get('nav a').contains('blog').click(); 17 | cy.url().should('include', '/blog'); 18 | }); 19 | }); -------------------------------------------------------------------------------- /packages/sapper-template/cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | module.exports = (on, config) => { 15 | // `on` is used to hook into various events Cypress emits 16 | // `config` is the resolved Cypress config 17 | } 18 | -------------------------------------------------------------------------------- /packages/sapper-template/cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /packages/sapper-template/cypress/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /packages/sapper-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "sapper-template", 4 | "description": "Sapper", 5 | "version": "0.0.1", 6 | "scripts": { 7 | "dev": "sapper dev", 8 | "build": "sapper build --legacy", 9 | "export": "sapper export --legacy", 10 | "start": "node __sapper__/build", 11 | "cy:run": "cypress run", 12 | "cy:open": "cypress open", 13 | "test": "run-p --race dev cy:run" 14 | }, 15 | "dependencies": { 16 | "compression": "^1.7.1", 17 | "polka": "^0.5.0", 18 | "sirv": "^0.4.0" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.0.0", 22 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 23 | "@babel/plugin-transform-runtime": "^7.0.0", 24 | "@babel/preset-env": "^7.0.0", 25 | "@babel/runtime": "^7.0.0", 26 | "@pyoner/svelte-nossr-preprocess": "^1.0.1", 27 | "@pyoner/svelte-ts-preprocess": "^1.3.0", 28 | "@rollup/plugin-commonjs": "^13.0.0", 29 | "@rollup/plugin-json": "^4.0.2", 30 | "@rollup/plugin-node-resolve": "^7.1.1", 31 | "@types/node": "^12.0.8", 32 | "@wessberg/rollup-plugin-ts": "^1.2.13", 33 | "npm-run-all": "^4.1.5", 34 | "rollup": "^2.19.0", 35 | "rollup-plugin-babel": "^4.0.2", 36 | "rollup-plugin-replace": "^2.0.0", 37 | "rollup-plugin-svelte": "^5.0.1", 38 | "rollup-plugin-terser": "^4.0.4", 39 | "sapper": "^0.27.0", 40 | "svelte": "^3.12.1", 41 | "typescript": "^3.4.5" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/sapper-template/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from "@rollup/plugin-node-resolve"; 2 | import replace from "rollup-plugin-replace"; 3 | import commonjs from "@rollup/plugin-commonjs"; 4 | import json from "@rollup/plugin-json"; 5 | import svelte from "rollup-plugin-svelte"; 6 | import babel from "rollup-plugin-babel"; 7 | import { terser } from "rollup-plugin-terser"; 8 | import typescript from "@wessberg/rollup-plugin-ts"; 9 | import config from "sapper/config/rollup.js"; 10 | import pkg from "./package.json"; 11 | import { nossr } from "@pyoner/svelte-nossr-preprocess"; 12 | 13 | const svelteOptions = require("./svelte.config"); 14 | const sveltePreprocessors = [nossr(), svelteOptions.preprocess]; 15 | 16 | const production = !process.env.ROLLUP_WATCH; 17 | 18 | const mode = process.env.NODE_ENV; 19 | const dev = mode === "development"; 20 | const legacy = !!process.env.SAPPER_LEGACY_BUILD; 21 | 22 | const onwarn = (warning, onwarn) => 23 | (warning.code === "CIRCULAR_DEPENDENCY" && 24 | /[/\\]@sapper[/\\]/.test(warning.message)) || 25 | onwarn(warning); 26 | 27 | export default { 28 | client: { 29 | input: config.client.input(), 30 | output: config.client.output(), 31 | plugins: [ 32 | replace({ 33 | "process.browser": true, 34 | "process.env.NODE_ENV": JSON.stringify(mode) 35 | }), 36 | json(), 37 | svelte({ 38 | ...svelteOptions, 39 | dev, 40 | hydratable: true, 41 | emitCss: true 42 | }), 43 | resolve({ 44 | browser: true 45 | }), 46 | commonjs(), 47 | typescript(), 48 | 49 | legacy && 50 | babel({ 51 | extensions: [".js", ".mjs", ".html", ".svelte"], 52 | runtimeHelpers: true, 53 | exclude: ["node_modules/@babel/**"], 54 | presets: [ 55 | [ 56 | "@babel/preset-env", 57 | { 58 | targets: "> 0.25%, not dead" 59 | } 60 | ] 61 | ], 62 | plugins: [ 63 | "@babel/plugin-syntax-dynamic-import", 64 | [ 65 | "@babel/plugin-transform-runtime", 66 | { 67 | useESModules: true 68 | } 69 | ] 70 | ] 71 | }), 72 | 73 | !dev && 74 | terser({ 75 | module: true 76 | }) 77 | ], 78 | 79 | onwarn 80 | }, 81 | 82 | server: { 83 | input: config.server.input(), 84 | output: config.server.output(), 85 | plugins: [ 86 | replace({ 87 | "process.browser": false, 88 | "process.env.NODE_ENV": JSON.stringify(mode) 89 | }), 90 | svelte({ 91 | preprocess: sveltePreprocessors, 92 | generate: "ssr", 93 | dev 94 | }), 95 | resolve(), 96 | commonjs(), 97 | typescript() 98 | ], 99 | external: Object.keys(pkg.dependencies).concat( 100 | require("module").builtinModules || 101 | Object.keys(process.binding("natives")) 102 | ), 103 | 104 | onwarn 105 | }, 106 | 107 | serviceworker: { 108 | input: config.serviceworker.input(), 109 | output: config.serviceworker.output(), 110 | plugins: [ 111 | resolve(), 112 | replace({ 113 | "process.browser": true, 114 | "process.env.NODE_ENV": JSON.stringify(mode) 115 | }), 116 | commonjs(), 117 | !dev && terser() 118 | ], 119 | 120 | onwarn 121 | } 122 | }; 123 | -------------------------------------------------------------------------------- /packages/sapper-template/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); -------------------------------------------------------------------------------- /packages/sapper-template/src/components/Counter.svelte: -------------------------------------------------------------------------------- 1 |
2 | Default Counter 3 |
4 | {value} 5 | 6 | 7 |
8 |
9 | 10 | 14 | -------------------------------------------------------------------------------- /packages/sapper-template/src/components/Nav.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 50 | 51 | 75 | -------------------------------------------------------------------------------- /packages/sapper-template/src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 29 | 30 | 31 | {status} 32 | 33 | 34 |

{status}

35 | 36 |

{error.message}

37 | 38 | {#if dev && error.stack} 39 |
{error.stack}
40 | {/if} 41 | -------------------------------------------------------------------------------- /packages/sapper-template/src/routes/_layout.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 |