commit
557fdeaf38
@ -0,0 +1,279 @@ |
||||
module.exports = { |
||||
"env": { |
||||
"browser": true, |
||||
"es6": true, |
||||
"node": true, |
||||
}, |
||||
"plugins": ["jest"], |
||||
"extends": "eslint:recommended", |
||||
"parserOptions": { |
||||
"ecmaVersion": 2018, |
||||
"sourceType": "module" |
||||
}, |
||||
"rules": { |
||||
"accessor-pairs": "error", |
||||
"array-bracket-newline": "off", |
||||
"array-bracket-spacing": [ |
||||
"error", |
||||
"never" |
||||
], |
||||
"array-callback-return": "error", |
||||
"array-element-newline": "off", |
||||
"arrow-body-style": "off", |
||||
"arrow-parens": "off", |
||||
"arrow-spacing": [ |
||||
"error", |
||||
{ |
||||
"after": true, |
||||
"before": true |
||||
} |
||||
], |
||||
"block-scoped-var": "error", |
||||
"block-spacing": "error", |
||||
"brace-style": [ |
||||
"error", |
||||
"1tbs" |
||||
], |
||||
"callback-return": "off", |
||||
"camelcase": "off", |
||||
"capitalized-comments": "off", |
||||
"class-methods-use-this": "error", |
||||
"comma-dangle": "off", |
||||
"comma-spacing": [ |
||||
"error", |
||||
{ |
||||
"after": true, |
||||
"before": false |
||||
} |
||||
], |
||||
"comma-style": [ |
||||
"error", |
||||
"last" |
||||
], |
||||
"complexity": "error", |
||||
"computed-property-spacing": [ |
||||
"error", |
||||
"never" |
||||
], |
||||
"consistent-return": "error", |
||||
"consistent-this": "error", |
||||
"curly": "off", |
||||
"default-case": "error", |
||||
"dot-location": "error", |
||||
"dot-notation": "off", |
||||
"eol-last": "error", |
||||
"eqeqeq": "off", |
||||
"func-call-spacing": "error", |
||||
"func-name-matching": "error", |
||||
"func-names": "error", |
||||
"func-style": [ |
||||
"error", |
||||
"expression" |
||||
], |
||||
"function-paren-newline": "off", |
||||
"generator-star-spacing": "error", |
||||
"global-require": "off", |
||||
"guard-for-in": "error", |
||||
"handle-callback-err": "error", |
||||
"id-blacklist": "error", |
||||
"id-length": "off", |
||||
"id-match": "error", |
||||
"implicit-arrow-linebreak": [ |
||||
"error", |
||||
"beside" |
||||
], |
||||
"indent": "off", |
||||
"indent-legacy": "off", |
||||
"init-declarations": "error", |
||||
"jsx-quotes": "error", |
||||
"key-spacing": "warn", |
||||
"keyword-spacing": "off", |
||||
"line-comment-position": "off", |
||||
"linebreak-style": [ |
||||
"error", |
||||
"unix" |
||||
], |
||||
"lines-around-comment": "error", |
||||
"lines-around-directive": "error", |
||||
"lines-between-class-members": "error", |
||||
"max-classes-per-file": "off", |
||||
"max-depth": "error", |
||||
"max-len": "off", |
||||
"max-lines": "off", |
||||
"max-lines-per-function": "off", |
||||
"max-nested-callbacks": "error", |
||||
"max-params": "off", |
||||
"max-statements": "off", |
||||
"max-statements-per-line": "error", |
||||
"multiline-comment-style": "off", |
||||
"new-cap": "error", |
||||
"new-parens": "error", |
||||
"newline-after-var": "off", |
||||
"newline-before-return": "off", |
||||
"newline-per-chained-call": "off", |
||||
"no-alert": "error", |
||||
"no-array-constructor": "error", |
||||
"no-async-promise-executor": "error", |
||||
"no-await-in-loop": "error", |
||||
"no-bitwise": "error", |
||||
"no-buffer-constructor": "error", |
||||
"no-caller": "error", |
||||
"no-catch-shadow": "error", |
||||
"no-confusing-arrow": "error", |
||||
"no-continue": "error", |
||||
"no-div-regex": "error", |
||||
"no-duplicate-imports": "error", |
||||
"no-else-return": "off", |
||||
"no-empty-function": "error", |
||||
"no-eq-null": "off", |
||||
"no-eval": "error", |
||||
"no-extend-native": "error", |
||||
"no-extra-bind": "error", |
||||
"no-extra-label": "error", |
||||
"no-extra-parens": "error", |
||||
"no-floating-decimal": "error", |
||||
"no-implicit-coercion": "error", |
||||
"no-implicit-globals": "error", |
||||
"no-implied-eval": "error", |
||||
"no-inline-comments": "off", |
||||
"no-invalid-this": "error", |
||||
"no-iterator": "error", |
||||
"no-label-var": "error", |
||||
"no-labels": "error", |
||||
"no-lone-blocks": "error", |
||||
"no-lonely-if": "error", |
||||
"no-loop-func": "error", |
||||
"no-magic-numbers": "off", |
||||
"no-misleading-character-class": "error", |
||||
"no-mixed-operators": "error", |
||||
"no-mixed-requires": "error", |
||||
"no-multi-assign": "error", |
||||
"no-multi-spaces": "off", |
||||
"no-multi-str": "error", |
||||
"no-multiple-empty-lines": "error", |
||||
"no-native-reassign": "error", |
||||
"no-negated-condition": "off", |
||||
"no-negated-in-lhs": "error", |
||||
"no-nested-ternary": "error", |
||||
"no-new": "error", |
||||
"no-new-func": "error", |
||||
"no-new-object": "error", |
||||
"no-new-require": "error", |
||||
"no-new-wrappers": "error", |
||||
"no-octal-escape": "error", |
||||
"no-param-reassign": "error", |
||||
"no-path-concat": "error", |
||||
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }], |
||||
"no-process-env": "off", |
||||
"no-process-exit": "off", |
||||
"no-proto": "error", |
||||
"no-prototype-builtins": "error", |
||||
"no-restricted-globals": "error", |
||||
"no-restricted-imports": "error", |
||||
"no-restricted-modules": "error", |
||||
"no-restricted-properties": "error", |
||||
"no-restricted-syntax": "error", |
||||
"no-return-assign": "error", |
||||
"no-return-await": "error", |
||||
"no-script-url": "error", |
||||
"no-self-compare": "error", |
||||
"no-sequences": "error", |
||||
"no-shadow": "off", |
||||
"no-shadow-restricted-names": "error", |
||||
"no-spaced-func": "error", |
||||
"no-sync": "warn", |
||||
"no-tabs": "off", |
||||
"no-template-curly-in-string": "error", |
||||
"no-ternary": "off", |
||||
"no-throw-literal": "error", |
||||
"no-trailing-spaces": "off", |
||||
"no-undef-init": "error", |
||||
"no-undefined": "off", |
||||
"no-underscore-dangle": "off", |
||||
"no-unmodified-loop-condition": "error", |
||||
"no-unneeded-ternary": "error", |
||||
"no-unused-expressions": "error", |
||||
"no-use-before-define": ["error", {"functions": true, "classes": false}], |
||||
"no-useless-call": "error", |
||||
"no-useless-computed-key": "error", |
||||
"no-useless-concat": "error", |
||||
"no-useless-constructor": "error", |
||||
"no-useless-rename": "error", |
||||
"no-useless-return": "error", |
||||
"no-var": "error", |
||||
"no-void": "error", |
||||
"no-warning-comments": "off", |
||||
"no-whitespace-before-property": "error", |
||||
"no-with": "error", |
||||
"nonblock-statement-body-position": "error", |
||||
"object-curly-newline": "off", |
||||
"object-curly-spacing": "off", |
||||
"object-shorthand": "error", |
||||
"one-var": "off", |
||||
"one-var-declaration-per-line": "error", |
||||
"operator-assignment": "error", |
||||
"operator-linebreak": "error", |
||||
"padded-blocks": "off", |
||||
"padding-line-between-statements": "error", |
||||
"prefer-arrow-callback": "error", |
||||
"prefer-const": "off", |
||||
"prefer-destructuring": "off", |
||||
"prefer-numeric-literals": "error", |
||||
"prefer-object-spread": "error", |
||||
"prefer-promise-reject-errors": "error", |
||||
"prefer-reflect": "off", |
||||
"prefer-rest-params": "error", |
||||
"prefer-spread": "error", |
||||
"prefer-template": "error", |
||||
"quote-props": "off", |
||||
"quotes": "off", |
||||
"radix": "error", |
||||
"require-atomic-updates": "warn", |
||||
"require-await": "off", |
||||
"require-jsdoc": "error", |
||||
"require-unicode-regexp": "error", |
||||
"rest-spread-spacing": "error", |
||||
"semi": "off", |
||||
"semi-spacing": "error", |
||||
"semi-style": [ |
||||
"error", |
||||
"last" |
||||
], |
||||
"sort-imports": "off", |
||||
"sort-keys": "off", |
||||
"sort-vars": "error", |
||||
"space-before-blocks": "error", |
||||
"space-before-function-paren": "off", |
||||
"space-in-parens": [ |
||||
"error", |
||||
"never" |
||||
], |
||||
"space-infix-ops": "off", |
||||
"space-unary-ops": "error", |
||||
"spaced-comment": [ |
||||
"error", |
||||
"always" |
||||
], |
||||
"strict": "error", |
||||
"switch-colon-spacing": "error", |
||||
"symbol-description": "error", |
||||
"template-curly-spacing": [ |
||||
"error", |
||||
"never" |
||||
], |
||||
"template-tag-spacing": "error", |
||||
"unicode-bom": [ |
||||
"error", |
||||
"never" |
||||
], |
||||
"valid-jsdoc": "error", |
||||
"vars-on-top": "error", |
||||
"wrap-iife": "error", |
||||
"wrap-regex": "error", |
||||
"yield-star-spacing": "error", |
||||
"yoda": [ |
||||
"error", |
||||
"never" |
||||
] |
||||
} |
||||
}; |
@ -0,0 +1,114 @@ |
||||
# ---> Node |
||||
# Logs |
||||
logs |
||||
*.log |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
|
||||
# Runtime data |
||||
pids |
||||
*.pid |
||||
*.seed |
||||
*.pid.lock |
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover |
||||
lib-cov |
||||
|
||||
# Coverage directory used by tools like istanbul |
||||
coverage |
||||
|
||||
# nyc test coverage |
||||
.nyc_output |
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) |
||||
.grunt |
||||
|
||||
# Bower dependency directory (https://bower.io/) |
||||
bower_components |
||||
|
||||
# node-waf configuration |
||||
.lock-wscript |
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html) |
||||
build/Release |
||||
|
||||
# Dependency directories |
||||
jspm_packages/ |
||||
|
||||
# TypeScript v1 declaration files |
||||
typings/ |
||||
|
||||
# Optional npm cache directory |
||||
.npm |
||||
|
||||
# Optional eslint cache |
||||
.eslintcache |
||||
|
||||
# Optional REPL history |
||||
.node_repl_history |
||||
|
||||
# Output of 'npm pack' |
||||
*.tgz |
||||
|
||||
# Yarn Integrity file |
||||
.yarn-integrity |
||||
|
||||
# dotenv environment variables file |
||||
.env |
||||
|
||||
# parcel-bundler cache (https://parceljs.org/) |
||||
.cache |
||||
|
||||
# next.js build output |
||||
.next |
||||
|
||||
# nuxt.js build output |
||||
.nuxt |
||||
|
||||
# vuepress build output |
||||
.vuepress/dist |
||||
|
||||
# Serverless directories |
||||
.serverless |
||||
|
||||
# FuseBox cache |
||||
.fusebox/ |
||||
|
||||
# ---> Vim |
||||
# Swap |
||||
[._]*.s[a-v][a-z] |
||||
[._]*.sw[a-p] |
||||
[._]s[a-rt-v][a-z] |
||||
[._]ss[a-gi-z] |
||||
[._]sw[a-p] |
||||
|
||||
# Session |
||||
Session.vim |
||||
|
||||
# Temporary |
||||
.netrwhist |
||||
*~ |
||||
# Auto-generated tag files |
||||
tags |
||||
# Persistent undo |
||||
[._]*.un~ |
||||
|
||||
.DS_Store |
||||
/node_modules/ |
||||
/src/node_modules/@sapper/ |
||||
yarn-error.log |
||||
/cypress/screenshots/ |
||||
.DS_Store |
||||
/node_modules/ |
||||
/src/node_modules/@sapper/ |
||||
yarn-error.log |
||||
/cypress/screenshots/ |
||||
/__sapper__/ |
||||
|
||||
.sessions |
||||
dump.rdb |
||||
devices/ |
||||
*.mp4 |
||||
*.webm |
||||
*.jpg |
@ -0,0 +1 @@ |
||||
There is no license given at all for this code. It is fully copyright like any creative work you find online. Think of this as being like a photographer's photo or a painting in a museum. You can look at it and marvel at it's glorious beauty, but you can't take it home or use it without permission. |
@ -0,0 +1,10 @@ |
||||
Notes for starter-project: |
||||
|
||||
* Keep it simple and just an SPA with svelte-spa |
||||
* Include everything needed to get started with a full stack. Database, knex, sqlite3, etc. |
||||
* Logins, passwords, and payments included ready to go. |
||||
* Email templates and sending built-in and ready. |
||||
|
||||
I installed most of the stuff so I think what I have to do is start building a first thing, then add |
||||
the components I pull out to it as I go. |
||||
|
@ -0,0 +1,24 @@ |
||||
function Player() { |
||||
} |
||||
Player.prototype.play = function(song) { |
||||
this.currentlyPlayingSong = song; |
||||
this.isPlaying = true; |
||||
}; |
||||
|
||||
Player.prototype.pause = function() { |
||||
this.isPlaying = false; |
||||
}; |
||||
|
||||
Player.prototype.resume = function() { |
||||
if (this.isPlaying) { |
||||
throw new Error("song is already playing"); |
||||
} |
||||
|
||||
this.isPlaying = true; |
||||
}; |
||||
|
||||
Player.prototype.makeFavorite = function() { |
||||
this.currentlyPlayingSong.persistFavoriteStatus(true); |
||||
}; |
||||
|
||||
module.exports = Player; |
@ -0,0 +1,9 @@ |
||||
function Song() { |
||||
} |
||||
|
||||
Song.prototype.persistFavoriteStatus = function(value) { |
||||
// something complicated
|
||||
throw new Error("not yet implemented"); |
||||
}; |
||||
|
||||
module.exports = Song; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,57 @@ |
||||
{ |
||||
"name": "svelte-app", |
||||
"version": "1.0.0", |
||||
"scripts": { |
||||
"build": "rollup -c", |
||||
"dev": "rollup -c -w", |
||||
"start": "sirv public", |
||||
"test": "jasmine" |
||||
}, |
||||
"devDependencies": { |
||||
"@rollup/plugin-commonjs": "^16.0.0", |
||||
"@rollup/plugin-node-resolve": "^10.0.0", |
||||
"axios": "^0.21.0", |
||||
"axios-cookiejar-support": "^1.0.1", |
||||
"chromedriver": "^87.0.0", |
||||
"faker": "^5.1.0", |
||||
"jasmine": "^3.6.3", |
||||
"maildev": "^1.1.0", |
||||
"node-notifier": "^8.0.0", |
||||
"pm2": "^4.5.0", |
||||
"pm2-logrotate": "^2.7.0", |
||||
"puppeteer": "^5.5.0", |
||||
"rollup": "^2.3.4", |
||||
"rollup-plugin-css-only": "^3.0.0", |
||||
"rollup-plugin-livereload": "^2.0.0", |
||||
"rollup-plugin-svelte": "^7.0.0", |
||||
"rollup-plugin-terser": "^7.0.0", |
||||
"svelte": "^3.0.0" |
||||
}, |
||||
"dependencies": { |
||||
"Validator": "^1.1.2", |
||||
"bcrypt": "^5.0.0", |
||||
"body-parser": "^1.19.0", |
||||
"bull": "^3.20.0", |
||||
"compression": "^1.7.4", |
||||
"cookie-session": "^1.4.0", |
||||
"dayjs": "^1.9.6", |
||||
"email-deep-validator": "^3.3.0", |
||||
"eslint": "^7.14.0", |
||||
"express-session": "^1.17.1", |
||||
"knex": "^0.21.12", |
||||
"knex-paginate": "^1.2.3", |
||||
"morgan": "^1.10.0", |
||||
"node-fetch": "^2.6.1", |
||||
"nodemailer": "^6.4.16", |
||||
"passport": "^0.4.1", |
||||
"passport-local": "^1.0.0", |
||||
"pg": "^8.5.1", |
||||
"pino": "^6.7.0", |
||||
"pino-http": "^5.3.0", |
||||
"pino-pretty": "^4.3.0", |
||||
"polka": "^0.5.2", |
||||
"sirv-cli": "^1.0.0", |
||||
"sqlite3": "^5.0.0", |
||||
"svelte-spa-router": "^3.0.5" |
||||
} |
||||
} |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 3.1 KiB |
@ -0,0 +1,449 @@ |
||||
/* MVP.css v1.6.2 - https://github.com/andybrewer/mvp */ |
||||
|
||||
:root { |
||||
--border-radius: 5px; |
||||
--box-shadow: 2px 2px 10px; |
||||
--color: #000; |
||||
--color-accent: #111; |
||||
--color-inactive: #999; |
||||
--color-inactive-secondary: #fff; |
||||
--color-bg: #fff; |
||||
--color-bg-secondary: #eee; |
||||
--color-secondary: #666; |
||||
--color-secondary-accent: #888; |
||||
--color-shadow: #ddd; |
||||
--color-shadow-secondary: #fff; |
||||
--color-bg-inverted: #555; |
||||
--color-text: #000; |
||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; |
||||
--hover-brightness: 1.2; |
||||
--justify-important: center; |
||||
--justify-normal: left; |
||||
--line-height: 1.5; |
||||
--width-card: 285px; |
||||
--width-card-medium: 460px; |
||||
--width-card-wide: 800px; |
||||
--width-content: 1090px; |
||||
} |
||||
|
||||
|
||||
[data-theme="dark"] { |
||||
--color: #bbb; |
||||
--color-accent: #fff; |
||||
--color-bg: #333; |
||||
--color-bg-secondary: #555; |
||||
--color-shadow-secondary: #333; |
||||
--color-secondary: #ddd; |
||||
--color-secondary-accent: #ddd; |
||||
--color-shadow: #bbb; |
||||
--color-text: #fff; |
||||
--color-text-secondary: #aaa; |
||||
--color-inactive: #666; |
||||
--color-bg-inverted: #fff; |
||||
} |
||||
|
||||
|
||||
/* Layout */ |
||||
article aside { |
||||
background: var(--color-secondary-accent); |
||||
border-left: 4px solid var(--color-secondary); |
||||
padding: 0.01rem 0.8rem; |
||||
} |
||||
|
||||
body { |
||||
background: var(--color-bg); |
||||
color: var(--color-text); |
||||
font-family: var(--font-family); |
||||
line-height: var(--line-height); |
||||
margin: 0; |
||||
overflow-x: hidden; |
||||
padding: 1rem 0; |
||||
} |
||||
|
||||
footer, |
||||
header, |
||||
main { |
||||
margin: 0 auto; |
||||
max-width: var(--width-content); |
||||
} |
||||
|
||||
hr { |
||||
background-color: var(--color-bg-secondary); |
||||
border: none; |
||||
height: 1px; |
||||
margin: 4rem 0; |
||||
} |
||||
|
||||
section { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
justify-content: var(--justify-important); |
||||
} |
||||
|
||||
section aside { |
||||
border: 1px solid var(--color-bg-secondary); |
||||
border-radius: var(--border-radius); |
||||
box-shadow: var(--box-shadow) var(--color-shadow); |
||||
margin: 1rem; |
||||
padding: 1.25rem; |
||||
width: var(--width-card); |
||||
} |
||||
|
||||
section aside:hover { |
||||
box-shadow: var(--box-shadow) var(--color-bg-secondary); |
||||
} |
||||
|
||||
section aside img { |
||||
max-width: 100%; |
||||
} |
||||
|
||||
[hidden] { |
||||
display: none; |
||||
} |
||||
|
||||
/* Headers */ |
||||
article header, |
||||
div header, |
||||
main header { |
||||
padding-top: 0; |
||||
} |
||||
|
||||
header { |
||||
text-align: var(--justify-important); |
||||
} |
||||
|
||||
header a b, |
||||
header a em, |
||||
header a i, |
||||
header a strong { |
||||
margin-left: 0.5rem; |
||||
margin-right: 0.5rem; |
||||
} |
||||
|
||||
header nav img { |
||||
margin: 1rem 0; |
||||
} |
||||
|
||||
section header { |
||||
padding-top: 0; |
||||
width: 100%; |
||||
} |
||||
|
||||
/* Nav */ |
||||
nav { |
||||
align-items: center; |
||||
display: flex; |
||||
font-weight: bold; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
nav ul { |
||||
list-style: none; |
||||
padding: 0; |
||||
} |
||||
|
||||
nav ul li { |
||||
display: inline-block; |
||||
margin: 0 0.5rem; |
||||
position: relative; |
||||
text-align: left; |
||||
} |
||||
|
||||
/* Nav Dropdown */ |
||||
nav ul li:hover ul { |
||||
display: block; |
||||
} |
||||
|
||||
nav ul li ul { |
||||
background: var(--color-bg); |
||||
border: 1px solid var(--color-bg-secondary); |
||||
border-radius: var(--border-radius); |
||||
box-shadow: var(--box-shadow) var(--color-shadow); |
||||
display: none; |
||||
height: auto; |
||||
left: -2px; |
||||
padding: .5rem 1rem; |
||||
position: absolute; |
||||
top: 1.7rem; |
||||
white-space: nowrap; |
||||
width: auto; |
||||
} |
||||
|
||||
nav ul li ul li, |
||||
nav ul li ul li a { |
||||
display: block; |
||||
} |
||||
|
||||
/* Typography */ |
||||
code, |
||||
samp { |
||||
background-color: var(--color-accent); |
||||
border-radius: var(--border-radius); |
||||
color: var(--color-text); |
||||
display: inline-block; |
||||
margin: 0 0.1rem; |
||||
padding: 0 0.5rem; |
||||
} |
||||
|
||||
details { |
||||
margin: 1.3rem 0; |
||||
} |
||||
|
||||
details summary { |
||||
font-weight: bold; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
h1, |
||||
h2, |
||||
h3, |
||||
h4, |
||||
h5, |
||||
h6 { |
||||
line-height: var(--line-height); |
||||
} |
||||
|
||||
mark { |
||||
padding: 0.1rem; |
||||
} |
||||
|
||||
ol li, |
||||
ul li { |
||||
padding: 0.2rem 0; |
||||
} |
||||
|
||||
p { |
||||
padding: 0; |
||||
} |
||||
|
||||
pre { |
||||
margin: 1rem 0; |
||||
max-width: var(--width-card-wide); |
||||
padding: 1rem 0; |
||||
} |
||||
|
||||
pre code, |
||||
pre samp { |
||||
display: block; |
||||
max-width: var(--width-card-wide); |
||||
padding: 0.5rem 2rem; |
||||
white-space: pre-wrap; |
||||
} |
||||
|
||||
small { |
||||
color: var(--color-text-secondary); |
||||
} |
||||
|
||||
sup { |
||||
background-color: var(--color-secondary); |
||||
border-radius: var(--border-radius); |
||||
color: var(--color-bg); |
||||
font-size: xx-small; |
||||
font-weight: bold; |
||||
margin: 0.2rem; |
||||
padding: 0.2rem 0.3rem; |
||||
position: relative; |
||||
top: -2px; |
||||
} |
||||
|
||||
/* Links */ |
||||
a { |
||||
--text-decoration: none; |
||||
color: var(--color-secondary); |
||||
display: inline-block; |
||||
font-weight: bold; |
||||
text-decoration: var(--text-decoration); |
||||
} |
||||
|
||||
a:hover { |
||||
filter: brightness(var(--hover-brightness)); |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
a b, |
||||
a em, |
||||
a i, |
||||
a strong, |
||||
button { |
||||
border-radius: var(--border-radius); |
||||
display: inline-block; |
||||
font-size: medium; |
||||
font-weight: bold; |
||||
line-height: var(--line-height); |
||||
padding: 1rem 2rem; |
||||
} |
||||
|
||||
button { |
||||
font-family: var(--font-family); |
||||
} |
||||
|
||||
button:hover { |
||||
cursor: pointer; |
||||
filter: brightness(var(--hover-brightness)); |
||||
} |
||||
|
||||
a b, |
||||
a strong, |
||||
button { |
||||
background-color: var(--color); |
||||
border: 2px solid var(--color); |
||||
color: var(--color-bg); |
||||
} |
||||
|
||||
a em, |
||||
a i { |
||||
border: 2px solid var(--color); |
||||
border-radius: var(--border-radius); |
||||
color: var(--color); |
||||
display: inline-block; |
||||
padding: 1rem 2rem; |
||||
} |
||||
|
||||
/* Images */ |
||||
figure { |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
figure img { |
||||
max-width: 100%; |
||||
} |
||||
|
||||
figure figcaption { |
||||
color: var(--color-text-secondary); |
||||
} |
||||
|
||||
/* Forms */ |
||||
|
||||
button:disabled, |
||||
input:disabled { |
||||
background: var(--color-bg-secondary); |
||||
border-color: var(--color-bg-secondary); |
||||
color: var(--color-text-secondary); |
||||
cursor: not-allowed; |
||||
} |
||||
|
||||
button[disabled]:hover { |
||||
filter: none; |
||||
} |
||||
|
||||
form { |
||||
border: 1px solid var(--color-bg-secondary); |
||||
border-radius: var(--border-radius); |
||||
box-shadow: var(--box-shadow) var(--color-shadow); |
||||
display: block; |
||||
max-width: var(--width-card-wide); |
||||
min-width: var(--width-card); |
||||
padding: 1.5rem; |
||||
text-align: var(--justify-normal); |
||||
} |
||||
|
||||
form header { |
||||
margin: 1.5rem 0; |
||||
padding: 1.5rem 0; |
||||
} |
||||
|
||||
input, |
||||
label, |
||||
select, |
||||
textarea { |
||||
display: block; |
||||
font-size: inherit; |
||||
max-width: var(--width-card-wide); |
||||
} |
||||
|
||||
input[type="checkbox"], |
||||
input[type="radio"] { |
||||
display: inline-block; |
||||
} |
||||
|
||||
input[type="checkbox"]+label, |
||||
input[type="radio"]+label { |
||||
display: inline-block; |
||||
font-weight: normal; |
||||
position: relative; |
||||
top: 1px; |
||||
} |
||||
|
||||
input, |
||||
select, |
||||
textarea { |
||||
border: 1px solid var(--color-bg-secondary); |
||||
border-radius: var(--border-radius); |
||||
margin-bottom: 1rem; |
||||
padding: 0.4rem 0.8rem; |
||||
} |
||||
|
||||
input[readonly], |
||||
textarea[readonly] { |
||||
background-color: var(--color-bg-secondary); |
||||
} |
||||
|
||||
label { |
||||
font-weight: bold; |
||||
margin-bottom: 0.2rem; |
||||
} |
||||
|
||||
/* Tables */ |
||||
table { |
||||
border: 1px solid var(--color-bg-secondary); |
||||
border-radius: var(--border-radius); |
||||
border-spacing: 0; |
||||
display: inline-block; |
||||
max-width: 100%; |
||||
overflow-x: auto; |
||||
padding: 0; |
||||
white-space: nowrap; |
||||
} |
||||
|
||||
table td, |
||||
table th, |
||||
table tr { |
||||
padding: 0.4rem 0.8rem; |
||||
text-align: var(--justify-important); |
||||
} |
||||
|
||||
table thead { |
||||
background-color: var(--color); |
||||
border-collapse: collapse; |
||||
border-radius: var(--border-radius); |
||||
color: var(--color-bg); |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
table thead th:first-child { |
||||
border-top-left-radius: var(--border-radius); |
||||
} |
||||
|
||||
table thead th:last-child { |
||||
border-top-right-radius: var(--border-radius); |
||||
} |
||||
|
||||
table thead th:first-child, |
||||
table tr td:first-child { |
||||
text-align: var(--justify-normal); |
||||
} |
||||
|
||||
table tr:nth-child(even) { |
||||
background-color: var(--color-accent); |
||||
} |
||||
|
||||
/* Quotes */ |
||||
blockquote { |
||||
display: block; |
||||
font-size: x-large; |
||||
line-height: var(--line-height); |
||||
margin: 1rem auto; |
||||
max-width: var(--width-card-medium); |
||||
padding: 1.5rem 1rem; |
||||
text-align: var(--justify-important); |
||||
} |
||||
|
||||
blockquote footer { |
||||
color: var(--color-text-secondary); |
||||
display: block; |
||||
font-size: small; |
||||
line-height: var(--line-height); |
||||
padding: 1.5rem 0; |
||||
} |
After Width: | Height: | Size: 58 KiB |
@ -0,0 +1,18 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset='utf-8'> |
||||
<meta name='viewport' content='width=device-width,initial-scale=1'> |
||||
|
||||
<title>fsck CSS</title> |
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'> |
||||
<link rel='stylesheet' href='/global.css'> |
||||
<link rel='stylesheet' href='/build/bundle.css'> |
||||
|
||||
<script defer src='/build/bundle.js'></script> |
||||
</head> |
||||
|
||||
<body> |
||||
</body> |
||||
</html> |
@ -0,0 +1,76 @@ |
||||
import svelte from 'rollup-plugin-svelte'; |
||||
import commonjs from '@rollup/plugin-commonjs'; |
||||
import resolve from '@rollup/plugin-node-resolve'; |
||||
import livereload from 'rollup-plugin-livereload'; |
||||
import { terser } from 'rollup-plugin-terser'; |
||||
import css from 'rollup-plugin-css-only'; |
||||
|
||||
const production = !process.env.ROLLUP_WATCH; |
||||
|
||||
function serve() { |
||||
let server; |
||||
|
||||
function toExit() { |
||||
if (server) server.kill(0); |
||||
} |
||||
|
||||
return { |
||||
writeBundle() { |
||||
if (server) return; |
||||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { |
||||
stdio: ['ignore', 'inherit', 'inherit'], |
||||
shell: true |
||||
}); |
||||
|
||||
process.on('SIGTERM', toExit); |
||||
process.on('exit', toExit); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
export default { |
||||
input: 'src/main.js', |
||||
output: { |
||||
sourcemap: true, |
||||
format: 'iife', |
||||
name: 'app', |
||||
file: 'public/build/bundle.js' |
||||
}, |
||||
plugins: [ |
||||
svelte({ |
||||
compilerOptions: { |
||||
// enable run-time checks when not in production
|
||||
dev: !production |
||||
} |
||||
}), |
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css({ output: 'bundle.css' }), |
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({ |
||||
browser: true, |
||||
dedupe: ['svelte'] |
||||
}), |
||||
commonjs(), |
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(), |
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'), |
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser() |
||||
], |
||||
watch: { |
||||
clearScreen: false |
||||
} |
||||
}; |
@ -0,0 +1,117 @@ |
||||
// @ts-check
|
||||
|
||||
/** This script modifies the project to support TS code in .svelte files like: |
||||
|
||||
<script lang="ts"> |
||||
export let name: string; |
||||
</script> |
||||
|
||||
As well as validating the code for CI. |
||||
*/ |
||||
|
||||
/** To work on this script: |
||||
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template |
||||
*/ |
||||
|
||||
const fs = require("fs") |
||||
const path = require("path") |
||||
const { argv } = require("process") |
||||
|
||||
const projectRoot = argv[2] || path.join(__dirname, "..") |
||||
|
||||
// Add deps to pkg.json
|
||||
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) |
||||
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { |
||||
"svelte-check": "^1.0.0", |
||||
"svelte-preprocess": "^4.0.0", |
||||
"@rollup/plugin-typescript": "^6.0.0", |
||||
"typescript": "^3.9.3", |
||||
"tslib": "^2.0.0", |
||||
"@tsconfig/svelte": "^1.0.0" |
||||
}) |
||||
|
||||
// Add script for checking
|
||||
packageJSON.scripts = Object.assign(packageJSON.scripts, { |
||||
"validate": "svelte-check" |
||||
}) |
||||
|
||||
// Write the package JSON
|
||||
fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) |
||||
|
||||
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
|
||||
const beforeMainJSPath = path.join(projectRoot, "src", "main.js") |
||||
const afterMainTSPath = path.join(projectRoot, "src", "main.ts") |
||||
fs.renameSync(beforeMainJSPath, afterMainTSPath) |
||||
|
||||
// Switch the app.svelte file to use TS
|
||||
const appSveltePath = path.join(projectRoot, "src", "App.svelte") |
||||
let appFile = fs.readFileSync(appSveltePath, "utf8") |
||||
appFile = appFile.replace("<script>", '<script lang="ts">') |
||||
appFile = appFile.replace("export let name;", 'export let name: string;') |
||||
fs.writeFileSync(appSveltePath, appFile) |
||||
|
||||
// Edit rollup config
|
||||
const rollupConfigPath = path.join(projectRoot, "rollup.config.js") |
||||
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8") |
||||
|
||||
// Edit imports
|
||||
rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
|
||||
import sveltePreprocess from 'svelte-preprocess'; |
||||
import typescript from '@rollup/plugin-typescript';`)
|
||||
|
||||
// Replace name of entry point
|
||||
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`) |
||||
|
||||
// Add preprocessor
|
||||
rollupConfig = rollupConfig.replace( |
||||
'compilerOptions:', |
||||
'preprocess: sveltePreprocess(),\n\t\t\tcompilerOptions:' |
||||
); |
||||
|
||||
// Add TypeScript
|
||||
rollupConfig = rollupConfig.replace( |
||||
'commonjs(),', |
||||
'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),' |
||||
); |
||||
fs.writeFileSync(rollupConfigPath, rollupConfig) |
||||
|
||||
// Add TSConfig
|
||||
const tsconfig = `{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json", |
||||
|
||||
"include": ["src/**/*"], |
||||
"exclude": ["node_modules/*", "__sapper__/*", "public/*"] |
||||
}` |
||||
const tsconfigPath = path.join(projectRoot, "tsconfig.json") |
||||
fs.writeFileSync(tsconfigPath, tsconfig) |
||||
|
||||
// Delete this script, but not during testing
|
||||
if (!argv[2]) { |
||||
// Remove the script
|
||||
fs.unlinkSync(path.join(__filename)) |
||||
|
||||
// Check for Mac's DS_store file, and if it's the only one left remove it
|
||||
const remainingFiles = fs.readdirSync(path.join(__dirname)) |
||||
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') { |
||||
fs.unlinkSync(path.join(__dirname, '.DS_store')) |
||||
} |
||||
|
||||
// Check if the scripts folder is empty
|
||||
if (fs.readdirSync(path.join(__dirname)).length === 0) { |
||||
// Remove the scripts folder
|
||||
fs.rmdirSync(path.join(__dirname)) |
||||
} |
||||
} |
||||
|
||||
// Adds the extension recommendation
|
||||
fs.mkdirSync(path.join(projectRoot, ".vscode")) |
||||
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
|
||||
"recommendations": ["svelte.svelte-vscode"] |
||||
} |
||||
`)
|
||||
|
||||
console.log("Converted to TypeScript.") |
||||
|
||||
if (fs.existsSync(path.join(projectRoot, "node_modules"))) { |
||||
console.log("\nYou will need to re-run your dependency manager to get started.") |
||||
} |
@ -0,0 +1,15 @@ |
||||
beforeEach(function () { |
||||
jasmine.addMatchers({ |
||||
toBePlaying: function () { |
||||
return { |
||||
compare: function (actual, expected) { |
||||
var player = actual; |
||||
|
||||
return { |
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
}); |
||||
}); |
@ -0,0 +1,60 @@ |
||||
describe("Player", () => { |
||||
var Player = require('../../lib/jasmine_examples/Player'); |
||||
var Song = require('../../lib/jasmine_examples/Song'); |
||||
var player; |
||||
var song; |
||||
|
||||
beforeEach(() => { |
||||
player = new Player(); |
||||
song = new Song(); |
||||
}); |
||||
|
||||
it("should be able to play a Song", () => { |
||||
player.play(song); |
||||
expect(player.currentlyPlayingSong).toEqual(song); |
||||
|
||||
//demonstrates use of custom matcher
|
||||
expect(player).toBePlaying(song); |
||||
}); |
||||
|
||||
describe("when song has been paused", () => { |
||||
beforeEach(() => { |
||||
player.play(song); |
||||
player.pause(); |
||||
}); |
||||
|
||||
it("should indicate that the song is currently paused", () => { |
||||
expect(player.isPlaying).toBeFalsy(); |
||||
|
||||
// demonstrates use of 'not' with a custom matcher
|
||||
expect(player).not.toBePlaying(song); |
||||
}); |
||||
|
||||
it("should be possible to resume", () => { |
||||
player.resume(); |
||||
expect(player.isPlaying).toBeTruthy(); |
||||
expect(player.currentlyPlayingSong).toEqual(song); |
||||
}); |
||||
}); |
||||
|
||||
// demonstrates use of spies to intercept and test method calls
|
||||
it("tells the current song if the user has made it a favorite", () => { |
||||
spyOn(song, 'persistFavoriteStatus'); |
||||
|
||||
player.play(song); |
||||
player.makeFavorite(); |
||||
|
||||
expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); |
||||
}); |
||||
|
||||
//demonstrates use of expected exceptions
|
||||
describe("#resume", () => { |
||||
it("should throw an exception if song is already playing", () => { |
||||
player.play(song); |
||||
|
||||
expect(() => { |
||||
player.resume(); |
||||
}).toThrowError("song is already playing"); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,11 @@ |
||||
{ |
||||
"spec_dir": "spec", |
||||
"spec_files": [ |
||||
"**/*[sS]pec.js" |
||||
], |
||||
"helpers": [ |
||||
"helpers/**/*.js" |
||||
], |
||||
"stopSpecOnExpectationFailure": false, |
||||
"random": true |
||||
} |
@ -0,0 +1 @@ |
||||
<h1>About Page</h1> |
@ -0,0 +1,59 @@ |
||||
<script> |
||||
import Router from 'svelte-spa-router'; |
||||
import routes from './routes'; |
||||
import { link } from 'svelte-spa-router'; |
||||
import Icon from './components/Icon.svelte'; |
||||
import Darkmode from './components/Darkmode.svelte'; |
||||
</script> |
||||
|
||||
<svelte:head> |
||||
<title>LJSTHW Starter Template</title> |
||||
</svelte:head> |
||||
|
||||
<style> |
||||
header { |
||||
} |
||||
|
||||
main { |
||||
} |
||||
|
||||
footer { |
||||
display: flex; |
||||
flex: flex-grow; |
||||
flex-direction: row; |
||||
} |
||||
|
||||
footer nav { |
||||
flex: 1; |
||||
} |
||||
</style> |
||||
|
||||
<header> |
||||
<nav> |
||||
<a href="/" use:link> |
||||
<Icon name="trash-2" size="64" /> |
||||
</a> |
||||
<ul> |
||||
<li><a href="/demos" use:link>Demos</a></li> |
||||
<li><a href="/about" use:link>About</a></li> |
||||
</ul> |
||||
</nav> |
||||
</header> |
||||
|
||||
<main> |
||||
<Router {routes } restoreScrollState={true} /> |
||||
</main> |
||||
|
||||
<hr> |
||||
<footer> |
||||
<nav> |
||||
<a href="/" use:link> |
||||
<p>Copyright (C) Big Corp.</p> |
||||
</a> |
||||
<ul> |
||||
<li><Icon name="twitter" size="32" /></li> |
||||
<li><Icon name="instagram" size="32" /></li> |
||||
<li><Darkmode /></li> |
||||
</ul> |
||||
</nav> |
||||
</footer> |
@ -0,0 +1,128 @@ |
||||
<script> |
||||
import {link} from 'svelte-spa-router'; |
||||
import Icon from './components/Icon.svelte'; |
||||
</script> |
||||
|
||||
<style> |
||||
hero { |
||||
display: block; |
||||
padding: 3rem; |
||||
background-color: var(--color-bg-secondary); |
||||
} |
||||
|
||||
hero h1 { |
||||
font-size: 3rem; |
||||
} |
||||
|
||||
aside a { |
||||
--text-decoration: underline; |
||||
} |
||||
|
||||
rationale { |
||||
display: flex; |
||||
flex-direction: column; |
||||
font-size: 1.5em; |
||||
padding-left: 4rem; |
||||
padding-right: 4rem; |
||||
} |
||||
</style> |
||||
|
||||
<hero> |
||||
<h1>fsck CSS</h1> |
||||
<p>An experiment in cleaning up CSS and HTML with modern tools like <b>flexbox</b> and <b>grids</b>.</p> |
||||
</hero> |
||||
|
||||
<hr> |
||||
|
||||
<section> |
||||
<aside> |
||||
<h3>Remove Classes</h3> |
||||
<Icon name="code" size="64" /> |
||||
<p>Using a classless style like <a href="https://andybrewer.github.io/mvp/">MVP.css</a>, you |
||||
bring back CSS specificity to its original intent.</p> |
||||
</aside> |
||||
|
||||
<aside> |
||||
<h3>Add Flexbox</h3> |
||||
<Icon name="box" size="64" /> |
||||
<p>Using <a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">flexbox</a> you can layout anything you want without tons of divs.</p> |
||||
</aside> |
||||
|
||||
<aside> |
||||
<h3>Modify with Variables</h3> |
||||
<Icon name="sliders" size="64" /> |
||||
<p>Using CSS variables you can replace many uses of classes and ids, avoiding most specificity |
||||
issues. Try the dark mode button below. |
||||
</p> |
||||
</aside> |
||||
</section> |
||||
|
||||
|
||||
<rationale> |
||||
<section> |
||||
<h1>Cleaner CSS</h1> |
||||
</section> |
||||
|
||||
<p>This website is nothing more than a set of small demos for the idea of |
||||
using flexbox and grids to clean up and simplify CSS. Most everything else |
||||
about CSS stays. Filters, transforms, attributes, and everything that |
||||
applies to the visual display of the components of a design. What gets |
||||
removed is <b>div</b> heavy, class heavy, not-semantic-at-all layout |
||||
systems cluttering the real information available through simple HTML |
||||
tags.</p> |
||||
|
||||
<p>In short, if you're writing this:</p> |
||||
|
||||
<section> |
||||
<aside> |
||||
<pre> |
||||
<div class="grid col-1"> |
||||
<div class="card"> |
||||
... |
||||
</div> |
||||
</div> |
||||
</pre> |
||||
</aside> |
||||
</section> |
||||
|
||||
<p>You could write this if you use flexbox, grids, and variables:</p> |
||||
|
||||
<section> |
||||
<aside> |
||||
<pre> |
||||
<card> |
||||
... |
||||
</card> |
||||
</pre> |
||||
</aside> |
||||
</section> |
||||
|
||||
<hr> |
||||
<section> |
||||
<p>I demonstrate the idea with a series of copies of existing websites and other layout problems |
||||
people frequently encounter. If you have a suggested layout challenge for me, then tell me on Twitter <a href="https://twitter.com/lzsthw">@lzsthw</a> and I'll give it a shot. |
||||
</p> |
||||
<a href="/demos" use:link><button>View The Demos</button></a> |
||||
</section> |
||||
|
||||
< |