refactor(es modules): modulize utils

This commit is contained in:
Azgaar 2022-06-26 19:20:31 +03:00
parent 11df349394
commit 12e1c9f334
45 changed files with 620 additions and 283 deletions

View file

@ -1858,18 +1858,6 @@
</td>
<td></td>
</tr>
<!-- <tr data-tip="Select language (not all languages are fully supported). Reload the page to apply">
<td></td>
<td>Language</td>
<td>
<select id="selectLanguage" data-stored="lang">
<option value="en" selected>English (100%)</option>
<option value="ru">Русский (1%)</option>
</select>
</td>
<td></td>
</tr> -->
</table>
<div>
@ -3957,18 +3945,20 @@
<button id="templateRedo" data-tip="Redo the action" class="icon-cw" disabled></button>
<button id="templateSave" data-tip="Download the template as a text file" class="icon-download"></button>
<button id="templateLoad" data-tip="Open previously downloaded template" class="icon-upload"></button>
<button
<a
id="templateCA"
data-tip="Find or share custom template on Cartography Assets portal"
class="icon-drafting-compass"
onclick="openURL('https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/templates')"
></button>
<button
href="https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/templates"
target="_blank"
></a>
<a
id="templateTutorial"
data-tip="Open Template Editor Tutorial"
class="icon-info"
onclick="wiki('Heightmap-template-editor')"
></button>
href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-template-editor"
target="_blank"
></a>
<label
data-tip="Set seed if you want template to generate the same heightmap each time. Leave blank to use random seed"
>
@ -5389,12 +5379,13 @@
class="icon-download"
></button>
<button id="styleSaverLoad" data-tip="Open previously downloaded style file" class="icon-upload"></button>
<button
<a
id="styleSaverCA"
data-tip="Find or share custom style preset on Cartography Assets portal"
class="icon-drafting-compass"
onclick="openURL('https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/styles/')"
></button>
href="https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/styles"
target="_blank"
></a>
</div>
</div>
@ -7698,7 +7689,6 @@
<script type="module" src="modules/coa-generator.js"></script>
<script type="module" src="modules/submap.js"></script>
<script src="libs/polylabel.min.js"></script>
<script src="libs/lineclip.min.js"></script>
<script src="libs/alea.min.js"></script>
<script type="module" src="modules/fonts.js"></script>
<script type="module" src="modules/ui/layers.js"></script>

View file

@ -1,2 +0,0 @@
// lineclip by mourner, https://github.com/mapbox/lineclip
"use strict";function lineclip(t,e,n){var r,i,u,o,s,h=t.length,c=bitCode(t[0],e),f=[];for(n=n||[],r=1;r<h;r++){for(i=t[r-1],o=s=bitCode(u=t[r],e);;){if(!(c|o)){f.push(i),o!==s?(f.push(u),r<h-1&&(n.push(f),f=[])):r===h-1&&f.push(u);break}if(c&o)break;c?c=bitCode(i=intersect(i,u,c,e),e):o=bitCode(u=intersect(i,u,o,e),e)}c=s}return f.length&&n.push(f),n}function polygonclip(t,e,n=0){for(var r,i,u,o,s,h,c,f=1;f<=8;f*=2){for(r=[],u=!(bitCode(i=t[t.length-1],e)&f),s=0;s<t.length;s++){o=(c=!(bitCode(h=t[s],e)&f))!==u;var l=intersect(i,h,f,e);o&&r.push(l),n&&o&&r.push(l,l),c&&r.push(h),i=h,u=c}if(!(t=r).length)break}return r}function intersect(t,e,n,r){return 8&n?[t[0]+(e[0]-t[0])*(r[3]-t[1])/(e[1]-t[1]),r[3]]:4&n?[t[0]+(e[0]-t[0])*(r[1]-t[1])/(e[1]-t[1]),r[1]]:2&n?[r[2],t[1]+(e[1]-t[1])*(r[2]-t[0])/(e[0]-t[0])]:1&n?[r[0],t[1]+(e[1]-t[1])*(r[0]-t[0])/(e[0]-t[0])]:null}function bitCode(t,e){var n=0;return t[0]<e[0]?n|=1:t[0]>e[2]&&(n|=2),t[1]<e[1]?n|=4:t[1]>e[3]&&(n|=8),n}

View file

