Migrate to SvelteKit and Vite

This commit is contained in:
2023-08-06 18:52:31 +02:00
parent 868a46302c
commit cd93d7442f
39 changed files with 2038 additions and 2044 deletions

View File

@@ -1,196 +0,0 @@
<script>
import ThemeWrapper from "./../node_modules/svelte-themer/components/ThemeWrapper.svelte";
import Matrix from "./Matrix.svelte";
import MatrixSizeInput from "./MatrixSizeInput.svelte";
import { themes } from "./themes";
import ThemeToggle from "./ThemeToggle.svelte";
let matrixWidth = 4;
let matrixHeight = 4;
let kernelWidth = 3;
let kernelHeight = 3;
let padding = 0;
let addPadding = true;
$: matrix = initMatrix(matrixWidth, matrixHeight, 1);
$: kernel = initMatrix(kernelWidth, kernelHeight, 1);
$: result = applyKernelFilter(matrix, kernel, addPadding, padding);
function initMatrix(width, height, value) {
return width > 0 && height > 0
? Array(Math.floor(height))
.fill(value)
.map(() => Array(Math.floor(width)).fill(value))
: [[]];
}
function applyKernelFilter(matrix, kernel, addPadding, padding = 0) {
let kernelHeight = kernel.length;
let kernelWidth = kernel[0].length;
let matrixHeight = matrix.length;
let matrixWidth = matrix[0].length;
let result = initMatrix(matrixWidth, matrixHeight, 0);
let kernelCenterX = Math.floor(kernelWidth / 2);
let kernelCenterY = Math.floor(kernelHeight / 2);
for (let i = 0; i < matrixHeight; i++) {
for (let j = 0; j < matrixWidth; j++) {
for (let m = 0; m < kernelHeight; m++) {
for (let n = 0; n < kernelWidth; n++) {
let ii = i + (m - kernelCenterY);
let jj = j + (n - kernelCenterX);
if (ii >= 0 && ii < matrixHeight && jj >= 0 && jj < matrixWidth) {
result[i][j] += matrix[ii][jj] * kernel[m][n];
} else {
result[i][j] += padding * kernel[m][n];
}
}
}
}
}
if (!addPadding && kernelCenterX > 0 && kernelCenterY > 0)
result =
kernelHeight >= matrixHeight || kernelWidth >= matrixWidth
? [[]]
: result
.slice(kernelCenterY, -kernelCenterY)
.map((r) => r.slice(kernelCenterX, -kernelCenterX));
return result;
}
</script>
<ThemeWrapper {themes} key="kernel-filter-calculator__theme">
<div class="container">
<header><h1>Matrix Kernel Filter Calculator</h1></header>
<main>
<h5 style="grid-area: matrix-title">Matrix</h5>
<h5 style="grid-area: kernel-title">Kernel</h5>
<h5 style="grid-area: result-title">Result</h5>
<div style="grid-area: matrix-size" data-test="matrix-size">
<MatrixSizeInput bind:matrixWidth bind:matrixHeight />
</div>
<div style="grid-area: kernel-size" data-test="kernel-size">
<MatrixSizeInput
bind:matrixWidth={kernelWidth}
bind:matrixHeight={kernelHeight}
/>
</div>
<div style="grid-area: result-size">
{result[0].length} &times; {result.length}
</div>
<div style="grid-area: matrix" data-test="matrix">
<Matrix bind:matrix />
</div>
<div style="grid-area: kernel" data-test="kernel">
<Matrix bind:matrix={kernel} />
</div>
<div style="grid-area: result" data-test="result">
<Matrix matrix={result} readonly="true" />
</div>
<div style="grid-area: padding">
<label>
<input
type="checkbox"
bind:checked={addPadding}
data-test="padding"
/>
Padding
</label>
<div>
<input
type="number"
bind:value={padding}
style="width: 3em;"
onclick="select()"
/>
</div>
</div>
</main>
<footer>
<div class="left"><ThemeToggle /></div>
<div class="center">
<a
href="https://github.com/mschuepbach/matrix-kernel-filter-calculator"
target="_blank"
title="GitHub Repository"
>
<img src="./GitHub-Mark.svg" alt="GitHub Repository" width="32px" />
</a>
</div>
<div class="right" />
</footer>
</div>
</ThemeWrapper>
<style>
:global(html) {
background-color: var(--theme-colors-background, initial);
color: var(--theme-colors-text, initial);
}
:global(input) {
color: var(--theme-colors-text, initial);
border-color: var(--theme-colors-input-border, initial);
background-color: var(--theme-colors-input-background, initial);
}
:global(button) {
color: var(--theme-colors-text, initial);
}
h5 {
margin: 1em 0 0;
}
.container {
text-align: center;
height: 100%;
display: flex;
flex-direction: column;
}
header {
margin-bottom: 1em;
}
main {
display: grid;
margin-bottom: auto;
grid-template-areas:
"matrix-title kernel-title result-title"
"matrix-size kernel-size result-size"
"matrix kernel result"
"padding padding padding";
grid-gap: 0.8em;
align-items: center;
}
@media (max-width: 960px) {
main {
grid-template-areas:
"matrix-title"
"matrix-size"
"matrix"
"kernel-title"
"kernel-size"
"kernel"
"result-title"
"result-size"
"result"
"padding";
}
}
footer {
display: flex;
margin-top: 1em;
text-align: left;
}
.left,
.right {
flex: 1;
}
</style>

