Skip to content
This repository was archived by the owner on Feb 15, 2023. It is now read-only.

Commit 9b2a107

Browse files
ortadummdidummRich-Harris
authored
Adds a setup TypeScript script, and docs in the README (#140)
* Adds a setup TypeScript script, and docs in the README * Adds a CTA to the TS script * Update scripts/setupTypeScript.js Co-authored-by: Simon H <[email protected]> * Fix README * emphasise that the script should be run immediately Co-authored-by: Simon H <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent 752c770 commit 9b2a107

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ If you're building a single-page app (SPA) with multiple routes, sirv needs to b
5757
"start": "sirv public --single"
5858
```
5959

60+
## Using TypeScript
61+
62+
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
63+
64+
```bash
65+
node scripts/setupTypeScript.js
66+
```
67+
68+
Or remove the script via:
69+
70+
```bash
71+
rm scripts/setupTypeScript.js
72+
```
6073

6174
## Deploying to the web
6275

scripts/setupTypeScript.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// @ts-check
2+
3+
/** This script modifies the project to support TS code in .svelte files like:
4+
5+
<script lang="ts">
6+
export let name: string;
7+
</script>
8+
9+
As well as validating the code for CI.
10+
*/
11+
12+
/** To work on this script:
13+
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
14+
*/
15+
16+
const fs = require("fs")
17+
const path = require("path")
18+
const { argv } = require("process")
19+
20+
const projectRoot = argv[2] || path.join(__dirname, "..")
21+
22+
// Add deps to pkg.json
23+
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
24+
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
25+
"svelte-check": "^0.1.0",
26+
"svelte-preprocess": "^4.0.0",
27+
"@rollup/plugin-typescript": "^4.0.0",
28+
"typescript": "^3.9.3",
29+
"tslib": "^2.0.0",
30+
"@tsconfig/svelte": "^1.0.0"
31+
})
32+
33+
// Add script for checking
34+
packageJSON.scripts = Object.assign(packageJSON.scripts, {
35+
"validate": "svelte-check"
36+
})
37+
38+
// Write the package JSON
39+
fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " "))
40+
41+
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
42+
const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
43+
const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
44+
fs.renameSync(beforeMainJSPath, afterMainTSPath)
45+
46+
// Switch the app.svelte file to use TS
47+
const appSveltePath = path.join(projectRoot, "src", "App.svelte")
48+
let appFile = fs.readFileSync(appSveltePath, "utf8")
49+
appFile = appFile.replace("<script>", '<script lang="ts">')
50+
appFile = appFile.replace("export let name;", 'export let name: string;')
51+
fs.writeFileSync(appSveltePath, appFile)
52+
53+
// Edit rollup config
54+
const rollupConfigPath = path.join(projectRoot, "rollup.config.js")
55+
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8")
56+
57+
// Edit imports
58+
rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
59+
import sveltePreprocess from 'svelte-preprocess';
60+
import typescript from '@rollup/plugin-typescript';`)
61+
62+
// Replace name of entry point
63+
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
64+
65+
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
66+
// Instead we look for `css:` then the next `}` and add the preprocessor to that
67+
let foundCSS = false
68+
let match
69+
70+
// https://regex101.com/r/OtNjwo/1
71+
const configEditor = new RegExp(/css:.|\n*}/gmi)
72+
while (( match = configEditor.exec(rollupConfig)) != null) {
73+
if (foundCSS) {
74+
const endOfCSSIndex = match.index + 1
75+
rollupConfig = rollupConfig.slice(0, endOfCSSIndex) + ",\n preprocess: sveltePreprocess()," + rollupConfig.slice(endOfCSSIndex);
76+
break
77+
}
78+
if (match[0].includes("css:")) foundCSS = true
79+
}
80+
81+
82+
// Add TypeScript
83+
rollupConfig = rollupConfig.replace("commonjs(),", 'commonjs(),\n\t\ttypescript({ sourceMap: !production }),')
84+
fs.writeFileSync(rollupConfigPath, rollupConfig)
85+
86+
// Add TSConfig
87+
const tsconfig = `{
88+
"extends": "@tsconfig/svelte/tsconfig.json",
89+
90+
"include": ["src/**/*"],
91+
"exclude": ["node_modules/*", "__sapper__/*", "public/*"],
92+
}`
93+
const tsconfigPath = path.join(projectRoot, "tsconfig.json")
94+
fs.writeFileSync(tsconfigPath, tsconfig)
95+
96+
// Delete this script, but not during testing
97+
if (!argv[2]) {
98+
// Remove the script
99+
fs.unlinkSync(path.join(__filename))
100+
// Remove the scripts folder
101+
fs.rmdirSync(path.join(__dirname))
102+
}
103+
104+
// Adds the extension recommendation
105+
fs.mkdirSync(path.join(projectRoot, ".vscode"))
106+
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
107+
"recommendations": ["svelte.svelte-vscode"]
108+
}
109+
`)
110+
111+
console.log("Converted to TypeScript.")
112+
113+
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
114+
console.log("\nYou will need to re-run your dependency manager to get started.")
115+
}

0 commit comments

Comments
 (0)