Merge 0a5caf4adb
into d88fbb7c55
This commit is contained in:
commit
0ad740041a
10 changed files with 1056 additions and 671 deletions
|
@ -1 +0,0 @@
|
||||||
public
|
|
|
@ -1,36 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true,
|
|
||||||
es6: true,
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
sourceType: 'module',
|
|
||||||
lib: ['es2020'],
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: true,
|
|
||||||
tsx: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: ['prettier', 'jsdoc', 'security'],
|
|
||||||
extends: [
|
|
||||||
'prettier',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:@typescript-eslint/eslint-recommended',
|
|
||||||
'plugin:prettier/recommended',
|
|
||||||
'plugin:jsdoc/recommended',
|
|
||||||
'plugin:security/recommended',
|
|
||||||
],
|
|
||||||
// add your custom rules here
|
|
||||||
rules: {
|
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'warn',
|
|
||||||
{ argsIgnorePattern: 'next|err|info|reject' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
60
eslint.config.js
Normal file
60
eslint.config.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// eslint.config.js
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import eslintPluginPrettier from 'eslint-plugin-prettier';
|
||||||
|
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||||
|
import security from 'eslint-plugin-security';
|
||||||
|
import jsdoc from 'eslint-plugin-jsdoc';
|
||||||
|
import globals from 'globals';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{ ignores: ['public'] },
|
||||||
|
js.configs.recommended,
|
||||||
|
jsdoc.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
sourceType: 'module',
|
||||||
|
lib: ['es2020'],
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true,
|
||||||
|
tsx: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
...globals.node, // Add Node.js globals
|
||||||
|
...globals.browser, // Add browser globals
|
||||||
|
...globals.es6, // Add ES6 globals
|
||||||
|
...globals.mocha, // Add Mocha globals (describe, it, before, after, etc.)
|
||||||
|
supertest: 'readonly', // Mark supertest as a global read-only variable
|
||||||
|
expect: 'readonly', // Mark expect as a global read-only variable if your assertion library isn't automatically detected
|
||||||
|
app: 'readonly', // Mark app as a global read-only variable
|
||||||
|
server: 'readonly', // Mark server as a global read-only variable
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
prettier: eslintPluginPrettier,
|
||||||
|
'@typescript-eslint': tseslint,
|
||||||
|
jsdoc: jsdoc,
|
||||||
|
security: security,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
...tseslint.configs['recommended'].rules,
|
||||||
|
...tseslint.configs['eslint-recommended'].rules,
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{ argsIgnorePattern: 'next|err|info|reject|^_' },
|
||||||
|
],
|
||||||
|
'prettier/prettier': 'error',
|
||||||
|
'jsdoc/require-description': 'warn',
|
||||||
|
'security/detect-object-injection': 'warn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
1428
package-lock.json
generated
1428
package-lock.json
generated
File diff suppressed because it is too large
Load diff
33
package.json
33
package.json
|
@ -17,8 +17,8 @@
|
||||||
"lint:yml": "yamllint --schema=CORE_SCHEMA *.{yml,yaml}",
|
"lint:yml": "yamllint --schema=CORE_SCHEMA *.{yml,yaml}",
|
||||||
"lint:js": "npm run lint:eslint && npm run lint:prettier",
|
"lint:js": "npm run lint:eslint && npm run lint:prettier",
|
||||||
"lint:js:fix": "npm run lint:eslint:fix && npm run lint:prettier:fix",
|
"lint:js:fix": "npm run lint:eslint:fix && npm run lint:prettier:fix",
|
||||||
"lint:eslint": "eslint \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs}\" --ignore-path .gitignore",
|
"lint:eslint": "eslint \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs}\" --ignore-pattern '.gitignore'",
|
||||||
"lint:eslint:fix": "eslint --fix \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs}\" --ignore-path .gitignore",
|
"lint:eslint:fix": "eslint --fix \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs}\" --ignore-pattern '.gitignore'",
|
||||||
"lint:prettier": "prettier --check \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
"lint:prettier": "prettier --check \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
||||||
"lint:prettier:fix": "prettier --write \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
"lint:prettier:fix": "prettier --write \"{,!(node_modules|dist|static|public)/**/}*.{js,ts,cjs,mjs,json}\" --ignore-path .gitignore",
|
||||||
"docker": "docker build . && docker run --rm -i -p 8080:8080 $(docker build -q .)"
|
"docker": "docker build . && docker run --rm -i -p 8080:8080 $(docker build -q .)"
|
||||||
|
@ -59,20 +59,21 @@
|
||||||
"tileserver-gl-styles": "2.0.0"
|
"tileserver-gl-styles": "2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.5.0",
|
"@commitlint/cli": "^19.8.0",
|
||||||
"@commitlint/config-conventional": "^19.5.0",
|
"@commitlint/config-conventional": "^19.8.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
"@typescript-eslint/parser": "^7.18.0",
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
"chai": "5.1.1",
|
"chai": "5.2.0",
|
||||||
"eslint": "^8.57.0",
|
"copyfiles": "2.4.1",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint": "^9.22.0",
|
||||||
"eslint-plugin-jsdoc": "^50.2.2",
|
"eslint-config-prettier": "^10.1.1",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-jsdoc": "^50.6.6",
|
||||||
"eslint-plugin-security": "^1.7.1",
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
"lint-staged": "^15.2.10",
|
"eslint-plugin-security": "^3.0.1",
|
||||||
"mocha": "^10.7.3",
|
"lint-staged": "^15.5.0",
|
||||||
"node-addon-api": "^8",
|
"mocha": "^11.1.0",
|
||||||
"prettier": "^3.3.3",
|
"node-addon-api": "^8.3.1",
|
||||||
|
"prettier": "^3.5.3",
|
||||||
"should": "^13.2.3",
|
"should": "^13.2.3",
|
||||||
"supertest": "^7.0.0",
|
"supertest": "^7.0.0",
|
||||||
"yaml-lint": "^1.7.0"
|
"yaml-lint": "^1.7.0"
|
||||||
|
|
|
@ -30,8 +30,8 @@ const packageJson = JSON.parse(
|
||||||
);
|
);
|
||||||
|
|
||||||
const isLight = packageJson.name.slice(-6) === '-light';
|
const isLight = packageJson.name.slice(-6) === '-light';
|
||||||
const serve_rendered = (
|
const serve_rendered = import(
|
||||||
await import(`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`)
|
`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`
|
||||||
).serve_rendered;
|
).serve_rendered;
|
||||||
|
|
||||||
export const serve_data = {
|
export const serve_data = {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ const staticTypeRegex = new RegExp(
|
||||||
);
|
);
|
||||||
|
|
||||||
const PATH_PATTERN =
|
const PATH_PATTERN =
|
||||||
/^((fill|stroke|width)\:[^\|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)/;
|
/^((fill|stroke|width):[^|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)/;
|
||||||
const httpTester = /^https?:\/\//i;
|
const httpTester = /^https?:\/\//i;
|
||||||
|
|
||||||
const mercator = new SphericalMercator();
|
const mercator = new SphericalMercator();
|
||||||
|
@ -273,7 +273,7 @@ function parseMarkerOptions(optionsList, marker) {
|
||||||
break;
|
break;
|
||||||
// Icon offset as positive or negative pixel value in the following
|
// Icon offset as positive or negative pixel value in the following
|
||||||
// format [offsetX],[offsetY] where [offsetY] is optional
|
// format [offsetX],[offsetY] where [offsetY] is optional
|
||||||
case 'offset':
|
case 'offset': {
|
||||||
const providedOffset = optionParts[1].split(',');
|
const providedOffset = optionParts[1].split(',');
|
||||||
// Set X-axis offset
|
// Set X-axis offset
|
||||||
marker.offsetX = parseFloat(providedOffset[0]);
|
marker.offsetX = parseFloat(providedOffset[0]);
|
||||||
|
@ -282,6 +282,7 @@ function parseMarkerOptions(optionsList, marker) {
|
||||||
marker.offsetY = parseFloat(providedOffset[1]);
|
marker.offsetY = parseFloat(providedOffset[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,6 +453,7 @@ async function respondImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format === 'png' || format === 'webp') {
|
if (format === 'png' || format === 'webp') {
|
||||||
|
/* empty */
|
||||||
} else if (format === 'jpg' || format === 'jpeg') {
|
} else if (format === 'jpg' || format === 'jpeg') {
|
||||||
format = 'jpeg';
|
format = 'jpeg';
|
||||||
} else {
|
} else {
|
||||||
|
@ -1486,68 +1488,78 @@ export const serve_rendered = {
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
getTerrainElevation: async function (data, param) {
|
getTerrainElevation: async function (data, param) {
|
||||||
return await new Promise(async (resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const image = new Image();
|
const image = new Image(); // Create a new Image object
|
||||||
image.onload = async () => {
|
image.onload = () => {
|
||||||
const canvas = createCanvas(param['tile_size'], param['tile_size']);
|
try {
|
||||||
const context = canvas.getContext('2d');
|
const canvas = createCanvas(param['tile_size'], param['tile_size']);
|
||||||
context.drawImage(image, 0, 0);
|
const context = canvas.getContext('2d');
|
||||||
|
context.drawImage(image, 0, 0);
|
||||||
|
|
||||||
// calculate pixel coordinate of tile,
|
// calculate pixel coordinate of tile,
|
||||||
// see https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
|
// see https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
|
||||||
let siny = Math.sin((param['lat'] * Math.PI) / 180);
|
let siny = Math.sin((param['lat'] * Math.PI) / 180);
|
||||||
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
|
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
|
||||||
// about a third of a tile past the edge of the world tile.
|
// about a third of a tile past the edge of the world tile.
|
||||||
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
|
siny = Math.min(Math.max(siny, -0.9999), 0.9999);
|
||||||
const xWorld = param['tile_size'] * (0.5 + param['long'] / 360);
|
const xWorld = param['tile_size'] * (0.5 + param['long'] / 360);
|
||||||
const yWorld =
|
const yWorld =
|
||||||
param['tile_size'] *
|
param['tile_size'] *
|
||||||
(0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
|
(0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI));
|
||||||
|
|
||||||
const scale = 1 << param['z'];
|
const scale = 1 << param['z'];
|
||||||
|
|
||||||
const xTile = Math.floor((xWorld * scale) / param['tile_size']);
|
const xTile = Math.floor((xWorld * scale) / param['tile_size']);
|
||||||
const yTile = Math.floor((yWorld * scale) / param['tile_size']);
|
const yTile = Math.floor((yWorld * scale) / param['tile_size']);
|
||||||
|
|
||||||
const xPixel = Math.floor(xWorld * scale) - xTile * param['tile_size'];
|
const xPixel =
|
||||||
const yPixel = Math.floor(yWorld * scale) - yTile * param['tile_size'];
|
Math.floor(xWorld * scale) - xTile * param['tile_size'];
|
||||||
if (
|
const yPixel =
|
||||||
xPixel < 0 ||
|
Math.floor(yWorld * scale) - yTile * param['tile_size'];
|
||||||
yPixel < 0 ||
|
if (
|
||||||
xPixel >= param['tile_size'] ||
|
xPixel < 0 ||
|
||||||
yPixel >= param['tile_size']
|
yPixel < 0 ||
|
||||||
) {
|
xPixel >= param['tile_size'] ||
|
||||||
return reject('Out of bounds Pixel');
|
yPixel >= param['tile_size']
|
||||||
|
) {
|
||||||
|
return reject('Out of bounds Pixel');
|
||||||
|
}
|
||||||
|
const imgdata = context.getImageData(xPixel, yPixel, 1, 1);
|
||||||
|
const red = imgdata.data[0];
|
||||||
|
const green = imgdata.data[1];
|
||||||
|
const blue = imgdata.data[2];
|
||||||
|
let elevation;
|
||||||
|
if (param['encoding'] === 'mapbox') {
|
||||||
|
elevation = -10000 + (red * 256 * 256 + green * 256 + blue) * 0.1;
|
||||||
|
} else if (param['encoding'] === 'terrarium') {
|
||||||
|
elevation = red * 256 + green + blue / 256 - 32768;
|
||||||
|
} else {
|
||||||
|
elevation = 'invalid encoding';
|
||||||
|
}
|
||||||
|
param['elevation'] = elevation;
|
||||||
|
param['red'] = red;
|
||||||
|
param['green'] = green;
|
||||||
|
param['blue'] = blue;
|
||||||
|
resolve(param);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error); // Catch any errors during canvas operations
|
||||||
}
|
}
|
||||||
const imgdata = context.getImageData(xPixel, yPixel, 1, 1);
|
|
||||||
const red = imgdata.data[0];
|
|
||||||
const green = imgdata.data[1];
|
|
||||||
const blue = imgdata.data[2];
|
|
||||||
let elevation;
|
|
||||||
if (param['encoding'] === 'mapbox') {
|
|
||||||
elevation = -10000 + (red * 256 * 256 + green * 256 + blue) * 0.1;
|
|
||||||
} else if (param['encoding'] === 'terrarium') {
|
|
||||||
elevation = red * 256 + green + blue / 256 - 32768;
|
|
||||||
} else {
|
|
||||||
elevation = 'invalid encoding';
|
|
||||||
}
|
|
||||||
param['elevation'] = elevation;
|
|
||||||
param['red'] = red;
|
|
||||||
param['green'] = green;
|
|
||||||
param['blue'] = blue;
|
|
||||||
resolve(param);
|
|
||||||
};
|
};
|
||||||
image.onerror = (err) => reject(err);
|
image.onerror = (err) => reject(err);
|
||||||
if (param['format'] === 'webp') {
|
|
||||||
|
// Load the image data - handle the sharp conversion outside the Promise
|
||||||
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const img = await sharp(data).toFormat('png').toBuffer();
|
if (param['format'] === 'webp') {
|
||||||
image.src = img;
|
const img = await sharp(data).toFormat('png').toBuffer();
|
||||||
|
image.src = `data:image/png;base64,${img.toString('base64')}`; // Set data URL
|
||||||
|
} else {
|
||||||
|
image.src = data;
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err); // Reject promise on sharp error
|
||||||
}
|
}
|
||||||
} else {
|
})();
|
||||||
image.src = data;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,8 +30,8 @@ const packageJson = JSON.parse(
|
||||||
);
|
);
|
||||||
const isLight = packageJson.name.slice(-6) === '-light';
|
const isLight = packageJson.name.slice(-6) === '-light';
|
||||||
|
|
||||||
const serve_rendered = (
|
const serve_rendered = import(
|
||||||
await import(`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`)
|
`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`
|
||||||
).serve_rendered;
|
).serve_rendered;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,13 +148,19 @@ async function start(opts) {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let dataDecoratorFunc = null; // Initialize to null
|
||||||
if (options.dataDecorator) {
|
if (options.dataDecorator) {
|
||||||
try {
|
try {
|
||||||
options.dataDecoratorFunc = require(
|
const dataDecoratorPath = path.resolve(paths.root, options.dataDecorator);
|
||||||
path.resolve(paths.root, options.dataDecorator),
|
const module = await import(dataDecoratorPath);
|
||||||
);
|
dataDecoratorFunc = module.default;
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
console.error(`Error loading data decorator: ${e}`);
|
||||||
|
// Handle the error (e.g., set a default decorator)
|
||||||
|
dataDecoratorFunc = null; // Or a default function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
options.dataDecoratorFunc = dataDecoratorFunc;
|
||||||
|
|
||||||
const data = clone(config.data || {});
|
const data = clone(config.data || {});
|
||||||
|
|
||||||
|
@ -671,7 +677,7 @@ async function start(opts) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wmts.hasOwnProperty('serve_rendered') && !wmts.serve_rendered) {
|
if (Object.hasOwn(wmts, 'serve_rendered') && !wmts.serve_rendered) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/utils.js
24
src/utils.js
|
@ -35,7 +35,6 @@ export function allowedScales(scale, maxScale = 9) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
||||||
const regex = new RegExp(`^[2-${maxScale}]x$`);
|
const regex = new RegExp(`^[2-${maxScale}]x$`);
|
||||||
if (!regex.test(scale)) {
|
if (!regex.test(scale)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -152,7 +151,7 @@ export function getTileUrls(
|
||||||
const hostParts = urlObject.host.split('.');
|
const hostParts = urlObject.host.split('.');
|
||||||
const relativeSubdomainsUsable =
|
const relativeSubdomainsUsable =
|
||||||
hostParts.length > 1 &&
|
hostParts.length > 1 &&
|
||||||
!/^([0-9]{1,3}\.){3}[0-9]{1,3}(\:[0-9]+)?$/.test(urlObject.host);
|
!/^([0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]+)?$/.test(urlObject.host);
|
||||||
const newDomains = [];
|
const newDomains = [];
|
||||||
for (const domain of domains) {
|
for (const domain of domains) {
|
||||||
if (domain.indexOf('*') !== -1) {
|
if (domain.indexOf('*') !== -1) {
|
||||||
|
@ -238,7 +237,7 @@ export function fixTileJSONCenter(tileJSON) {
|
||||||
export function readFile(filename) {
|
export function readFile(filename) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const sanitizedFilename = path.normalize(filename); // Normalize path, remove ..
|
const sanitizedFilename = path.normalize(filename); // Normalize path, remove ..
|
||||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
||||||
fs.readFile(String(sanitizedFilename), (err, data) => {
|
fs.readFile(String(sanitizedFilename), (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
@ -260,7 +259,7 @@ export function readFile(filename) {
|
||||||
*/
|
*/
|
||||||
async function getFontPbf(allowedFonts, fontPath, name, range, fallbacks) {
|
async function getFontPbf(allowedFonts, fontPath, name, range, fallbacks) {
|
||||||
if (!allowedFonts || (allowedFonts[name] && fallbacks)) {
|
if (!allowedFonts || (allowedFonts[name] && fallbacks)) {
|
||||||
const fontMatch = name?.match(/^[\p{L}\p{N} \-\.~!*'()@&=+,#$\[\]]+$/u);
|
const fontMatch = name?.match(/^[\p{L}\p{N} \-.~!*'()@&=+,#$[\]]+$/u);
|
||||||
const sanitizedName = fontMatch?.[0] || 'invalid';
|
const sanitizedName = fontMatch?.[0] || 'invalid';
|
||||||
if (!name || typeof name !== 'string' || name.trim() === '' || !fontMatch) {
|
if (!name || typeof name !== 'string' || name.trim() === '' || !fontMatch) {
|
||||||
console.error(
|
console.error(
|
||||||
|
@ -394,7 +393,8 @@ export function isValidHttpUrl(string) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
url = new URL(string);
|
url = new URL(string);
|
||||||
} catch (_) {
|
} catch (e) {
|
||||||
|
void e;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,15 +412,19 @@ export function isValidHttpUrl(string) {
|
||||||
*/
|
*/
|
||||||
export async function fetchTileData(source, sourceType, z, x, y) {
|
export async function fetchTileData(source, sourceType, z, x, y) {
|
||||||
if (sourceType === 'pmtiles') {
|
if (sourceType === 'pmtiles') {
|
||||||
return await new Promise(async (resolve) => {
|
try {
|
||||||
const tileinfo = await getPMtilesTile(source, z, x, y);
|
const tileinfo = await getPMtilesTile(source, z, x, y);
|
||||||
if (!tileinfo?.data) return resolve(null);
|
if (!tileinfo?.data) return null;
|
||||||
resolve({ data: tileinfo.data, headers: tileinfo.header });
|
return { data: tileinfo.data, headers: tileinfo.header };
|
||||||
});
|
} catch (error) {
|
||||||
|
console.error('Error fetching PMTiles tile:', error);
|
||||||
|
return null; // Or throw the error if you want to propagate it
|
||||||
|
}
|
||||||
} else if (sourceType === 'mbtiles') {
|
} else if (sourceType === 'mbtiles') {
|
||||||
return await new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
source.getTile(z, x, y, (err, tileData, tileHeader) => {
|
source.getTile(z, x, y, (err, tileData, tileHeader) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.error('Error fetching MBTiles tile:', err);
|
||||||
return resolve(null);
|
return resolve(null);
|
||||||
}
|
}
|
||||||
resolve({ data: tileData, headers: tileHeader });
|
resolve({ data: tileData, headers: tileHeader });
|
||||||
|
|
Loading…
Reference in a new issue