View File

@@ -1,31 +0,0 @@
<script>
export let matrix = [[]];
export let readonly = false;
</script>
<div>
{#each matrix as row, i}
<div class="row">
{#each row as _, j}
<input
type="number"
bind:value={matrix[i][j]}
onclick="select()"
{readonly}
/>
{/each}
</div>
{/each}
</div>
<style>
input {
width: 3em;
}
.row {
display: flex;
flex-direction: row;
justify-content: center;
}
</style>

View File

@@ -1,16 +0,0 @@
<script>
export let matrixWidth = 3;
export let matrixHeight = 3;
</script>
<div>
<input type="number" min="1" bind:value={matrixWidth} onclick="select()" />
<span>&times;</span>
<input type="number" min="1" bind:value={matrixHeight} onclick="select()" />
</div>
<style>
input {
width: 3em;
}
</style>

View File

@@ -1,17 +0,0 @@
<script>
import { getContext } from "svelte";
let { toggle, current } = getContext("theme");
</script>
<button on:click={toggle} title="Toggle Theme" data-test="toggle-theme">
<slot>{$current}</slot>
</button>
<style>
button {
border: none;
background: none;
font-weight: 600;
cursor: pointer;
}
</style>

13
src/app.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" class="svg-inline--fa fa-github" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,7 +0,0 @@
import App from './App.svelte';
const app = new App({
target: document.body,
});
export default app;

57
src/routes/+layout.svelte Normal file
View File

@@ -0,0 +1,57 @@
<script>
import github from '$lib/images/github.svg';
import { ThemeWrapper } from 'svelte-themer';
import ThemeToggle from './ThemeToggle.svelte';
import './styles.css';
import { themes } from './themes';
</script>
<ThemeWrapper {themes} key="kernel-filter-calculator__theme">
<div class="container">
<header><h1>Matrix Kernel Filter Calculator</h1></header>
<main>
<slot />
</main>
<footer>
<div class="left"><ThemeToggle /></div>
<div class="center">
<a
href="https://github.com/mschuepbach/matrix-kernel-filter-calculator"
target="_blank"
title="GitHub Repository"
>
<img src={github} alt="GitHub Repository" width="32px" />
</a>
</div>
<div class="right" />
</footer>
</div>
</ThemeWrapper>
<style>
.container {
text-align: center;
height: 100%;
display: flex;
flex-direction: column;
}
header {
margin-bottom: 1em;
}
main {
flex-grow: 1;
}
footer {
display: flex;
margin-top: 1em;
text-align: left;
}
.left,
.right {
flex: 1;
}
</style>

1
src/routes/+page.js Normal file
View File

@@ -0,0 +1 @@
export const prerender = true;

131
src/routes/+page.svelte Normal file
View File

@@ -0,0 +1,131 @@
<script>
import Matrix from './Matrix.svelte';
import MatrixSizeInput from './MatrixSizeInput.svelte';
let matrixWidth = 4;
let matrixHeight = 4;
let kernelWidth = 3;
let kernelHeight = 3;
let padding = 0;
let addPadding = true;
$: matrix = initMatrix(matrixWidth, matrixHeight, 1);
$: kernel = initMatrix(kernelWidth, kernelHeight, 1);
$: result = applyKernelFilter(matrix, kernel, addPadding, padding);
function initMatrix(width, height, value) {
return width > 0 && height > 0
? Array(Math.floor(height))
.fill(value)
.map(() => Array(Math.floor(width)).fill(value))
: [[]];
}
function applyKernelFilter(matrix, kernel, addPadding, padding = 0) {
let kernelHeight = kernel.length;
let kernelWidth = kernel[0].length;
let matrixHeight = matrix.length;
let matrixWidth = matrix[0].length;
let result = initMatrix(matrixWidth, matrixHeight, 0);
let kernelCenterX = Math.floor(kernelWidth / 2);
let kernelCenterY = Math.floor(kernelHeight / 2);
for (let i = 0; i < matrixHeight; i++) {
for (let j = 0; j < matrixWidth; j++) {
for (let m = 0; m < kernelHeight; m++) {
for (let n = 0; n < kernelWidth; n++) {
let ii = i + (m - kernelCenterY);
let jj = j + (n - kernelCenterX);
if (ii >= 0 && ii < matrixHeight && jj >= 0 && jj < matrixWidth) {
result[i][j] += matrix[ii][jj] * kernel[m][n];
} else {
result[i][j] += padding * kernel[m][n];
}
}
}
}
}
if (!addPadding && kernelCenterX > 0 && kernelCenterY > 0)
result =
kernelHeight >= matrixHeight || kernelWidth >= matrixWidth
? [[]]
: result
.slice(kernelCenterY, -kernelCenterY)
.map((r) => r.slice(kernelCenterX, -kernelCenterX));
return result;
}
</script>
<svelte:head>
<title>Kernel Filter Calculator</title>
<meta name="description" content="Simple calculator for matrix kernel filters" />
</svelte:head>
<div class="content">
<h5 style="grid-area: matrix-title">Matrix</h5>
<h5 style="grid-area: kernel-title">Kernel</h5>
<h5 style="grid-area: result-title">Result</h5>
<div style="grid-area: matrix-size" data-test="matrix-size">
<MatrixSizeInput bind:matrixWidth bind:matrixHeight />
</div>
<div style="grid-area: kernel-size" data-test="kernel-size">
<MatrixSizeInput bind:matrixWidth={kernelWidth} bind:matrixHeight={kernelHeight} />
</div>
<div style="grid-area: result-size">
{result[0].length} &times; {result.length}
</div>
<div style="grid-area: matrix" data-test="matrix">
<Matrix bind:matrix />
</div>
<div style="grid-area: kernel" data-test="kernel">
<Matrix bind:matrix={kernel} />
</div>
<div style="grid-area: result" data-test="result">
<Matrix matrix={result} readonly="true" />
</div>
<div style="grid-area: padding">
<label>
<input type="checkbox" bind:checked={addPadding} data-test="padding" />
Padding
</label>
<div>
<input type="number" bind:value={padding} style="width: 3em;" onclick="select()" />
</div>
</div>
</div>
<style>
h5 {
margin: 1em 0 0;
}
.content {
display: grid;
margin-bottom: auto;
grid-template-areas:
'matrix-title kernel-title result-title'
'matrix-size kernel-size result-size'
'matrix kernel result'
'padding padding padding';
grid-gap: 0.8em;
align-items: center;
}
@media (max-width: 960px) {
.content {
grid-template-areas:
'matrix-title'
'matrix-size'
'matrix'
'kernel-title'
'kernel-size'
'kernel'
'result-title'
'result-size'
'result'
'padding';
}
}
</style>

26
src/routes/Matrix.svelte Normal file
View File

@@ -0,0 +1,26 @@
<script>
export let matrix = [[]];
export let readonly = false;
</script>
<div>
{#each matrix as row, i}
<div class="row">
{#each row as _, j}
<input type="number" bind:value={matrix[i][j]} onclick="select()" {readonly} />
{/each}
</div>
{/each}
</div>
<style>
input {
width: 3em;
}
.row {
display: flex;
flex-direction: row;
justify-content: center;
}
</style>

View File

@@ -0,0 +1,16 @@
<script>
export let matrixWidth = 3;
export let matrixHeight = 3;
</script>
<div>
<input type="number" min="1" bind:value={matrixWidth} onclick="select()" />
<span>&times;</span>
<input type="number" min="1" bind:value={matrixHeight} onclick="select()" />
</div>
<style>
input {
width: 3em;
}
</style>

View File

@@ -0,0 +1,17 @@
<script>
import { getContext } from 'svelte';
const { toggle, current } = getContext('theme');
</script>
<button on:click={toggle} title="Toggle Theme" data-test="toggle-theme">
<slot>{$current}</slot>
</button>
<style>
button {
border: none;
background: none;
font-weight: 600;
cursor: pointer;
}
</style>

54
src/routes/styles.css Normal file
View File

@@ -0,0 +1,54 @@
html,
body {
position: relative;
width: 100%;
height: 100%;
background-color: var(--theme-colors-background, initial);
color: var(--theme-colors-text, initial);
}
body {
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: none;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
'Helvetica Neue', sans-serif;
}
input {
color: var(--theme-colors-text, initial);
border-color: var(--theme-colors-input-border, initial);
background-color: var(--theme-colors-input-background, initial);
}
button {
color: var(--theme-colors-text, initial);
}
input,
button,
select,
textarea {
font-family: inherit;
font-size: inherit;
-webkit-padding: 0.4em 0;
padding: 0.4em;
margin: 0.5em;
box-sizing: border-box;
border-width: 1px;
border-style: solid;
border-radius: 2px;
}
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type='number'] {
-moz-appearance: textfield;
}

34
src/routes/themes.js Normal file
View File

@@ -0,0 +1,34 @@
export const themes = {
light: {
colors: {
text: '#222',
background: {
_: '#fff',
contrast: '#b1b1b1'
},
primary: '#0060df',
primary_dark: '#0250bb',
secondary: '#b000bf',
input: {
border: '#ccc',
background: '#fff'
}
}
},
dark: {
colors: {
text: '#eee',
background: {
_: '#222',
contrast: '#0d1215'
},
primary: '#0060df',
primary_dark: '#0250bb',
secondary: '#b000bf',
input: {
border: '#999',
background: '#222'
}
}
}
};

View File

@@ -1,34 +0,0 @@
export const themes = {
light: {
colors: {
text: "#333",
background: {
_: "#fff",
contrast: "#b1b1b1",
},
primary: "#0060df",
primary_dark: "#0250bb",
secondary: "#b000bf",
input: {
border: "#ccc",
background: "#fff",
},
},
},
dark: {
colors: {
text: "#eee",
background: {
_: "#333",
contrast: "#0d1215",
},
primary: "#0060df",
primary_dark: "#0250bb",
secondary: "#b000bf",
input: {
border: "#999",
background: "#333",
},
},
},
};