@ -2,6 +2,7 @@ import {TIME} from "/src/config/logging";
import {findCell} from "/src/utils/graphUtils";
import {layerIsOn} from "./ui/layers";
import {getColors, getRandomColor, getMixedColor} from "/src/utils/colorUtils";
import {getMiddlePoint} from "@/utils/lineUtils";
import {rn, minmax} from "/src/utils/numberUtils";
window.BurgsAndStates = (function () {

View file

@ -25,7 +25,6 @@ let svgWidth;
let svgHeight;
let options = {};
let mapCoordinates = {};
let populationRate;
let distanceScale;
let urbanization;

View file

@ -1,6 +1,7 @@
import {getGridPolygon} from "/src/utils/graphUtils";
import {unique} from "/src/utils/arrayUtils";
import {tip} from "/src/scripts/tooltips";
import {getCoordinates} from "@/utils/coordinateUtils";
import {rn} from "/src/utils/numberUtils";
// download map as SVG

View file

@ -2,7 +2,10 @@ import {restoreDefaultEvents} from "/src/scripts/events";
import {calculateVoronoi, findCell} from "/src/utils/graphUtils";
import {last} from "/src/utils/arrayUtils";
import {tip} from "/src/scripts/tooltips";
import {parseError} from "@/utils/errorUtils";
import {rn, minmax} from "/src/utils/numberUtils";
import {link} from "@/utils/linkUtils";
import {ldb} from "@/scripts/indexedDB";
function quickLoad() {
ldb.get("lastMap", blob => {

View file

@ -1,5 +1,6 @@
import {tip} from "/src/scripts/tooltips";
import {rn} from "/src/utils/numberUtils";
import {ldb} from "@/scripts/indexedDB";
// functions to save project as .map file

View file

@ -562,6 +562,14 @@ window.Markers = (function () {
notes.push({id, name, legend});
}
function generateDate(from = 100, to = 1000) {
return new Date(rand(from, to), rand(12), rand(31)).toLocaleDateString("en", {
year: "numeric",
month: "long",
day: "numeric"
});
}
function listDungeons({cells}) {
return cells.i.filter(i => !occupied[i] && cells.pop[i] && cells.pop[i] < 3);
}

View file

@ -1,5 +1,6 @@
import {TIME} from "/src/config/logging";
import {rn} from "/src/utils/numberUtils";
import {TIME} from "@/config/logging";
import {clipPoly} from "@/utils/lineUtils";
import {rn} from "@/utils/numberUtils";
window.OceanLayers = (function () {
let cells, vertices, pointsN, used;

View file

@ -1,4 +1,5 @@
import {findCell} from "/src/utils/graphUtils";
import {getMiddlePoint} from "@/utils/lineUtils";
import {rn} from "/src/utils/numberUtils";
window.Submap = (function () {

View file

@ -1,5 +1,6 @@
import {last} from "/src/utils/arrayUtils";
import {tip} from "/src/scripts/tooltips";
import {wiki} from "@/utils/linkUtils";
import {rn, minmax} from "/src/utils/numberUtils";
export class Battle {

View file

@ -2,6 +2,7 @@ import {restoreDefaultEvents} from "/src/scripts/events";
import {findAll, findCell, getPackPolygon, isLand} from "/src/utils/graphUtils";
import {tip, showMainTip, clearMainTip} from "/src/scripts/tooltips";
import {getRandomColor} from "/src/utils/colorUtils";
import {openURL} from "@/utils/linkUtils";
import {rn} from "/src/utils/numberUtils";
export function editBiomes() {

View file

@ -1,6 +1,7 @@
import {findCell} from "/src/utils/graphUtils";
import {tip, clearMainTip} from "/src/scripts/tooltips";
import {rn} from "/src/utils/numberUtils";
import {prompt} from "@/scripts/prompt";
export function editBurg(id) {
if (customization) return;

View file

@ -1,6 +1,7 @@
import {restoreDefaultEvents} from "/src/scripts/events";
import {findCell} from "/src/utils/graphUtils";
import {tip, clearMainTip} from "/src/scripts/tooltips";
import {getCoordinates} from "@/utils/coordinateUtils";
import {rn} from "/src/utils/numberUtils";
export function overviewBurgs() {
@ -500,8 +501,9 @@ export function overviewBurgs() {
data += rn(b.population * populationRate * urbanization) + ",";
// add geography data
data += getLatitude(b.y, 2) + ",";
data += getLongitude(b.x, 2) + ",";
const [lon, lat] = getCoordinates(b.x, b.y, 2);
data += lat + ",";
data += lon + ",";
data += parseInt(getHeight(pack.cells.h[b.cell])) + ",";
// add status data

View file

@ -1,5 +1,6 @@
import {getPackPolygon} from "/src/utils/graphUtils";
import {tip} from "/src/scripts/tooltips";
import {clipPoly} from "@/utils/lineUtils";
import {rn} from "/src/utils/numberUtils";
export function editCoastline(node = d3.event.target) {

View file

@ -1,5 +1,6 @@
import {clearMainTip} from "/src/scripts/tooltips";
import {tip} from "/src/scripts/tooltips";
import {openURL} from "@/utils/linkUtils";
import {rn} from "/src/utils/numberUtils";
export function editEmblem(type, id, el) {

View file

@ -1,5 +1,7 @@
import {findCell, findGridCell} from "/src/utils/graphUtils";
import {rn} from "/src/utils/numberUtils";
import {link} from "@/utils/linkUtils";
import {getCoordinates, toDMS} from "@/utils/coordinateUtils";
// fit full-screen map if window is resized
window.addEventListener("resize", function (e) {
@ -29,8 +31,10 @@ function updateCellInfo(point, i, g) {
const x = (infoX.innerHTML = rn(point[0]));
const y = (infoY.innerHTML = rn(point[1]));
const f = cells.f[i];
infoLat.innerHTML = toDMS(getLatitude(y, 4), "lat");
infoLon.innerHTML = toDMS(getLongitude(x, 4), "lon");
const [lon, lat] = getCoordinates(x, y, 4);
infoLat.innerHTML = toDMS(lat, "lat");
infoLon.innerHTML = toDMS(lon, "lon");
infoCell.innerHTML = i;
infoArea.innerHTML = cells.area[i] ? si(getArea(cells.area[i])) + " " + getAreaUnit() : "n/a";
@ -58,16 +62,6 @@ function updateCellInfo(point, i, g) {
infoBiome.innerHTML = biomesData.name[cells.biome[i]];
}
// convert coordinate to DMS format
function toDMS(coord, c) {
const degrees = Math.floor(Math.abs(coord));
const minutesNotTruncated = (Math.abs(coord) - degrees) * 60;
const minutes = Math.floor(minutesNotTruncated);
const seconds = Math.floor((minutesNotTruncated - minutes) * 60);
const cardinal = c === "lat" ? (coord >= 0 ? "N" : "S") : coord >= 0 ? "E" : "W";
return degrees + "° " + minutes + " " + seconds + "″ " + cardinal;
}
// get surface elevation
function getElevation(f, h) {
if (f.land) return getHeight(h) + " (" + h + ")"; // land: usual height

View file

@ -4,6 +4,8 @@ import {last, createTypedArray} from "/src/utils/arrayUtils";
import {tip, showMainTip, clearMainTip} from "/src/scripts/tooltips";
import {byId} from "/src/utils/shorthands";
import {rn, minmax, lim} from "/src/utils/numberUtils";
import {link} from "@/utils/linkUtils";
import {prompt} from "@/scripts/prompt";
export function editHeightmap(options) {
const {mode, tool} = options || {};

View file

@ -5,7 +5,10 @@ import {last} from "/src/utils/arrayUtils";
import {stored, store} from "/src/utils/shorthands";
import {tip} from "/src/scripts/tooltips";
import {byId} from "/src/utils/shorthands";
import {clipPoly} from "@/utils/lineUtils";
import {rn, minmax, normalize} from "/src/utils/numberUtils";
import {isCtrlClick} from "@/utils/keyboardUtils";
import {prompt} from "@/scripts/prompt";
let presets = {};
restoreCustomPresets(); // run on-load

View file

@ -1,4 +1,5 @@
import {tip} from "/src/scripts/tooltips";
import {wiki} from "@/utils/linkUtils";
import {rn} from "/src/utils/numberUtils";
export function overviewMilitary() {

View file

@ -1,5 +1,6 @@
import {unique} from "/src/utils/arrayUtils";
import {tip} from "/src/scripts/tooltips";
import {openURL} from "@/utils/linkUtils";
import {rn} from "/src/utils/numberUtils";
export function editNamesbase() {

View file

@ -1,5 +1,6 @@
import {findCell, getPackPolygon} from "/src/utils/graphUtils";
import {tip, clearMainTip} from "/src/scripts/tooltips";
import {getSegmentId} from "@/utils/lineUtils";
import {rn} from "/src/utils/numberUtils";
export function editRiver(id) {

View file

@ -1,4 +1,5 @@
import {tip, showMainTip, clearMainTip} from "/src/scripts/tooltips";
import {getSegmentId} from "@/utils/lineUtils";
import {rn} from "/src/utils/numberUtils";
export function editRoute(onClick) {

View file

@ -1,5 +1,6 @@
import {byId} from "/src/utils/shorthands";
import {clearMainTip} from "/src/scripts/tooltips";
import {parseError} from "@/utils/errorUtils";
import {rn, minmax} from "/src/utils/numberUtils";
window.UISubmap = (function () {

View file

@ -3,8 +3,8 @@ import {findCell} from "/src/utils/graphUtils";
import {last} from "/src/utils/arrayUtils";
import {tip, clearMainTip} from "/src/scripts/tooltips";
import {rn} from "/src/utils/numberUtils";
// module to control the Tools options (click to edit, to re-geenerate, tp add)
import {isCtrlClick} from "@/utils/keyboardUtils";
import {prompt} from "@/scripts/prompt";
toolsContent.addEventListener("click", function (event) {
if (customization) return tip("Please exit the customization mode first", false, "warning");

View file

@ -1,6 +1,7 @@
import {restoreDefaultEvents} from "/src/scripts/events";
import {findCell} from "/src/utils/graphUtils";
import {tip} from "/src/scripts/tooltips";
import {prompt} from "@/scripts/prompt";
export function editUnits() {
closeDialogs("#unitsEditor, .stable");

View file

@ -10,5 +10,8 @@
"devDependencies": {
"typescript": "^4.7.4",
"vite": "^2.9.12"
},
"dependencies": {
"lineclip": "^1.1.5"
}
}

View file

@ -21,8 +21,10 @@ import {
isLand,
shouldRegenerateGrid
} from "./utils/graphUtils";
import {parseError} from "@/utils/errorUtils";
import {rn, minmax, normalize} from "./utils/numberUtils";
import {createTypedArray} from "./utils/arrayUtils";
import {clipPoly} from "@/utils/lineUtils";
import {byId} from "./utils/shorthands";
import "./components";
@ -41,7 +43,7 @@ options = {
winds: [225, 45, 225, 315, 135, 315],
stateLabelsMode: "auto"
};
mapCoordinates = {}; // map coordinates on globe
populationRate = +byId("populationRateInput").value;
distanceScale = +byId("distanceScaleInput").value;
urbanization = +byId("urbanizationInput").value;
@ -368,7 +370,7 @@ async function generate(options) {
OceanLayers();
defineMapSize();
calculateMapCoordinates();
window.mapCoordinates = calculateMapCoordinates();
calculateTemperatures();
generatePrecipitation();
@ -674,7 +676,7 @@ function defineMapSize() {
}
// calculate map position on globe
function calculateMapCoordinates() {
function calculateMapCoordinates(): IMapCoordinates {
const size = +byId("mapSizeOutput").value;
const latShift = +byId("latitudeOutput").value;
@ -683,7 +685,7 @@ function calculateMapCoordinates() {
const latS = rn(latN - latT, 1);
const lon = rn(Math.min(((graphWidth / graphHeight) * latT) / 2, 180));
mapCoordinates = {latT, latN, latS, lonT: lon * 2, lonW: -lon, lonE: lon};
return {latT, latN, latS, lonT: lon * 2, lonW: -lon, lonE: lon};
}
// temperature model

View file

@ -1,5 +1,6 @@
import {findCell} from "/src/utils/graphUtils";
import {last} from "/src/utils/arrayUtils";
import {getSegmentId} from "@/utils/lineUtils";
import {rn} from "/src/utils/numberUtils";
export class Rulers {

50
src/scripts/indexedDB.js Normal file
View file

@ -0,0 +1,50 @@
// indexedDB support: ldb object
// @ts-ignore unimplemented historical interfaces
const indexedDBfactory = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
if (!indexedDBfactory) console.error("indexedDB not supported");
let database;
const databaseRequest = indexedDBfactory.open("d2", 1);
databaseRequest.onsuccess = function () {
database = this.result;
};
databaseRequest.onerror = function (e) {
console.error("indexedDB request error", e);
};
databaseRequest.onupgradeneeded = function (event) {
database = null;
const store = databaseRequest.result.createObjectStore("s", {keyPath: "k"});
store.transaction.oncomplete = function (e) {
database = e.target.db;
};
};
function getValue(key, callback) {
if (!database) {
setTimeout(() => getValue(key, callback), 100);
return;
}
database.transaction("s").objectStore("s").get(key).onsuccess = function (e) {
const value = (e.target.result && e.target.result.v) || null;
callback(value);
};
}
function setValue(key) {
if (!database) {
setTimeout(() => setValue(key, value), 100);
return;
}
database
.transaction("s", "readwrite")
.objectStore("s")
.put({[key]: value});
}
export const ldb = {get: getValue, set: setValue};

44
src/scripts/prompt.ts Normal file
View file

@ -0,0 +1,44 @@
import {ERROR} from "@/config/logging";
// prompt replacer (prompt does not work in Electron)
const $prompt: HTMLElement = document.getElementById("prompt")!;
const $form: HTMLFormElement = $prompt.querySelector("#promptForm")!;
const $input: HTMLInputElement = $prompt.querySelector("#promptInput")!;
const $text: HTMLDivElement = $prompt.querySelector("#promptText")!;
const $cancel: HTMLButtonElement = $prompt.querySelector("#promptCancel")!;
const defaultText = "Please provide an input";
const defaultOptions = {default: 1, step: 0.01, min: 0, max: 100, required: true};
export function prompt(promptText = defaultText, options = defaultOptions, callback: (value: number | string) => void) {
if (options.default === undefined)
return ERROR && console.error("Prompt: options object does not have default value defined");
$text.innerHTML = promptText;
$input.type = typeof options.default === "number" ? "number" : "text";
if (options.step !== undefined) $input.step = String(options.step);
if (options.min !== undefined) $input.min = String(options.min);
if (options.max !== undefined) $input.max = String(options.max);
$input.required = options.required === false ? false : true;
$input.placeholder = "type a " + $input.type;
$input.value = String(options.default);
$prompt.style.display = "block";
$form.addEventListener(
"submit",
event => {
event.preventDefault();
$prompt.style.display = "none";
const value = $input.type === "number" ? Number($input.value) : $input.value;
if (callback) callback(value);
},
{once: true}
);
}
$cancel.addEventListener("click", () => {
$prompt.style.display = "none";
});

1
src/types/common.d.ts vendored Normal file
View file

@ -0,0 +1 @@
type UnknownObject = {[key: string]: unknown};

8
src/types/coordinates.d.ts vendored Normal file
View file

@ -0,0 +1,8 @@
interface IMapCoordinates {
latT: number;
latN: number;
latS: number;
lonT: number;
lonW: number;
lonE: number;
}

4
src/types/modules.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
declare module "lineclip" {
export function polygon(points: number[][], bbox: number[], result?: number[][]): number[][];
export function lineclip(points: number[][], bbox: number[]): number[][];
}

View file

@ -13,6 +13,9 @@ interface Window {
pack: IPack;
grig: IGrid;
d3: typeof d3;
graphHeight: number;
graphWidth: number;
mapCoordinates: IMapCoordinates;
}
interface Node {

3
src/types/point.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
type TPoint = [number, number];
type TPoints = TPoint[];

View file

@ -0,0 +1,25 @@
import {rn} from "./numberUtils";
const {mapCoordinates, graphWidth, graphHeight} = window;
function getLongitude(x: number, decimals = 2) {
return rn(mapCoordinates.lonW + (x / graphWidth) * mapCoordinates.lonT, decimals);
}
function getLatitude(y: number, decimals = 2) {
return rn(mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT, decimals);
}
export function getCoordinates(x: number, y: number, decimals = 2) {
return [getLongitude(x, decimals), getLatitude(y, decimals)];
}
// convert coordinate to DMS format
export function toDMS(coord: number, type: "lat" | "lon") {
const degrees = Math.floor(Math.abs(coord));
const minutesNotTruncated = (Math.abs(coord) - degrees) * 60;
const minutes = Math.floor(minutesNotTruncated);
const seconds = Math.floor((minutesNotTruncated - minutes) * 60);
const cardinal = type === "lat" ? (coord >= 0 ? "N" : "S") : coord >= 0 ? "E" : "W";
return `${degrees}° ${minutes} ${seconds}${cardinal}`;
}

8
src/utils/errorUtils.ts Normal file
View file

@ -0,0 +1,8 @@
// parse error to get the readable string
export function parseError(error: Error) {
const errorString = error.toString() + " " + error.stack;
const regex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
const errorNoURL = errorString.replace(regex, url => "<i>" + url.split("/").at(-1) + "</i>");
const errorParsed = errorNoURL.replace(/at /gi, "<br>&nbsp;&nbsp;at ");
return errorParsed;
}

View file

@ -0,0 +1,3 @@
export function isCtrlClick(event: MouseEvent) {
return event.ctrlKey || event.metaKey;
}

56
src/utils/lineUtils.ts Normal file
View file

@ -0,0 +1,56 @@
import {polygon} from "lineclip";
const {graphWidth, graphHeight, pack} = window;
// clip polygon by graph bbox
export function clipPoly(points: TPoints) {
return polygon(points, [0, 0, graphWidth, graphHeight]);
}
// get segment of any point on polyline
export function getSegmentId(points: TPoints, point: TPoint, step = 10) {
if (points.length === 2) return 1;
const d2 = (p1: TPoint, p2: TPoint) => (p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2;
let minSegment = 1;
let minDist = Infinity;
for (let i = 0; i < points.length - 1; i++) {
const p1 = points[i];
const p2 = points[i + 1];
const length = Math.sqrt(d2(p1, p2));
const segments = Math.ceil(length / step);
const dx = (p2[0] - p1[0]) / segments;
const dy = (p2[1] - p1[1]) / segments;
for (let s = 0; s < segments; s++) {
const x = p1[0] + s * dx;
const y = p1[1] + s * dy;
const dist2 = d2(point, [x, y]);
if (dist2 >= minDist) continue;
minDist = dist2;
minSegment = i + 1;
}
}
return minSegment;
}
// return center point of common edge of 2 pack cells
export function getMiddlePoint(cell1: number, cell2: number) {
const {cells, vertices} = pack;
const commonVertices = cells.v[cell1].filter((vertex: number) =>
vertices.c[vertex].some((cellId: number) => cellId === cell2)
);
const [x1, y1] = vertices.p[commonVertices[0]];
const [x2, y2] = vertices.p[commonVertices[1]];
const x = (x1 + x2) / 2;
const y = (y1 + y2) / 2;
return [x, y];
}

14
src/utils/linkUtils.ts Normal file
View file

@ -0,0 +1,14 @@
// open URL in a new tab or window
export function openURL(url: string) {
window.open(url, "_blank");
}
// open project wiki-page
export function wiki(page: string) {
window.open("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/" + page, "_blank");
}
// wrap URL into html anchor element
export function link(url: string, text: string) {
return `<a href="${url}" rel="noopener" target="_blank">${text}</a>`;
}

View file

@ -1,236 +0,0 @@
import {rn} from "/src/utils/numberUtils";
// clip polygon by graph bbox
function clipPoly(points, secure = 0) {
return polygonclip(points, [0, 0, graphWidth, graphHeight], secure);
}
// get segment of any point on polyline
function getSegmentId(points, point, step = 10) {
if (points.length === 2) return 1;
const d2 = (p1, p2) => (p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2;
let minSegment = 1;
let minDist = Infinity;
for (let i = 0; i < points.length - 1; i++) {
const p1 = points[i];
const p2 = points[i + 1];
const length = Math.sqrt(d2(p1, p2));
const segments = Math.ceil(length / step);
const dx = (p2[0] - p1[0]) / segments;
const dy = (p2[1] - p1[1]) / segments;
for (let s = 0; s < segments; s++) {
const x = p1[0] + s * dx;
const y = p1[1] + s * dy;
const dist2 = d2(point, [x, y]);
if (dist2 >= minDist) continue;
minDist = dist2;
minSegment = i + 1;
}
}
return minSegment;
}
// return center point of common edge of 2 pack cells
function getMiddlePoint(cell1, cell2) {
const {cells, vertices} = pack;
const commonVertices = cells.v[cell1].filter(vertex => vertices.c[vertex].some(cell => cell === cell2));
const [x1, y1] = vertices.p[commonVertices[0]];
const [x2, y2] = vertices.p[commonVertices[1]];
const x = (x1 + x2) / 2;
const y = (y1 + y2) / 2;
return [x, y];
}
function debounce(func, ms) {
let isCooldown = false;
return function () {
if (isCooldown) return;
func.apply(this, arguments);
isCooldown = true;
setTimeout(() => (isCooldown = false), ms);
};
}
function throttle(func, ms) {
let isThrottled = false;
let savedArgs;
let savedThis;
function wrapper() {
if (isThrottled) {
savedArgs = arguments;
savedThis = this;
return;
}
func.apply(this, arguments);
isThrottled = true;
setTimeout(function () {
isThrottled = false;
if (savedArgs) {
wrapper.apply(savedThis, savedArgs);
savedArgs = savedThis = null;
}
}, ms);
}
return wrapper;
}
// parse error to get the readable string in Chrome and Firefox
function parseError(error) {
const isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
const errorString = isFirefox ? error.toString() + " " + error.stack : error.stack;
const regex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
const errorNoURL = errorString.replace(regex, url => "<i>" + url.split("/").at(-1) + "</i>");
const errorParsed = errorNoURL.replace(/at /gi, "<br>&nbsp;&nbsp;at ");
return errorParsed;
}
function getBase64(url, callback) {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
const reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.send();
}
// open URL in a new tab or window
function openURL(url) {
window.open(url, "_blank");
}
// open project wiki-page
function wiki(page) {
window.open("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/" + page, "_blank");
}
// wrap URL into html a element
function link(URL, description) {
return `<a href="${URL}" rel="noopener" target="_blank">${description}</a>`;
}
function isCtrlClick(event) {
// meta key is cmd key on MacOs
return event.ctrlKey || event.metaKey;
}
function generateDate(from = 100, to = 1000) {
return new Date(rand(from, to), rand(12), rand(31)).toLocaleDateString("en", {
year: "numeric",
month: "long",
day: "numeric"
});
}
function getLongitude(x, decimals = 2) {
return rn(mapCoordinates.lonW + (x / graphWidth) * mapCoordinates.lonT, decimals);
}
function getLatitude(y, decimals = 2) {
return rn(mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT, decimals);
}
function getCoordinates(x, y, decimals = 2) {
return [getLongitude(x, decimals), getLatitude(y, decimals)];
}
// prompt replacer (prompt does not work in Electron)
void (function () {
const prompt = document.getElementById("prompt");
const form = prompt.querySelector("#promptForm");
const defaultText = "Please provide an input";
const defaultOptions = {default: 1, step: 0.01, min: 0, max: 100, required: true};
window.prompt = function (promptText = defaultText, options = defaultOptions, callback) {
if (options.default === undefined)
return ERROR && console.error("Prompt: options object does not have default value defined");
const input = prompt.querySelector("#promptInput");
prompt.querySelector("#promptText").innerHTML = promptText;
const type = typeof options.default === "number" ? "number" : "text";
input.type = type;
if (options.step !== undefined) input.step = options.step;
if (options.min !== undefined) input.min = options.min;
if (options.max !== undefined) input.max = options.max;
input.required = options.required === false ? false : true;
input.placeholder = "type a " + type;
input.value = options.default;
prompt.style.display = "block";
form.addEventListener(
"submit",
event => {
event.preventDefault();
prompt.style.display = "none";
const v = type === "number" ? +input.value : input.value;
if (callback) callback(v);
},
{once: true}
);
};
const cancel = prompt.querySelector("#promptCancel");
cancel.addEventListener("click", () => {
prompt.style.display = "none";
});
})();
// indexedDB; ldb object
void (function () {
function e(t, o) {
return n
? void (n.transaction("s").objectStore("s").get(t).onsuccess = function (e) {
var t = (e.target.result && e.target.result.v) || null;
o(t);
})
: void setTimeout(function () {
e(t, o);
}, 100);
}
var t = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
if (!t) return void ERROR && console.error("indexedDB not supported");
var n,
o = {k: "", v: ""},
r = t.open("d2", 1);
(r.onsuccess = function (e) {
n = this.result;
}),
(r.onerror = function (e) {
ERROR && console.error("indexedDB request error"), INFO && console.log(e);
}),
(r.onupgradeneeded = function (e) {
n = null;
var t = e.target.result.createObjectStore("s", {keyPath: "k"});
t.transaction.oncomplete = function (e) {
n = e.target.db;
};
}),
(window.ldb = {
get: e,
set: function (e, t) {
(o.k = e), (o.v = t), n.transaction("s", "readwrite").objectStore("s").put(o);
}
});
})();

View file

@ -23,3 +23,55 @@ function nest(values, map, reduce, keys) {
return map(groups);
})(values, 0);
}
function debounce(func, ms) {
let isCooldown = false;
return function () {
if (isCooldown) return;
func.apply(this, arguments);
isCooldown = true;
setTimeout(() => (isCooldown = false), ms);
};
}
function throttle(func, ms) {
let isThrottled = false;
let savedArgs;
let savedThis;
function wrapper() {
if (isThrottled) {
savedArgs = arguments;
savedThis = this;
return;
}
func.apply(this, arguments);
isThrottled = true;
setTimeout(function () {
isThrottled = false;
if (savedArgs) {
wrapper.apply(savedThis, savedArgs);
savedArgs = savedThis = null;
}
}, ms);
}
return wrapper;
}
function getBase64(url, callback) {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
const reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.send();
}

276
yarn-error.log Normal file
View file

@ -0,0 +1,276 @@
Arguments:
/opt/homebrew/Cellar/node/18.0.0/bin/node /opt/homebrew/Cellar/yarn/1.22.18/libexec/bin/yarn.js add @types/lineclip -D
PATH:
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/yarn-[version]/bin:/opt/yarn-[version]/bin:/opt/homebrew/bin
Yarn version:
1.22.18
Node version:
18.0.0
Platform:
darwin arm64
Trace:
Error: https://registry.yarnpkg.com/@types%2flineclip: Not found
at params.callback [as _callback] (/opt/homebrew/Cellar/yarn/1.22.18/libexec/lib/cli.js:66138:18)
at self.callback (/opt/homebrew/Cellar/yarn/1.22.18/libexec/lib/cli.js:140883:22)
at Request.emit (node:events:527:28)
at Request.<anonymous> (/opt/homebrew/Cellar/yarn/1.22.18/libexec/lib/cli.js:141855:10)
at Request.emit (node:events:527:28)
at IncomingMessage.<anonymous> (/opt/homebrew/Cellar/yarn/1.22.18/libexec/lib/cli.js:141777:12)
at Object.onceWrapper (node:events:641:28)
at IncomingMessage.emit (node:events:539:35)
at endReadableNT (node:internal/streams/readable:1344:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
npm manifest:
{
"name": "fantasy-map-generator",
"version": "1.87.04",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"typescript": "^4.7.4",
"vite": "^2.9.12"
},
"dependencies": {
"lineclip": "^1.1.5"
}
}
yarn manifest:
No manifest
Lockfile:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
esbuild-android-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.47.tgz#ef95b42c67bcf4268c869153fa3ad1466c4cea6b"
integrity sha512-R13Bd9+tqLVFndncMHssZrPWe6/0Kpv2/dt4aA69soX4PRxlzsVpCvoJeFE8sOEoeVEiBkI0myjlkDodXlHa0g==
esbuild-android-arm64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.47.tgz#4ebd7ce9fb250b4695faa3ee46fd3b0754ecd9e6"
integrity sha512-OkwOjj7ts4lBp/TL6hdd8HftIzOy/pdtbrNA4+0oVWgGG64HrdVzAF5gxtJufAPOsEjkyh1oIYvKAUinKKQRSQ==
esbuild-darwin-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.47.tgz#e0da6c244f497192f951807f003f6a423ed23188"
integrity sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA==
esbuild-darwin-arm64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.47.tgz#cd40fd49a672fca581ed202834239dfe540a9028"
integrity sha512-seCmearlQyvdvM/noz1L9+qblC5vcBrhUaOoLEDDoLInF/VQ9IkobGiLlyTPYP5dW1YD4LXhtBgOyevoIHGGnw==
esbuild-freebsd-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.47.tgz#8da6a14c095b29c01fc8087a16cb7906debc2d67"
integrity sha512-ZH8K2Q8/Ux5kXXvQMDsJcxvkIwut69KVrYQhza/ptkW50DC089bCVrJZZ3sKzIoOx+YPTrmsZvqeZERjyYrlvQ==
esbuild-freebsd-arm64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.47.tgz#ad31f9c92817ff8f33fd253af7ab5122dc1b83f6"
integrity sha512-ZJMQAJQsIOhn3XTm7MPQfCzEu5b9STNC+s90zMWe2afy9EwnHV7Ov7ohEMv2lyWlc2pjqLW8QJnz2r0KZmeAEQ==
esbuild-linux-32@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.47.tgz#de085e4db2e692ea30c71208ccc23fdcf5196c58"
integrity sha512-FxZOCKoEDPRYvq300lsWCTv1kcHgiiZfNrPtEhFAiqD7QZaXrad8LxyJ8fXGcWzIFzRiYZVtB3ttvITBvAFhKw==
esbuild-linux-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.47.tgz#2a9321bbccb01f01b04cebfcfccbabeba3658ba1"
integrity sha512-nFNOk9vWVfvWYF9YNYksZptgQAdstnDCMtR6m42l5Wfugbzu11VpMCY9XrD4yFxvPo9zmzcoUL/88y0lfJZJJw==
esbuild-linux-arm64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.47.tgz#b9da7b6fc4b0ca7a13363a0c5b7bb927e4bc535a"
integrity sha512-ywfme6HVrhWcevzmsufjd4iT3PxTfCX9HOdxA7Hd+/ZM23Y9nXeb+vG6AyA6jgq/JovkcqRHcL9XwRNpWG6XRw==
esbuild-linux-arm@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.47.tgz#56fec2a09b9561c337059d4af53625142aded853"
integrity sha512-ZGE1Bqg/gPRXrBpgpvH81tQHpiaGxa8c9Rx/XOylkIl2ypLuOcawXEAo8ls+5DFCcRGt/o3sV+PzpAFZobOsmA==
esbuild-linux-mips64le@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.47.tgz#9db21561f8f22ed79ef2aedb7bbef082b46cf823"
integrity sha512-mg3D8YndZ1LvUiEdDYR3OsmeyAew4MA/dvaEJxvyygahWmpv1SlEEnhEZlhPokjsUMfRagzsEF/d/2XF+kTQGg==
esbuild-linux-ppc64le@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.47.tgz#dc3a3da321222b11e96e50efafec9d2de408198b"
integrity sha512-WER+f3+szmnZiWoK6AsrTKGoJoErG2LlauSmk73LEZFQ/iWC+KhhDsOkn1xBUpzXWsxN9THmQFltLoaFEH8F8w==
esbuild-linux-riscv64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.47.tgz#9bd6dcd3dca6c0357084ecd06e1d2d4bf105335f"
integrity sha512-1fI6bP3A3rvI9BsaaXbMoaOjLE3lVkJtLxsgLHqlBhLlBVY7UqffWBvkrX/9zfPhhVMd9ZRFiaqXnB1T7BsL2g==
esbuild-linux-s390x@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.47.tgz#a458af939b52f2cd32fc561410d441a51f69d41f"
integrity sha512-eZrWzy0xFAhki1CWRGnhsHVz7IlSKX6yT2tj2Eg8lhAwlRE5E96Hsb0M1mPSE1dHGpt1QVwwVivXIAacF/G6mw==
esbuild-netbsd-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.47.tgz#6388e785d7e7e4420cb01348d7483ab511b16aa8"
integrity sha512-Qjdjr+KQQVH5Q2Q1r6HBYswFTToPpss3gqCiSw2Fpq/ua8+eXSQyAMG+UvULPqXceOwpnPo4smyZyHdlkcPppQ==
esbuild-openbsd-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.47.tgz#309af806db561aa886c445344d1aacab850dbdc5"
integrity sha512-QpgN8ofL7B9z8g5zZqJE+eFvD1LehRlxr25PBkjyyasakm4599iroUpaj96rdqRlO2ShuyqwJdr+oNqWwTUmQw==
esbuild-sunos-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.47.tgz#3f19612dcdb89ba6c65283a7ff6e16f8afbf8aaa"
integrity sha512-uOeSgLUwukLioAJOiGYm3kNl+1wJjgJA8R671GYgcPgCx7QR73zfvYqXFFcIO93/nBdIbt5hd8RItqbbf3HtAQ==
esbuild-windows-32@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.47.tgz#a92d279c8458d5dc319abcfeb30aa49e8f2e6f7f"
integrity sha512-H0fWsLTp2WBfKLBgwYT4OTfFly4Im/8B5f3ojDv1Kx//kiubVY0IQunP2Koc/fr/0wI7hj3IiBDbSrmKlrNgLQ==
esbuild-windows-64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.47.tgz#2564c3fcf0c23d701edb71af8c52d3be4cec5f8a"
integrity sha512-/Pk5jIEH34T68r8PweKRi77W49KwanZ8X6lr3vDAtOlH5EumPE4pBHqkCUdELanvsT14yMXLQ/C/8XPi1pAtkQ==
esbuild-windows-arm64@0.14.47:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.47.tgz#86d9db1a22d83360f726ac5fba41c2f625db6878"
integrity sha512-HFSW2lnp62fl86/qPQlqw6asIwCnEsEoNIL1h2uVMgakddf+vUuMcCbtUY1i8sst7KkgHrVKCJQB33YhhOweCQ==
esbuild@^0.14.27:
version "0.14.47"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.47.tgz#0d6415f6bd8eb9e73a58f7f9ae04c5276cda0e4d"
integrity sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA==
optionalDependencies:
esbuild-android-64 "0.14.47"
esbuild-android-arm64 "0.14.47"
esbuild-darwin-64 "0.14.47"
esbuild-darwin-arm64 "0.14.47"
esbuild-freebsd-64 "0.14.47"
esbuild-freebsd-arm64 "0.14.47"
esbuild-linux-32 "0.14.47"
esbuild-linux-64 "0.14.47"
esbuild-linux-arm "0.14.47"
esbuild-linux-arm64 "0.14.47"
esbuild-linux-mips64le "0.14.47"
esbuild-linux-ppc64le "0.14.47"
esbuild-linux-riscv64 "0.14.47"
esbuild-linux-s390x "0.14.47"
esbuild-netbsd-64 "0.14.47"
esbuild-openbsd-64 "0.14.47"
esbuild-sunos-64 "0.14.47"
esbuild-windows-32 "0.14.47"
esbuild-windows-64 "0.14.47"
esbuild-windows-arm64 "0.14.47"
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
is-core-module@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==
dependencies:
has "^1.0.3"
lineclip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/lineclip/-/lineclip-1.1.5.tgz#2bf26067d94354feabf91e42768236db5616fd13"
integrity sha512-KlA/wRSjpKl7tS9iRUdlG72oQ7qZ1IlVbVgHwoO10TBR/4gQ86uhKow6nlzMAJJhjCWKto8OeoAzzIzKSmN25A==
nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
postcss@^8.4.13:
version "8.4.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"
resolve@^1.22.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
dependencies:
is-core-module "^2.9.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
rollup@^2.59.0:
version "2.75.7"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.7.tgz#221ff11887ae271e37dcc649ba32ce1590aaa0b9"
integrity sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==
optionalDependencies:
fsevents "~2.3.2"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
typescript@^4.7.4:
version "4.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
vite@^2.9.12:
version "2.9.12"
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.12.tgz#b1d636b0a8ac636afe9d83e3792d4895509a941b"
integrity sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==
dependencies:
esbuild "^0.14.27"
postcss "^8.4.13"
resolve "^1.22.0"
rollup "^2.59.0"
optionalDependencies:
fsevents "~2.3.2"

View file

@ -152,6 +152,11 @@ is-core-module@^2.9.0:
dependencies:
has "^1.0.3"
lineclip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/lineclip/-/lineclip-1.1.5.tgz#2bf26067d94354feabf91e42768236db5616fd13"
integrity sha512-KlA/wRSjpKl7tS9iRUdlG72oQ7qZ1IlVbVgHwoO10TBR/4gQ86uhKow6nlzMAJJhjCWKto8OeoAzzIzKSmN25A==
nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"