Last active
January 29, 2023 03:19
-
-
Save guiseek/b97e20d98da05a5057a079d6c91b880c to your computer and use it in GitHub Desktop.
Comandos pra começar um projeto simples usando TypeScript + HTML + ESBuild, usando Shell Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Para usar, dê permissão de execução ao script | |
# usando o comando: chmod +x create-project.sh | |
# e então execute: ./create-project.sh projeto | |
mkdir $1 | |
cd $1 | |
npm init -y | |
echo '{ | |
"compilerOptions": { | |
"target": "es5", | |
"lib": [ | |
"es2020", | |
"dom", | |
"dom.iterable" | |
], | |
"experimentalDecorators": true, | |
"emitDecoratorMetadata": true, | |
"module": "commonjs", | |
"esModuleInterop": true, | |
"forceConsistentCasingInFileNames": true, | |
"strict": false, | |
"skipLibCheck": true | |
} | |
}' > tsconfig.json | |
npm i -D esbuild esbuild-serve typescript@latest prettier | |
mkdir src | |
echo "document.addEventListener('DOMContentLoaded', () => { | |
const form = document.querySelector('form') | |
if (form) { | |
const button = form.querySelector('button') | |
if (button) button.disabled = true | |
form.onchange = () => { | |
const valid = !form.checkValidity() | |
if (button) button.disabled = valid | |
} | |
form.onsubmit = (ev) => { | |
ev.preventDefault() | |
const data = new FormData(form) | |
const values = Object.fromEntries(data.entries()) | |
console.log(values) | |
} | |
} | |
}) | |
" > src/main.ts | |
mkdir -p public/styles | |
echo '<!DOCTYPE html> | |
<html lang="pt-br"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<link rel="preconnect" href="https://fonts.googleapis.com" /> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
<link | |
href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500&display=swap" | |
rel="stylesheet" | |
/> | |
<link rel="stylesheet" href="styles/main.css" /> | |
<script src="main.js" defer></script> | |
<title>Página da Web</title> | |
</head> | |
<body> | |
<header> | |
<h1>'$1'</h1> | |
</header> | |
<main> | |
<article> | |
<h2>Artigo sobre JavaScript</h2> | |
<p> | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sin | |
laboramus, quis est, qui alienae modum statuat industriae? Traditur, | |
inquit, ab Epicuro ratio neglegendi doloris. Duo Reges: constructio | |
interrete. Te enim iudicem aequum puto, modo quae dicat ille bene | |
noris. Quamquam id quidem licebit iis existimare, qui legerint. Sed | |
quid sentiat, non videtis. Duo enim genera quae erant, fecit tria. | |
Quodsi ipsam honestatem undique pertectam atque absolutam. Odium autem | |
et invidiam facile vitabis. Consequens enim est et post oritur, ut | |
dixi. | |
</p> | |
<pre><code>document.addEventListener("DOMContentLoaded", () => { | |
const form = document.querySelector("form") | |
if (form) { | |
const button = form.querySelector("button") | |
if (button) button.disabled = true | |
form.onchange = () => { | |
const valid = !form.checkValidity() | |
if (button) button.disabled = valid | |
} | |
form.onsubmit = (ev) => { | |
ev.preventDefault() | |
const data = new FormData(form) | |
const values = Object.fromEntries(data.entries()) | |
console.log(values) | |
} | |
} | |
})</code></pre> | |
</article> | |
<form> | |
<section> | |
<label for="name">Nome</label> | |
<input | |
id="name" | |
type="text" | |
autofocus | |
autocomplete="given-name" | |
name="name" | |
required | |
/> | |
<output>Obrigatório</output> | |
</section> | |
<section> | |
<label for="email">E-mail</label> | |
<input | |
id="email" | |
type="email" | |
name="email" | |
autocomplete="email" | |
required | |
/> | |
<output>Email inválido</output> | |
</section> | |
<section> | |
<label for="password">Senha</label> | |
<input | |
id="password" | |
type="password" | |
name="password" | |
autocomplete="new-password" | |
minlength="6" | |
required | |
/> | |
<output>Mínimo de 6 caracteres</output> | |
</section> | |
<section> | |
<label> <input type="checkbox" name="terms" /> Li e concordo com os termos </label> | |
</section> | |
<hr /> | |
<button>Enviar</button> | |
</form> | |
</main> | |
<footer>© 2021</footer> | |
</body> | |
</html> | |
' > public/index.html | |
echo ':root { | |
/* Palette generated by Material Palette | |
materialpalette.com/deep-purple/cyan */ | |
--dark-primary-color: #512da8; | |
--default-primary-color: #673ab7; | |
--light-primary-color: #d1c4e9; | |
--text-primary-color: #ffffff; | |
--accent-color: #00bcd4; | |
--primary-text-color: #212121; | |
--secondary-text-color: #757575; | |
--divider-color: #bdbdbd; | |
--warn-color: #eb3535; | |
--default-font-family: "Fira Sans", sans-serif; | |
--default-element-margin: 6px; | |
--default-element-padding: 8px; | |
--default-block-padding: 10px; | |
--default-border-width: 2px; | |
--border-radius-xs: 2px; | |
--border-radius-sm: 4px; | |
--border-radius-md: 8px; | |
--border-radius-lg: 12px; | |
} | |
html, | |
body { | |
height: 100%; | |
} | |
body { | |
margin: 0; | |
display: flex; | |
flex-direction: column; | |
accent-color: var(--accent-color); | |
color: var(--primary-text-color); | |
font-family: var(--default-font-family); | |
} | |
main { | |
flex: 1; | |
padding: var(--default-block-padding); | |
} | |
header, | |
footer { | |
color: var(--text-primary-color); | |
padding: var(--default-block-padding); | |
background-color: var(--dark-primary-color); | |
} | |
button { | |
padding: var(--default-element-padding) | |
calc(var(--default-element-padding) * 2); | |
background-color: var(--default-primary-color); | |
border-radius: var(--border-radius-sm); | |
color: var(--text-primary-color); | |
border: 0; | |
} | |
button:disabled { | |
background-color: var(--light-primary-color); | |
} | |
button.accent { | |
background-color: var(--accent-color); | |
} | |
form section output { | |
visibility: hidden; | |
} | |
form.invalid input:invalid, | |
form section input:invalid:focus + output { | |
visibility: visible; | |
} | |
form section output { | |
color: var(--warn-color); | |
} | |
form section { | |
display: flex; | |
flex-direction: column; | |
margin-top: var(--default-element-margin); | |
margin-bottom: var(--default-element-margin); | |
} | |
input { | |
border-radius: var(--border-radius-sm); | |
padding: var(--default-element-padding); | |
border: var(--default-border-width) solid var(--dark-primary-color); | |
} | |
input[type="checkbox"] { | |
transform: scale(1.2); | |
} | |
pre { | |
padding: var(--default-block-padding); | |
background-color: var(--primary-text-color); | |
} | |
code { | |
font-size: 16px; | |
color: var(--light-primary-color); | |
} | |
' > public/styles/main.css | |
echo 'import esbuildServe from "esbuild-serve"; | |
esbuildServe( | |
{ | |
logLevel: "info", | |
entryPoints: ["src/main.ts"], | |
bundle: true, | |
outfile: "public/main.js", | |
sourcemap: true, | |
}, | |
{ root: "public" } | |
);' > esbuild.config.js | |
echo '{ | |
"semi": false, | |
"singleQuote": true | |
}' > .prettierrc | |
npx json -I -f package.json -e "this.type = 'module';" | |
npx json -I -f package.json -e "this.scripts.build = 'node esbuild.config.js';" | |
npx json -I -f package.json -e "this.scripts.start = 'node esbuild.config.js -w';" | |
npm start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment