Skip to content

Instantly share code, notes, and snippets.

@robertfairley
Last active November 8, 2017 04:13
Show Gist options
  • Save robertfairley/8dae0dfbabceeb199cf5d01f26f5cda3 to your computer and use it in GitHub Desktop.
Save robertfairley/8dae0dfbabceeb199cf5d01f26f5cda3 to your computer and use it in GitHub Desktop.
A very basic typescript app generator

ts-init

A very basic typescript app generator. Builds a bare-bones basic set of files for a TypeScript front-end web app.


Install

Copy and paste this code to a file in your PATH without any extension, or remove the hashbang and run with Python.

Requirements

This script will work on macOS and Linux systems with Python and NodeJS installed.

Run

Make sure the script has executable priveleges and run ts-init from your terminal (or whatever you named the file) if relying on the hashbang. Otherwise use Python and run python ts-init.py (adding the file extension).

It will prompt you for a filename or fall back on a default if you decide not to pass one.

#!/usr/bin/env python
import re
import sys
import subprocess
# GLOBALS
PROMPT = "[ ES5 INIT ]"
TEMPLATE = {
"html": """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=0, initial-scale=1.0" />
[TITLEPLACEHOLDER]
<link rel="stylesheet" href="public/app.css" />
</head>
<body>
<main id="root" role="main"></main>
<script src="public/app.js"></script>
</body>
</html>
""",
"css": """
html, body {
appearance: none;
margin: 1em;
padding: 0;
font-family: "Gill Sans", -apple-system, "Helvetica Neue", "Helvetica", "Verdana", sans-serif;
font-weight: 100;
background-color: #eee;
color: #121212;
}
html > *, body > * {
appearance: none;
}
h1 {
font-weight: 200;
}
a {
color: #121212;
}
a:active {
color: #121212;
}
button {
appearance: none;
border-radius: 0;
padding: 10px 15px;
background-color: #2222ee;
color: #fff;
box-sizing: border-box;
border: 2px solid #2222ee;
transition: 300ms all ease;
user-select: none;
}
button:hover {
background-color: #2222ff;
}
button:active {
background-color: #2222dd;
}
button:focus {
border: 2px dashed #eee;
outline: 0;
}
""",
"typescript": """
type EL = {
main: HTMLElement
};
const el: EL = {
main: document.querySelector("#root"),
};
el.main.innerHTML = `
<h1>TypeScript to ES5 App - Browser Friendly!</h1>
<p>This is your new Typescript -> ES5 app compiled with webpack!</p>
`
""",
"webpack": """
module.exports = {
entry: "./src/index.ts",
output: {
filename: "app.js",
path: __dirname + "/public"
},
devtool: "source-map",
resolve: {
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
rules: [
{ test: /\.tsx?$/, loader: "awesome-typescript-loader", exclude: /node_modules/ },
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader", exclude: /node_modules/ }
]
}
};
""",
"package_json": """
{
"name": "",
"version": "0.0.1",
"description": "[ fill this in ]",
"main": "app.js",
"scripts": {
"build": "webpack --progress",
"watch": "webpack --progress --watch",
"start": "serve -p 6060"
},
"devDependencies": {
"typescript": "latest",
"webpack": "latest",
"awesome-typescript-loader": "latest",
"source-map-loader": "latest"
}
}
""",
"tsconfig_json": """
{
"compilerOptions": {
"outDir": "./public/",
"allowJs": true,
"target": "es5"
},
"include": {
"./src/**/*"
}
}
"""
}
def log(msg = None, file_name = None):
if (msg == None):
print ("%s File written: `%s`" % (PROMPT, file_name))
elif (file_name == None):
print ("%s %s" % (PROMPT, msg))
else:
print("%s %s: %s" % (PROMPT, msg, file_name))
def setup_modules():
subprocess.call(["npm", "install"])
def setup_npm():
filename = "package.json"
with open(filename, "w+") as fin:
fin.write(TEMPLATE["package_json"])
log(None, filename)
def setup_tsconfig():
filename = "tsconfig.json"
with open(filename, "w+") as fin:
fin.write(TEMPLATE["tsconfig_json"])
log(None, filename)
def setup_webpack():
filename = "webpack.config.js"
with open(filename, "w+") as fin:
fin.write(TEMPLATE["webpack"])
log(None, filename)
def setup_html(title):
filename = "index.html"
with open(filename, "w+") as fin:
title_replacement = "<title>%s</title>" % title
html_file_str = re.sub(r"(\[TITLEPLACEHOLDER\])", title_replacement, TEMPLATE["html"])
fin.write(html_file_str)
log(None, filename)
def setup_css():
subprocess.call(["mkdir", "public"])
filename = "app.css"
dir = "./public/"
with open(dir+filename, "w+") as fin:
fin.write(TEMPLATE["css"])
log(None, dir+filename)
def setup_typescript():
subprocess.call(["mkdir", "src"])
filename = "./src/index.ts"
with open(filename, "w+") as fin:
fin.write(TEMPLATE["typescript"])
log(None, filename)
subprocess.call(["npm", "run", "build"])
def main():
TITLE = raw_input("Enter a title for your application:\n>>> ")
if TITLE == None:
TITLE = "Typescript App"
setup_npm()
setup_tsconfig()
setup_modules()
setup_webpack()
setup_html(TITLE)
setup_css()
setup_typescript()
print ("%s Done!" % PROMPT)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment