Switch from webpack to vite

This commit is contained in:
James Lyne 2021-05-15 20:25:03 +01:00
parent 30cecb98e6
commit ce241c93e0
29 changed files with 2432 additions and 8764 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
VITE_VERSION=0.7.5

View File

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

140
index.html Normal file
View File

@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="preload" href="https://fonts.gstatic.com/s/raleway/v14/1Ptug8zYS_SKggPNyC0ITw.woff2" as="font" crossorigin="anonymous">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="theme-color" content="#222222">
<link rel="manifest" href="/live-atlas/favicons/site.webmanifest">
<link rel="icon" href="/live-atlas/favicons/favicon.svg">
<link rel=”mask-icon” href="/live-atlas/favicons/mask.svg" color="#cccccc">
<link rel="apple-touch-icon" sizes="180x180" href="/live-atlas/favicons/apple-touch-icon.png">
<meta name="keywords" content="minecraft, map, dynamic, liveatlas" />
<meta name="description" content="Minecraft Dynamic Map" />
<title>Minecraft Dynamic Map - LiveAtlas</title>
<style>
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
html, body {
background-color: #121212;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
noscript {
color: #cccccc;
font-size: 1rem;
font-family: sans-serif;
text-align: center;
line-height: 1.25;
}
#splash, noscript {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
transition: 0.3s opacity linear;
z-index: 10000;
background-color: #121212;
cursor: wait;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 1.6rem;
padding: 4rem;
}
#splash[hidden] {
display: none;
}
#splash__spinner {
margin-top: 4rem;
animation: fade 0.5s linear 1s;
animation-fill-mode: both;
}
#splash__error {
margin-top: 2rem;
transition: opacity 0.5s ease-in;
}
#splash__error[aria-hidden=true] {
opacity: 0;
}
#splash__error-attempt:not(:empty):before {
content:' (';
}
#splash__error-attempt:not(:empty):after {
content:')';
}
</style>
</head>
<body>
<div id="splash">
<svg id="splash__logo" width="200" height="200" viewBox="0 0 270.06 267.09">
<g transform="translate(-.49951 -4.5791)">
<path transform="scale(.75)"
d="m0.66602 9.7227v298.96c0.046934 2.8741 0.25213 2.6741 2.535 3.6641l110.65 47.987c3.8989 1.918 3.6147 1.7537 3.6147-2.3528v-297.68c-0.0605-3.8542 0.32855-4.1331-2.8087-5.4937l-110.14-47.768c-2.988-1.1299-3.8517-1.741-3.8517 2.6812zm65.271 177.53c19.088 0 34.562 15.922 34.562 35.562 2.2e-4 6.4076-1.6821 12.696-4.8691 18.201l-25.939 55.648c-1.8045 3.8714-3.0529 3.8185-5.0156-0.0742l-28.344-55.426c-0.68826-1.1762-1.3097-2.3924-1.8613-3.6426l-0.21875-0.42578 0.03711 8e-3c-1.9214-4.5044-2.9137-9.3701-2.9141-14.289 0-19.641 15.474-35.562 34.562-35.562zm0 20.625c-8.0178-6e-5 -14.518 6.6877-14.518 14.938s6.4998 14.938 14.518 14.938c8.0178 6e-5 14.518-6.6877 14.518-14.938s-6.4998-14.938-14.518-14.938z"
fill="#cccccc"/>
<path transform="scale(.75)"
d="m236.43 8.5914-86.609 38.801c-9.3133 4.1592-8.1971 3.54-8.1971 14.952v297.52c-0.0201 2.6943-0.30938 2.8029 2.1555 1.7437l97.364-41.839c2.3162-0.98051 2.0784-1.6006 2.0784-3.5142v-303.35c0.15129-9.1976 0.75524-7.3665-6.7914-4.3133zm-44.714 54.614c19.088 0 34.562 15.922 34.562 35.562-1.9e-4 6.4108-1.6846 12.702-4.875 18.209l-25.934 55.643c-1.8045 3.8714-3.0529 3.8185-5.0156-0.0742l-28.357-55.453c-0.6778-1.1591-1.2908-2.357-1.8359-3.5879l-0.23243-0.45508 0.0391 8e-3c-1.9214-4.5044-2.9136-9.3699-2.9141-14.289 0-19.641 15.474-35.562 34.562-35.562zm0 20.625c-8.0178-6e-5 -14.518 6.6877-14.518 14.938 0 8.2498 6.4998 14.938 14.518 14.938 8.0178 7e-5 14.518-6.6877 14.518-14.938 0-8.2498-6.4998-14.938-14.518-14.938z"
fill="#cccccc"/>
<path d="m267.64 36.871-59.959-29.533c-6.555-3.2203-6.5798-4.161-6.4472 2.3579v225.51c-0.0251 3.9614 0.03 3.9662 3.1935 5.4609l62.579 29.567c3.8853 1.693 3.4322 1.9822 3.5316-1.5506v-224.87c0.0476-4.7459 0.23478-5.4796-2.8976-6.934z"
fill="#cccccc"/>
</g>
</svg>
<svg id="splash__spinner" width="38" height="38" viewBox="0 0 38 38" stroke="#fff">
<g transform="translate(1 1)" stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18" fill="transparent"/>
<path d="M36 18c0-9.94-8.06-18-18-18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</svg>
<div id="splash__error" role="alert" aria-hidden="true">
Failed to load server configuration. Retrying<span id="splash__error-attempt"></span>...
</div>
</div>
<noscript>
<strong>LiveAtlas requires JavaScript to work.<br />Please enable it to continue.</strong>
</noscript>
<div id="mcmap" class="dynmap"></div>
<script src="/standalone/config.js"></script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

10746
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,11 @@
"version": "0.7.5",
"private": false,
"scripts": {
"serve": "vue-cli-service serve ",
"build": "vue-cli-service build --report",
"lint": "vue-cli-service lint",
"postinstall": "node --experimental-modules --experimental-json-modules scripts/fix-leaflet.mjs"
"serve": "vite",
"preview": "vite preview --port 8082",
"build": "vue-tsc --noEmit && vite build --out-dir dist",
"lint": "eslint src",
"lint:fix": "eslint src --fix"
},
"dependencies": {
"core-js": "^3.6.5",
@ -17,24 +18,22 @@
"@types/leaflet": "^1.5.19",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-typescript": "^4.5.9",
"@vue/cli-service": "~4.5.0",
"@vitejs/plugin-vue": "^1.2.2",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-typescript": "^5.0.2",
"babel-eslint": "^10.1.0",
"clipboard": "^2.0.6",
"eslint": "^7.5.0",
"eslint-plugin-vue": "^7.0.0-0",
"leaflet": "^1.7.1",
"normalize-scss": "^7.0.1",
"sass": "^1.29.0",
"sass-loader": "^10.1.0",
"svgo": "^1.1.0",
"svgo-loader": "^2.1.0",
"typescript": "~3.9.3",
"vite": "^2.3.2",
"vite-plugin-svg-sprite-component": "^1.0.8",
"vue-cli-plugin-svg-sprite": "~1.0.0",
"vue-tsc": "^0.1.2",
"vuex": "^4.0.0-rc.1"
},
"eslintConfig": {

View File

@ -25,7 +25,7 @@ import {computed, defineComponent, onBeforeUnmount, onMounted, onUnmounted, ref,
import Map from './components/Map.vue';
import Sidebar from './components/Sidebar.vue';
import ChatBox from './components/ChatBox.vue';
import {useStore} from "./store";
import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {parseUrl} from '@/util';
import {MutationTypes} from "@/store/mutation-types";

View File

@ -15,7 +15,7 @@
-->
<template>
<div class="map" :style="{'background-color': mapBackground }">
<div class="map" :style="{backgroundColor: mapBackground }">
<MapLayer v-for="[name, map] in maps" :key="name" :map="map" :name="name" :leaflet="leaflet"></MapLayer>
<PlayersLayer v-if="playerMarkersEnabled" :leaflet="leaflet"></PlayersLayer>
<MarkerSetLayer v-for="[name, markerSet] in markerSets" :key="name" :markerSet="markerSet" :leaflet="leaflet"></MarkerSetLayer>
@ -60,7 +60,7 @@ export default defineComponent({
setup() {
const store = useStore(),
leaflet = undefined as DynmapMap | undefined,
leaflet = undefined as any,
maps = computed(() => store.state.maps),
markerSets = computed(() => store.state.markerSets),
@ -193,7 +193,7 @@ export default defineComponent({
crs: CRS.Simple,
worldCopyJump: false,
// markerZoomAnimation: false,
}));
})) as DynmapMap;
this.leaflet.createPane('vectors');

View File

@ -45,6 +45,8 @@ import {useStore} from "@/store";
import SvgIcon from "@/components/SvgIcon.vue";
import {MutationTypes} from "@/store/mutation-types";
import {DynmapUIElement} from "@/dynmap";
import "@/assets/icons/players.svg";
import "@/assets/icons/maps.svg";
export default defineComponent({
components: {

View File

@ -39,12 +39,7 @@ export default {
computed: {
iconPath() {
let icon = require(`@/assets/icons/${this.name}.svg`);
if (Object.prototype.hasOwnProperty.call(icon, 'default')) {
icon = icon.default;
}
return icon.url;
return `#${this.name}`;
},
className() {

View File

@ -27,8 +27,7 @@
import {DynmapChat} from "@/dynmap";
import {getMinecraftHead} from '@/util';
import {useStore} from "@/store";
const defaultImage = require('@/assets/images/player_face.png');
import defaultImage from '@/assets/images/player_face.png';
export default defineComponent({
props: {

View File

@ -37,8 +37,7 @@ import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types";
import {defineComponent, onMounted, ref, watch} from "@vue/runtime-core";
import {getMinecraftHead} from '@/util';
const defaultImage = require('@/assets/images/player_face.png');
import defaultImage from '@/assets/images/player_face.png';
export default defineComponent({
name: 'FollowTarget',

View File

@ -31,8 +31,7 @@ import {DynmapPlayer} from "@/dynmap";
import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types";
import {getMinecraftHead} from '@/util';
const defaultImage = require('@/assets/images/player_face.png');
import defaultImage from '@/assets/images/player_face.png';
export default defineComponent({
name: 'PlayerListItem',

View File

@ -33,6 +33,17 @@ import {DynmapWorldMap, DynmapWorld} from "@/dynmap";
import {defineComponent} from 'vue';
import {MutationTypes} from "@/store/mutation-types";
import SvgIcon from "@/components/SvgIcon.vue";
import "@/assets/icons/block_world_surface.svg";
import "@/assets/icons/block_world_cave.svg";
import "@/assets/icons/block_world_biome.svg";
import "@/assets/icons/block_world_flat.svg";
import "@/assets/icons/block_nether_flat.svg";
import "@/assets/icons/block_nether_surface.svg";
import "@/assets/icons/block_the_end_flat.svg";
import "@/assets/icons/block_the_end_surface.svg";
import "@/assets/icons/block_other.svg";
import "@/assets/icons/block_other_flat.svg";
import "@/assets/icons/block_skylands.svg";
export default defineComponent({
name: 'WorldListItem',

2
src/dynmap.d.ts vendored
View File

@ -116,7 +116,7 @@ interface DynmapWorld {
title: string;
height: number;
center: Coordinate;
maps: Map<String, DynmapWorldMap>;
maps: Map<string, DynmapWorldMap>;
}
interface DynmapWorldMap {

26
src/index.d.ts vendored
View File

@ -1,12 +1,20 @@
declare module '*.svg' {
const content: any;
export default content;
import { ComponentCustomProperties } from 'vue'
import {State, Store} from "@/store";
declare module "*.png" {
const value: any;
export = value;
}
interface BrowserSpriteSymbol {
id: string;
viewBox: string;
content: string;
node: SVGSymbolElement;
url: string;
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
declare module '@vue/runtime-core' {
// provide typings for `this.$store`
interface ComponentCustomProperties {
$store: Store<State>
}
}

View File

@ -15,11 +15,12 @@
*/
import {Control, ControlOptions, DomUtil, Map} from 'leaflet';
import chat from '@/assets/icons/chat.svg';
import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types";
import {watch} from "@vue/runtime-core";
import "@/assets/icons/chat.svg";
export class ChatControl extends Control {
// @ts-ignore
options: ControlOptions
@ -34,8 +35,8 @@ export class ChatControl extends Control {
chatButton.type = 'button';
chatButton.title = 'Chat';
chatButton.innerHTML = `
<svg class="svg-icon" viewBox="${chat.viewBox}">
<use xlink:href="${chat.url}" />
<svg class="svg-icon">
<use xlink:href="#chat" />
</svg>`;
chatButton.addEventListener('click', e => {

View File

@ -21,15 +21,16 @@ import {ControlOptions, DomUtil, Util, Map, Control} from 'leaflet';
import {getMinecraftTime} from '@/util';
import {DynmapWorldState} from "@/dynmap";
import sun from '@/assets/icons/clock_sun.svg';
import sunRain from '@/assets/icons/clock_sun_rain.svg';
import sunStorm from '@/assets/icons/clock_sun_storm.svg';
import moon from '@/assets/icons/clock_moon.svg';
import moonRain from '@/assets/icons/clock_moon_rain.svg';
import moonStorm from '@/assets/icons/clock_moon_storm.svg';
import {watch} from "@vue/runtime-core";
import {useStore} from "@/store";
import "@/assets/icons/clock_moon.svg";
import "@/assets/icons/clock_moon_rain.svg";
import "@/assets/icons/clock_moon_storm.svg";
import "@/assets/icons/clock_sun.svg";
import "@/assets/icons/clock_sun_rain.svg";
import "@/assets/icons/clock_sun_storm.svg";
export interface ClockControlOptions extends ControlOptions {
showTimeOfDay: boolean;
showDigitalClock: boolean;
@ -44,8 +45,8 @@ export class ClockControl extends Control {
private _sun?: HTMLElement;
private _moon?: HTMLElement;
private _clock?: HTMLElement;
private _currentMoonIcon?: BrowserSpriteSymbol;
private _currentSunIcon?: BrowserSpriteSymbol;
private _currentMoonIcon?: string;
private _currentSunIcon?: string;
private _unwatchHandler?: Function;
constructor(options: ClockControlOptions) {
@ -66,12 +67,12 @@ export class ClockControl extends Control {
this._moon.style.transform = 'translate(-150px, -150px)';
this._sun!.innerHTML = `
<svg class="svg-icon" viewBox="${sun.viewBox}">
<use xlink:href="${sun.url}" />
<svg class="svg-icon">
<use xlink:href="#clock_sun" />
</svg>`;
this._moon!.innerHTML = `
<svg class="svg-icon" viewBox="${moon.viewBox}">
<use xlink:href="${moon.url}" />
<svg class="svg-icon">
<use xlink:href="#clock_moon" />
</svg>`;
if (this.options.showDigitalClock) {
@ -138,33 +139,33 @@ export class ClockControl extends Control {
if (this.options.showWeather) {
if (worldState.thundering) {
this._setSunIcon(sunStorm);
this._setMoonIcon(moonStorm);
this._setSunIcon('clock_sun_storm');
this._setMoonIcon('clock_moon_storm');
} else if (worldState.raining) {
this._setSunIcon(sunRain);
this._setMoonIcon(moonRain);
this._setSunIcon('clock_sun_rain');
this._setMoonIcon('clock_moon_rain');
} else {
this._setSunIcon(sun);
this._setMoonIcon(moon);
this._setSunIcon('clock_moon');
this._setMoonIcon('clock_sun');
}
}
}
_setSunIcon(icon: BrowserSpriteSymbol) {
_setSunIcon(icon: string) {
if(this._sun && this._currentSunIcon !== icon) {
this._sun!.innerHTML = `
<svg class="svg-icon" viewBox="${icon.viewBox}">
<use xlink:href="${icon.url}" />
<svg class="svg-icon">
<use xlink:href="#${icon}" />
</svg>`;
this._currentSunIcon = icon;
}
}
_setMoonIcon(icon: BrowserSpriteSymbol) {
_setMoonIcon(icon: string) {
if(this._moon && this._currentMoonIcon !== icon) {
this._moon!.innerHTML = `
<svg class="svg-icon" viewBox="${icon.viewBox}">
<use xlink:href="${icon.url}" />
<svg class="svg-icon">
<use xlink:href="#${icon}" />
</svg>`;
this._currentMoonIcon = icon;
}

View File

@ -18,12 +18,12 @@
*/
import {Util, Control, DomEvent, LeafletEvent, Map as LeafletMap, Layer, DomUtil} from 'leaflet';
import layers from '@/assets/icons/layers.svg';
import LayersObject = Control.LayersObject;
import LayersOptions = Control.LayersOptions;
import Layers = Control.Layers;
import checkbox from '@/assets/icons/checkbox.svg';
import '@/assets/icons/layers.svg';
import '@/assets/icons/checkbox.svg';
export class DynmapLayerControl extends Control.Layers {
private _layersLink?: HTMLElement;
@ -55,8 +55,8 @@ export class DynmapLayerControl extends Control.Layers {
const element = super.onAdd(map);
this._layersLink!.innerHTML = `
<svg class="svg-icon" viewBox="${layers.viewBox}">
<use xlink:href="${layers.url}" />
<svg class="svg-icon">
<use xlink:href="#layers" />
</svg>`;
return element;
@ -120,8 +120,8 @@ export class DynmapLayerControl extends Control.Layers {
item.appendChild(input);
item.insertAdjacentHTML('beforeend', `
<svg class="svg-icon" viewBox="${checkbox.viewBox}" aria-hidden="true">
<use xlink:href="${checkbox.url}" />
<svg class="svg-icon" aria-hidden="true">
<use xlink:href="#checkbox" />
</svg>`);
item.appendChild(label);

View File

@ -19,7 +19,7 @@
import {Control, ControlOptions, DomUtil, Map} from 'leaflet';
import {useStore} from "@/store";
import linkIcon from '@/assets/icons/link.svg';
import '@/assets/icons/link.svg';
import ClipboardJS from 'clipboard';
export class LinkControl extends Control {
@ -38,8 +38,8 @@ export class LinkControl extends Control {
linkButton.type = 'button';
linkButton.title = 'Copy link to current location';
linkButton.innerHTML = `
<svg class="svg-icon" viewBox="${linkIcon.viewBox}" aria-hidden="true">
<use xlink:href="${linkIcon.url}" />
<svg class="svg-icon" aria-hidden="true">
<use xlink:href="#link" />
</svg>`;
new ClipboardJS(linkButton, {

View File

@ -30,7 +30,7 @@ import {
LeafletEvent,
Map, TileLayer,
} from 'leaflet';
import loadingIcon from '@/assets/icons/loading.svg';
import '@/assets/icons/loading.svg';
export interface LoadingControlOptions extends ControlOptions {
delayIndicator?: number;
@ -54,8 +54,8 @@ export class LoadingControl extends Control {
this._loadingIndicator.title = 'Loading...';
this._loadingIndicator.hidden = true;
this._loadingIndicator.innerHTML = `
<svg class="svg-icon" viewBox="${loadingIcon.viewBox}">
<use xlink:href="${loadingIcon.url}" />
<svg class="svg-icon">
<use xlink:href="#loading" />
</svg>`;
this._addLayerListeners(map);

View File

@ -23,6 +23,7 @@ export interface DynmapIconOptions extends DivIconOptions {
icon: string;
label: string;
isHtml?: boolean;
showLabel?: boolean;
}
const markerContainer: HTMLDivElement = document.createElement('div');

View File

@ -20,8 +20,7 @@
import {MarkerOptions, DivIcon, DomUtil} from 'leaflet';
import {DynmapPlayer} from "@/dynmap";
import {getMinecraftHead} from '@/util';
const playerImage = require('@/assets/images/player_face.png');
import playerImage from '@/assets/images/player_face.png';
const noSkinImage: HTMLImageElement = document.createElement('img');
noSkinImage.height = 16;

View File

@ -24,7 +24,8 @@ import '@/scss/style.scss';
const splash = document.getElementById('splash'),
splashError = document.getElementById('splash__error'),
splashAttempt = document.getElementById('splash__error-attempt');
splashAttempt = document.getElementById('splash__error-attempt'),
svgs = import.meta.globEager('/assets/icons/*.svg');
window.hideSplash = function() {
requestAnimationFrame(function() {

5
src/shims-vue.d.ts vendored
View File

@ -1,5 +0,0 @@
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

View File

@ -68,7 +68,7 @@ export type State = {
}
export const state: State = {
version: process.env.PACKAGE_VERSION || 'Unknown',
version: (import.meta.env.VITE_VERSION || 'Unknown') as string,
configuration: {
version: '',

9
src/vuex.d.ts vendored
View File

@ -1,9 +0,0 @@
import { ComponentCustomProperties } from 'vue'
import {State, Store} from "@/store";
declare module '@vue/runtime-core' {
// provide typings for `this.$store`
interface ComponentCustomProperties {
$store: Store<State>
}
}

View File

@ -12,9 +12,11 @@
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"isolatedModules": true,
"baseUrl": ".",
"types": [
"webpack-env"
"vite/client",
"vue"
],
"paths": {
"@/*": [

24
vite.config.ts Normal file
View File

@ -0,0 +1,24 @@
import { defineConfig } from 'vite';
import { resolve } from 'path';
import vue from '@vitejs/plugin-vue';
import svgSpritePlugin from "vite-plugin-svg-sprite-component"
export default defineConfig({
plugins: [vue(), svgSpritePlugin({
symbolId: (name) => name,
})],
server: {
port: 8080
},
resolve: {
alias: [
{
find: '@',
replacement: resolve(__dirname, 'src')
}
]
},
build: {
chunkSizeWarningLimit: 600,
}
});

View File

@ -1,41 +0,0 @@
const
webpack = require('webpack'),
fs = require('fs'),
packageJson = fs.readFileSync('./package.json'),
version = JSON.parse(packageJson).version || 'Unknown';
module.exports = {
publicPath: '',
assetsDir: 'live-atlas',
pluginOptions: {
svgSprite: {
loaderOptions: {
extract: true,
spriteFilename: 'live-atlas/img/icons.[hash:8].svg'
},
}
},
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
'process.env': {
PACKAGE_VERSION: '"' + version + '"'
}
})
]
},
chainWebpack: config => {
config.plugin('html')
.tap(args => {
args[0].minify = false
return args
})
config.module
.rule('svg-sprite')
.use('svgo-loader')
.loader('svgo-loader')
}
}