Use eslint-config-awzzm-vue, refactor some code and improve NavigationBar.vue
This commit is contained in:
parent
eb9ad07a86
commit
37e43d4098
23 changed files with 2141 additions and 1842 deletions
|
@ -1,13 +0,0 @@
|
||||||
# editorconfig.org
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
trim_trailing_whitespace = false
|
|
31
.eslintrc.js
31
.eslintrc.js
|
@ -1,27 +1,12 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"root": true,
|
root: true,
|
||||||
"env": {
|
extends: [
|
||||||
browser: true,
|
|
||||||
node: true,
|
|
||||||
es6: true
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"parser": "babel-eslint"
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"plugin:nuxt/recommended",
|
"plugin:nuxt/recommended",
|
||||||
"@moritzruth",
|
"awzzm-vue/nuxt"
|
||||||
"@moritzruth/eslint-config/vue"
|
|
||||||
],
|
],
|
||||||
rules: {
|
parserOptions: {
|
||||||
"no-unused-vars": "warn",
|
parser: "babel-eslint",
|
||||||
"vue/no-unused-components": "warn"
|
ecmaVersion: 11,
|
||||||
},
|
sourceType: "module"
|
||||||
"settings": {
|
|
||||||
"import/resolver": {
|
|
||||||
webpack: {
|
|
||||||
config: "webpack.resolve.js"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
|
/* global workbox */
|
||||||
|
|
||||||
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
|
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
|
||||||
workbox.routing.registerRoute(
|
workbox.routing.registerRoute(
|
||||||
/^https:\/\/fonts\.googleapis\.com/,
|
/^https:\/\/fonts\.googleapis\.com/u,
|
||||||
new workbox.strategies.StaleWhileRevalidate({ cacheName: "google-fonts-stylesheets" })
|
new workbox.strategies.StaleWhileRevalidate({ cacheName: "google-fonts-stylesheets" })
|
||||||
);
|
)
|
||||||
|
|
||||||
// Cache the underlying font files with a cache-first strategy for 1 year.
|
// Cache the underlying font files with a cache-first strategy for 1 year.
|
||||||
workbox.routing.registerRoute(
|
workbox.routing.registerRoute(
|
||||||
/^https:\/\/fonts\.gstatic\.com/,
|
/^https:\/\/fonts\.gstatic\.com/u,
|
||||||
new workbox.strategies.CacheFirst({
|
new workbox.strategies.CacheFirst({
|
||||||
cacheName: "google-fonts-webfonts",
|
cacheName: "google-fonts-webfonts",
|
||||||
plugins: [
|
plugins: [
|
||||||
|
@ -19,4 +20,4 @@ workbox.routing.registerRoute(
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ export const footerItems = [
|
||||||
to: "/legal-notice"
|
to: "/legal-notice"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Privacy Policy",
|
label: "Privacy",
|
||||||
to: "/privacy-policy"
|
to: "/privacy"
|
||||||
}
|
}
|
||||||
];
|
]
|
|
@ -1,7 +1,7 @@
|
||||||
import _kebabCase from "lodash.kebabcase";
|
import _kebabCase from "lodash.kebabcase"
|
||||||
|
|
||||||
export function toModifierClasses(base, classes) {
|
export function toModifierClasses(base, classes) {
|
||||||
return Object.entries(classes)
|
return Object.entries(classes)
|
||||||
.filter(([, value]) => Boolean(value))
|
.filter(([, value]) => Boolean(value))
|
||||||
.map(([key]) => `${base}--${_kebabCase(key)}`);
|
.map(([key]) => `${base}--${_kebabCase(key)}`)
|
||||||
}
|
}
|
|
@ -125,5 +125,5 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "AnimatedLogo"
|
name: "AnimatedLogo"
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -31,44 +31,32 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ExternalIcon from "@/assets/icons/external.svg";
|
import ExternalIcon from "@/assets/icons/external.svg"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ExternalLink",
|
name: "ExternalLink",
|
||||||
components: { ExternalIcon },
|
components: { ExternalIcon },
|
||||||
props: {
|
props: {
|
||||||
href: {
|
href: { type: String, required: true },
|
||||||
type: String,
|
showProtocol: { type: Boolean },
|
||||||
required: true
|
showQuery: { type: Boolean }
|
||||||
},
|
|
||||||
showProtocol: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
showQuery: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
label() {
|
label() {
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const url = new (process.server ? require("url").URL : window.URL)(this.href);
|
const url = new (process.server ? require("url").URL : window.URL)(this.href)
|
||||||
let label = "";
|
let label = ""
|
||||||
|
|
||||||
if (this.showProtocol) {
|
if (this.showProtocol) {
|
||||||
label += url.protocol;
|
label += url.protocol
|
||||||
label += "//";
|
label += "//"
|
||||||
}
|
}
|
||||||
|
|
||||||
label += url.host + url.pathname;
|
label += url.host + url.pathname
|
||||||
|
|
||||||
if (this.showQuery) {
|
if (this.showQuery) label += url.search
|
||||||
label += url.search;
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
return label;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -126,30 +126,12 @@
|
||||||
export default {
|
export default {
|
||||||
name: "MyButton",
|
name: "MyButton",
|
||||||
props: {
|
props: {
|
||||||
to: {
|
to: { type: String, default: "" },
|
||||||
type: String,
|
href: { type: String, default: "" },
|
||||||
default: ""
|
loading: { type: Boolean },
|
||||||
},
|
disabled: { type: Boolean },
|
||||||
href: {
|
isSubmit: { type: Boolean },
|
||||||
type: String,
|
center: { type: Boolean }
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
loading: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
isSubmit: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
center: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isExternalLink: vm => Boolean(vm.href),
|
isExternalLink: vm => Boolean(vm.href),
|
||||||
|
@ -157,28 +139,27 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
if (!this.disabled && !this.loading) {
|
if (!this.disabled && !this.loading)
|
||||||
this.$emit("click", event);
|
this.$emit("click", event)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render(h) {
|
render(h) {
|
||||||
const children = [];
|
const children = []
|
||||||
|
|
||||||
if (this.$slots.prefix) {
|
if (this.$slots.prefix) {
|
||||||
children.push(h("div", {
|
children.push(h("div", {
|
||||||
class: "my-button__prefix"
|
class: "my-button__prefix"
|
||||||
}, this.$slots.prefix));
|
}, this.$slots.prefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
children.push(h("div", {
|
children.push(h("div", {
|
||||||
class: "my-button__text"
|
class: "my-button__text"
|
||||||
}, this.$slots.default));
|
}, this.$slots.default))
|
||||||
|
|
||||||
if (this.$slots.suffix) {
|
if (this.$slots.suffix) {
|
||||||
h("div", {
|
h("div", {
|
||||||
class: "my-button__suffix"
|
class: "my-button__suffix"
|
||||||
}, this.$slots.suffix);
|
}, this.$slots.suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseOptions = {
|
const baseOptions = {
|
||||||
|
@ -203,7 +184,7 @@
|
||||||
attrs: {
|
attrs: {
|
||||||
tabindex: this.disabled || this.loading ? "-1" : "0"
|
tabindex: this.disabled || this.loading ? "-1" : "0"
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (this.isInternalLink) {
|
if (this.isInternalLink) {
|
||||||
return h("nuxt-link", {
|
return h("nuxt-link", {
|
||||||
|
@ -211,7 +192,7 @@
|
||||||
props: {
|
props: {
|
||||||
to: this.to
|
to: this.to
|
||||||
}
|
}
|
||||||
}, children);
|
}, children)
|
||||||
} else if (this.isExternalLink) {
|
} else if (this.isExternalLink) {
|
||||||
return h("a", {
|
return h("a", {
|
||||||
...baseOptions,
|
...baseOptions,
|
||||||
|
@ -220,7 +201,7 @@
|
||||||
href: this.href,
|
href: this.href,
|
||||||
rel: "noopener"
|
rel: "noopener"
|
||||||
}
|
}
|
||||||
}, children);
|
}, children)
|
||||||
}
|
}
|
||||||
|
|
||||||
return h("button", {
|
return h("button", {
|
||||||
|
@ -230,7 +211,7 @@
|
||||||
disabled: this.disabled,
|
disabled: this.disabled,
|
||||||
type: this.isSubmit ? "submit" : "button"
|
type: this.isSubmit ? "submit" : "button"
|
||||||
}
|
}
|
||||||
}, children);
|
}, children)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<footer class="my-footer">
|
<footer class="my-footer">
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-for="item in $options.items"
|
v-for="item in $options.items"
|
||||||
class="my-footer__link"
|
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
|
class="my-footer__link"
|
||||||
:to="item.to"
|
:to="item.to"
|
||||||
@click.native.passive="open = false"
|
@click.native.passive="open = false"
|
||||||
>
|
>
|
||||||
|
@ -55,10 +55,10 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { footerItems } from "@/assets/js/footerItems";
|
import { footerItems } from "assets/js/footer-items"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MyFooter",
|
name: "MyFooter",
|
||||||
items: footerItems
|
items: footerItems
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -16,29 +16,22 @@
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-bar__links">
|
<div class="navigation-bar__links">
|
||||||
<div
|
|
||||||
v-for="item in $options.items"
|
|
||||||
class="navigation-bar__link-container"
|
|
||||||
:key="item.label"
|
|
||||||
>
|
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-if="item.to"
|
v-for="item in $options.items"
|
||||||
|
:key="item.label"
|
||||||
class="navigation-bar__link"
|
class="navigation-bar__link"
|
||||||
|
:exact="item.to === '/'"
|
||||||
:to="item.to"
|
:to="item.to"
|
||||||
@click.native.passive="open = false"
|
@click.native="open = false"
|
||||||
|
@mouseenter.native="e => handleLinkEvent(e, true)"
|
||||||
|
@focus.native="e => handleLinkEvent(e, true)"
|
||||||
|
@mouseleave.native="e => handleLinkEvent(e, false)"
|
||||||
|
@blur.native="e => handleLinkEvent(e, false)"
|
||||||
>
|
>
|
||||||
|
<span class="navigation-bar__link-text">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
|
</span>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<a
|
|
||||||
v-else
|
|
||||||
class="navigation-bar__link"
|
|
||||||
rel="noopener"
|
|
||||||
:href="item.href"
|
|
||||||
@click.passive="open = false"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -147,9 +140,10 @@
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-bar__link-container {
|
.navigation-bar__link {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: white;
|
background: white;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -175,24 +169,33 @@
|
||||||
transition: 200ms opacity ease;
|
transition: 200ms opacity ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover, &:focus-within {
|
&:hover, &:focus, &.nuxt-link-active {
|
||||||
&::before {
|
&::before {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-bar__link {
|
.navigation-bar__link-text {
|
||||||
$offset: -3px;
|
$offset: -3px;
|
||||||
|
|
||||||
outline: none;
|
|
||||||
transform: translate($offset, $offset);
|
transform: translate($offset, $offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-bar__link {
|
.navigation-bar--hide-active-state {
|
||||||
|
.navigation-bar__link.nuxt-link-active {
|
||||||
|
&::before {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-bar__link-text {
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-bar__link-text {
|
||||||
display: block;
|
display: block;
|
||||||
color: colors.$background-c;
|
color: colors.$background-c;
|
||||||
text-decoration: none;
|
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
|
||||||
background: colors.$background;
|
background: colors.$background;
|
||||||
|
@ -261,19 +264,19 @@
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-bar__link-container:not(:last-child) {
|
.navigation-bar__link:not(:last-child) {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
margin-right: 40px;
|
margin-right: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation-bar__link {
|
.navigation-bar__link-text {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { toModifierClasses } from "@/assets/js/toModifierClasses";
|
import { toModifierClasses } from "assets/js/to-modifier-classes"
|
||||||
|
|
||||||
const ITEMS = [
|
const ITEMS = [
|
||||||
{
|
{
|
||||||
|
@ -284,49 +287,50 @@
|
||||||
label: "Projects",
|
label: "Projects",
|
||||||
to: "/projects"
|
to: "/projects"
|
||||||
}
|
}
|
||||||
];
|
]
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "NavigationBar",
|
name: "NavigationBar",
|
||||||
props: {
|
props: {
|
||||||
backgroundAfterScroll: {
|
backgroundAfterScroll: { type: Boolean },
|
||||||
type: Boolean,
|
title: { type: String, default: "" }
|
||||||
default: false
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ""
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
open: false,
|
open: false,
|
||||||
scrollPosition: 0
|
scrollPosition: 0,
|
||||||
|
hideActiveState: false
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
showTitle: vm => vm.scrollPosition > 60,
|
showTitle: vm => vm.scrollPosition > 60,
|
||||||
showBackground: vm => vm.backgroundAfterScroll ? vm.scrollPosition > 0 : true,
|
showBackground: vm => vm.backgroundAfterScroll ? vm.scrollPosition > 0 : true,
|
||||||
classes() {
|
classes() {
|
||||||
const { open, showBackground } = this;
|
const { open, showBackground, hideActiveState } = this
|
||||||
|
|
||||||
return toModifierClasses("navigation-bar", {
|
return toModifierClasses("navigation-bar", {
|
||||||
open,
|
open,
|
||||||
showBackground
|
showBackground,
|
||||||
});
|
hideActiveState
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const scrollListener = () => {
|
const scrollListener = () => {
|
||||||
this.scrollPosition = window.scrollY;
|
this.scrollPosition = window.scrollY
|
||||||
};
|
}
|
||||||
|
|
||||||
window.addEventListener("scroll", scrollListener, { passive: true });
|
window.addEventListener("scroll", scrollListener, { passive: true })
|
||||||
|
|
||||||
this.$on("hook:beforeDestroy", () => {
|
this.$on("hook:beforeDestroy", () => {
|
||||||
window.removeEventListener("scroll", scrollListener);
|
window.removeEventListener("scroll", scrollListener)
|
||||||
});
|
})
|
||||||
|
|
||||||
scrollListener();
|
scrollListener()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleLinkEvent(event, hideActiveStateNow) {
|
||||||
|
if (!event.target.classList.contains("nuxt-link-active")) this.hideActiveState = hideActiveStateNow
|
||||||
|
}
|
||||||
},
|
},
|
||||||
items: ITEMS
|
items: ITEMS
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="my-project__description">
|
<div class="my-project__description">
|
||||||
<slot/>
|
<slot/>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-project__links" v-if="github || npm || url">
|
<div v-if="github || npm || url" class="my-project__links">
|
||||||
<MyButton
|
<MyButton
|
||||||
v-if="url !== ''"
|
v-if="url !== ''"
|
||||||
class="my-project__link"
|
class="my-project__link"
|
||||||
|
@ -108,10 +108,10 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MyButton from "@/components/MyButton";
|
import MyButton from "@/components/MyButton"
|
||||||
import GitHubIcon from "@/assets/icons/github.svg";
|
import GitHubIcon from "@/assets/icons/github.svg"
|
||||||
import NPMIcon from "@/assets/icons/npm.svg";
|
import NPMIcon from "@/assets/icons/npm.svg"
|
||||||
import PointerRightIcon from "@/assets/icons/pointer-right.svg";
|
import PointerRightIcon from "@/assets/icons/pointer-right.svg"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MyProject",
|
name: "MyProject",
|
||||||
|
@ -138,5 +138,5 @@
|
||||||
default: ""
|
default: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MyFooter from "@/components/MyFooter";
|
import MyFooter from "@/components/MyFooter"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "DefaultLayout",
|
name: "DefaultLayout",
|
||||||
components: { MyFooter }
|
components: { MyFooter }
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -9,5 +9,5 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "EmptyLayout"
|
name: "EmptyLayout"
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
7
manifest.json
Normal file
7
manifest.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "Moritz Ruth",
|
||||||
|
"short_name": "Moritz Ruth",
|
||||||
|
"background_color": "#000000",
|
||||||
|
"display": "browser",
|
||||||
|
"description": "Moritz Ruth creates things."
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
/* eslint-disable camelcase */
|
import manifest from "./manifest.json"
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default {
|
export default {
|
||||||
mode: "spa",
|
mode: "spa",
|
||||||
|
@ -6,7 +7,7 @@ export default {
|
||||||
** Headers of the page
|
** Headers of the page
|
||||||
*/
|
*/
|
||||||
head: {
|
head: {
|
||||||
titleTemplate: "%s | Moritz Ruth",
|
titleTemplate: `%s | ${manifest.name}`,
|
||||||
link: [
|
link: [
|
||||||
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
|
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
|
||||||
{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;600&display=swap" }
|
{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;600&display=swap" }
|
||||||
|
@ -49,31 +50,13 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
viewport: "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0",
|
viewport: "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0",
|
||||||
mobileApp: false,
|
mobileApp: false,
|
||||||
name: "Moritz Ruth",
|
name: manifest.name,
|
||||||
author: "Moritz Ruth",
|
author: "Moritz Ruth",
|
||||||
description: "Moritz Ruth is a web developer, photograph and digital creator.",
|
description: manifest.description,
|
||||||
lang: "en",
|
lang: "en",
|
||||||
themeColor: "#000000"
|
themeColor: "#000000"
|
||||||
},
|
},
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/Manifest
|
// https://developer.mozilla.org/en-US/docs/Web/Manifest
|
||||||
manifest: {
|
manifest
|
||||||
name: "Moritz Ruth",
|
|
||||||
short_name: "Moritz Ruth",
|
|
||||||
background_color: "#000000",
|
|
||||||
display: "browser",
|
|
||||||
description: "Moritz Ruth is a web developer, photograph and digital creator."
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Build configuration
|
|
||||||
*/
|
|
||||||
build: {
|
|
||||||
/*
|
|
||||||
** You can extend webpack config here
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
extend(config, context) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
19
package.json
19
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "moritzruth.de",
|
"name": "moritzruth.de",
|
||||||
"description": "Moritz Ruth is a web developer, photograph and digital creator.",
|
"description": "Ny personal website",
|
||||||
"author": "Moritz Ruth",
|
"author": "Moritz Ruth <dev@moritzruth.de>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "HOST=0.0.0.0 nuxt",
|
"dev": "HOST=0.0.0.0 nuxt",
|
||||||
|
@ -12,22 +12,21 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxtjs/pwa": "^3.0.0-beta.20",
|
"@nuxtjs/pwa": "^3.0.0-beta.20",
|
||||||
"lodash.kebabcase": "^4.1.1",
|
"lodash.kebabcase": "^4.1.1",
|
||||||
"nuxt": "^2.12.2",
|
"nuxt": "^2.14.0",
|
||||||
"shaped.js": "^1.0.3",
|
"shaped.js": "^2.0.0",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-ripple-directive": "^2.0.1"
|
"vue-ripple-directive": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@moritzruth/eslint-config": "^2.0.5",
|
"@nuxt/types": "^2.14.1",
|
||||||
"@nuxtjs/eslint-module": "^2.0.0",
|
"@nuxtjs/eslint-module": "^2.0.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.6.0",
|
||||||
"eslint-import-resolver-webpack": "^0.12.1",
|
"eslint-config-awzzm-vue": "^1.0.2",
|
||||||
"eslint-plugin-nuxt": "^1.0.0",
|
"eslint-plugin-nuxt": "^1.0.0",
|
||||||
"fibers": "^5.0.0",
|
"fibers": "^5.0.0",
|
||||||
"sass": "^1.26.3",
|
"sass": "^1.26.10",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^9.0.2",
|
||||||
"serve": "^11.3.0",
|
|
||||||
"svg-to-vue-component": "^0.3.8"
|
"svg-to-vue-component": "^0.3.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="index-page">
|
<div class="index-page">
|
||||||
<NavigationBar background-after-scroll title="Start"/>
|
<NavigationBar background-after-scroll title="Start"/>
|
||||||
<canvas class="index-page__background" ref="canvas"/>
|
<canvas ref="canvas" class="index-page__background"/>
|
||||||
<main class="index-page__content">
|
<main class="index-page__content">
|
||||||
<AnimatedLogo/>
|
<AnimatedLogo/>
|
||||||
<div class="index-page__socials">
|
<div class="index-page__socials">
|
||||||
|
@ -12,7 +12,8 @@
|
||||||
><InstagramIcon class="index-page__social-icon"/></a>
|
><InstagramIcon class="index-page__social-icon"/></a>
|
||||||
<a
|
<a
|
||||||
class="index-page__social"
|
class="index-page__social"
|
||||||
href="https://twitter.com/moritz_ruth"
|
href="httpsU
|
||||||
|
://twitter.com/moritz_ruth"
|
||||||
title="Twitter"
|
title="Twitter"
|
||||||
><TwitterIcon class="index-page__social-icon"/></a>
|
><TwitterIcon class="index-page__social-icon"/></a>
|
||||||
<a
|
<a
|
||||||
|
@ -34,10 +35,10 @@
|
||||||
<footer class="index-page__footer">
|
<footer class="index-page__footer">
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-for="item in $options.footerItems"
|
v-for="item in $options.footerItems"
|
||||||
class="index-page__footer-link"
|
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
|
class="index-page__footer-link"
|
||||||
:to="item.to"
|
:to="item.to"
|
||||||
@click.native.passive="open = false"
|
@click.native.passive="() => { open = null }"
|
||||||
>
|
>
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
|
@ -154,68 +155,34 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Canvas } from "shaped.js";
|
import { ShapedCanvas } from "shaped.js"
|
||||||
import AnimatedLogo from "@/components/AnimatedLogo";
|
import AnimatedLogo from "@/components/AnimatedLogo"
|
||||||
import NavigationBar from "@/components/NavigationBar";
|
import NavigationBar from "@/components/NavigationBar"
|
||||||
import { footerItems } from "@/assets/js/footerItems";
|
import { footerItems } from "assets/js/footer-items"
|
||||||
import InstagramIcon from "@/assets/icons/instagram.svg";
|
import InstagramIcon from "@/assets/icons/instagram.svg"
|
||||||
import TwitterIcon from "@/assets/icons/twitter.svg";
|
import TwitterIcon from "@/assets/icons/twitter.svg"
|
||||||
import NPMIcon from "@/assets/icons/npm.svg";
|
import NPMIcon from "@/assets/icons/npm.svg"
|
||||||
import GitHubIcon from "@/assets/icons/github.svg";
|
import GitHubIcon from "@/assets/icons/github.svg"
|
||||||
import EmailIcon from "@/assets/icons/email.svg";
|
import EmailIcon from "@/assets/icons/email.svg"
|
||||||
|
|
||||||
const LINES = [
|
|
||||||
{
|
|
||||||
minCount: 8,
|
|
||||||
probability: 1 / 30000,
|
|
||||||
height: 1,
|
|
||||||
length: [80, 150],
|
|
||||||
speed: [0.2, 0.5],
|
|
||||||
colors: [
|
|
||||||
"#BB2081",
|
|
||||||
"#14AAD8"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "IndexPage",
|
name: "IndexPage",
|
||||||
layout: "empty",
|
layout: "empty",
|
||||||
head: () => ({ title: "Moritz Ruth", titleTemplate: "%s" }),
|
|
||||||
components: { NavigationBar, AnimatedLogo, InstagramIcon, TwitterIcon, NPMIcon, GitHubIcon, EmailIcon },
|
components: { NavigationBar, AnimatedLogo, InstagramIcon, TwitterIcon, NPMIcon, GitHubIcon, EmailIcon },
|
||||||
mounted() {
|
mounted() {
|
||||||
let configIndex = 0;
|
const shaped = new ShapedCanvas(this.$refs.canvas, {
|
||||||
|
useWindowSize: true,
|
||||||
|
colors: ["#BB2081", "#14AAD8"],
|
||||||
|
minCount: 8,
|
||||||
|
probability: 1 / 30000,
|
||||||
|
height: 1,
|
||||||
|
length: [80, 150],
|
||||||
|
speed: [0.2, 0.5]
|
||||||
|
})
|
||||||
|
|
||||||
if (localStorage !== undefined) {
|
this.$once("hook:beforeDestroy", () => shaped.stop())
|
||||||
const rawValue = localStorage.getItem("nextBackground");
|
|
||||||
|
|
||||||
if (rawValue) {
|
|
||||||
try {
|
|
||||||
configIndex = JSON.parse(rawValue);
|
|
||||||
} catch {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configIndex > LINES.length - 1) {
|
|
||||||
configIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localStorage !== undefined) {
|
|
||||||
localStorage.setItem("nextBackground", JSON.stringify(configIndex + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = LINES[configIndex];
|
|
||||||
const backgroundCanvas = new Canvas(this.$refs.canvas, {
|
|
||||||
lines: config,
|
|
||||||
fillWindowSize: true
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$once("hook:beforeDestroy", () => {
|
|
||||||
backgroundCanvas.destroy();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
head: () => ({ title: "Moritz Ruth creates things", titleTemplate: "%s" }),
|
||||||
footerItems
|
footerItems
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavigationBar from "../components/NavigationBar";
|
import NavigationBar from "../components/NavigationBar"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "LegalNoticePage",
|
name: "LegalNoticePage",
|
||||||
|
@ -75,5 +75,5 @@
|
||||||
htmlAttrs: { lang: "de" },
|
htmlAttrs: { lang: "de" },
|
||||||
title: "Legal notice"
|
title: "Legal notice"
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -284,8 +284,8 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ExternalLink from "@/components/ExternalLink";
|
import ExternalLink from "@/components/ExternalLink"
|
||||||
import NavigationBar from "@/components/NavigationBar";
|
import NavigationBar from "@/components/NavigationBar"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PrivacyPolicyPage",
|
name: "PrivacyPolicyPage",
|
||||||
|
@ -294,5 +294,5 @@
|
||||||
htmlAttrs: { lang: "de" },
|
htmlAttrs: { lang: "de" },
|
||||||
title: "Privacy Policy"
|
title: "Privacy Policy"
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
|
@ -67,12 +67,12 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavigationBar from "@/components/NavigationBar";
|
import NavigationBar from "@/components/NavigationBar"
|
||||||
import MyProject from "@/components/pages/projects/MyProject";
|
import MyProject from "@/components/pages/projects/MyProject"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ProjectsPage",
|
name: "ProjectsPage",
|
||||||
components: { MyProject, NavigationBar },
|
components: { MyProject, NavigationBar },
|
||||||
head: () => ({ title: "Projects" })
|
head: () => ({ title: "Projects" })
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue"
|
||||||
import Ripple from "vue-ripple-directive";
|
import Ripple from "vue-ripple-directive"
|
||||||
|
|
||||||
Vue.directive("ripple", Ripple);
|
Vue.directive("ripple", Ripple)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
// Used by ESLint and WebStorm
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
"@": path.resolve(__dirname),
|
|
||||||
"~": path.resolve(__dirname)
|
|
||||||
},
|
|
||||||
extensions: [".vue", ".js"]
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue