@loaders.gl/wms
Version:
Framework-independent loaders for the WMS (Web Map Service) standard
4 lines • 102 kB
Source Map (JSON)
{
"version": 3,
"sources": ["index.js", "lib/parsers/csw/parse-csw-capabilities.js", "lib/parsers/csw/parse-exception-report.js", "csw-capabilities-loader.js", "lib/parsers/csw/parse-csw-domain.js", "csw-domain-loader.js", "lib/parsers/csw/parse-csw-records.js", "csw-records-loader.js", "lib/parsers/wms/parse-wms-error.js", "wms-error-loader.js", "lib/parsers/wms/parse-wms-capabilities.js", "lib/parsers/xml/parse-xml-helpers.js", "wms-capabilities-loader.js", "lib/parsers/wms/parse-wms-features.js", "wip/wms-feature-info-loader.js", "lib/parsers/wms/parse-wms-layer-description.js", "wip/wms-layer-description-loader.js", "lib/parsers/wfs/parse-wfs-capabilities.js", "wfs-capabilities-loader.js", "lib/parsers/gml/parse-gml.js", "lib/parsers/gml/deep-strict-equal.js", "gml-loader.js", "services/ogc/wms-service.js", "services/arcgis/arcgis-server.js", "services/arcgis/arcgis-image-server.js", "lib/deprecated/create-image-source.js"],
"sourcesContent": ["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nexport { CSWCapabilitiesLoader } from \"./csw-capabilities-loader.js\";\nexport { CSWDomainLoader } from \"./csw-domain-loader.js\";\nexport { CSWRecordsLoader } from \"./csw-records-loader.js\";\n// WMS - Web Map Service\nexport { WMSErrorLoader } from \"./wms-error-loader.js\";\nexport { WMSCapabilitiesLoader } from \"./wms-capabilities-loader.js\";\nexport { WMSFeatureInfoLoader as _WMSFeatureInfoLoader } from \"./wip/wms-feature-info-loader.js\";\nexport { WMSLayerDescriptionLoader as _WMSLayerDescriptionLoader } from \"./wip/wms-layer-description-loader.js\";\nexport { WFSCapabilitiesLoader as _WFSCapabilitiesLoader } from \"./wfs-capabilities-loader.js\";\nexport { GMLLoader as _GMLLoader } from \"./gml-loader.js\";\n// EXPERIMENTAL: DATA SOURCES\n// OGC Services\n// export {CSWSource} from './services/ogc/csw-service';\nexport { WMSSource, WMSImageSource } from \"./services/ogc/wms-service.js\";\n// ArcGIS SourceLoaders\nexport { getArcGISServices as _getArcGISServices } from \"./services/arcgis/arcgis-server.js\";\nexport { ArcGISImageServerSource as _ArcGISImageServerSource } from \"./services/arcgis/arcgis-image-server.js\";\n// DEPRECATED: TODO - remove once deck.gl has been udpated\nexport { ImageSource } from '@loaders.gl/loader-utils';\nexport { createImageSource } from \"./lib/deprecated/create-image-source.js\";\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\nimport { parseExceptionReport } from \"./parse-exception-report.js\";\n/**\n * Parses a typed data structure from raw XML for `GetCapabilities` response\n * @note Error handlings is fairly weak\n */\nexport function parseCSWCapabilities(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, {\n ...options,\n xml: {\n ...options?.xml,\n removeNSPrefix: true,\n uncapitalizeKeys: true\n }\n });\n parseExceptionReport(parsedXML);\n const xmlCapabilities = parsedXML.capabilities || parsedXML;\n return xmlCapabilities;\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n// import type {XMLLoaderOptions} from '@loaders.gl/xml';\n// import {XMLLoader} from '@loaders.gl/xml';\n/**\n * Parses a typed data structure from raw XML for `GetDomain` response\n * @note Error handlings is fairly weak\n */\nexport function parseExceptionReport(parsedXML) {\n // const parsedXML = XMLLoader.parseTextSync?.(text, {\n // ...options,\n // xml: {\n // ...options?.xml,\n // removeNSPrefix: true,\n // uncapitalizeKeys: true\n // }\n // });\n const exceptionReport = parsedXML.exceptionReport;\n if (!exceptionReport) {\n return;\n }\n const errorMessage = exceptionReport.exception?.exceptionText ||\n exceptionReport.exception?.exceptionCode ||\n exceptionReport.exception?.locator ||\n 'server error';\n throw new Error(`Catalog Server: ${errorMessage}`);\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseCSWCapabilities } from \"./lib/parsers/csw/parse-csw-capabilities.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the CSW GetCapability request\n */\nexport const CSWCapabilitiesLoader = {\n dataType: null,\n batchType: null,\n id: 'csw-capabilities',\n name: 'CSW Capabilities',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.csw_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n csw: {}\n },\n parse: async (arrayBuffer, options) => parseCSWCapabilities(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseCSWCapabilities(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\nimport { parseExceptionReport } from \"./parse-exception-report.js\";\n/**\n * Parses a typed data structure from raw XML for `GetDomain` response\n * @note Error handlings is fairly weak\n */\nexport function parseCSWDomain(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, {\n ...options,\n xml: {\n ...options?.xml,\n removeNSPrefix: true,\n uncapitalizeKeys: true,\n arrayPaths: [\n 'GetDomainResponse.DomainValues',\n 'GetDomainResponse.DomainValues.ListOfValues.value'\n ]\n }\n });\n parseExceptionReport(parsedXML);\n const xmlDomain = parsedXML.getDomainResponse;\n for (const domainValue of xmlDomain.domainValues) {\n // Drop the nested <listOfValues><value><value><listOfValues> => values[]\n domainValue.values = domainValue.listOfValues?.value;\n delete domainValue.listOfValues;\n }\n return xmlDomain;\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseCSWDomain } from \"./lib/parsers/csw/parse-csw-domain.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the CSW GetCapability request\n */\nexport const CSWDomainLoader = {\n dataType: null,\n batchType: null,\n id: 'csw-domain',\n name: 'CSW Domain',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.csw_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n csw: {}\n },\n parse: async (arrayBuffer, options) => parseCSWDomain(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseCSWDomain(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { convertXMLFieldToArrayInPlace, XMLLoader } from '@loaders.gl/xml';\nimport { parseExceptionReport } from \"./parse-exception-report.js\";\n/**\n * Parses a typed data structure from raw XML for `GetRecords` response\n * @note Error handlings is fairly weak\n */\nexport function parseCSWRecords(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, {\n ...options,\n xml: {\n ...options?.xml,\n removeNSPrefix: true,\n uncapitalizeKeys: true,\n arrayPaths: [],\n _fastXML: {\n ...options?.xml?._fastXML,\n parseAttributeValue: true\n }\n }\n });\n parseExceptionReport(parsedXML);\n const xmlRecords = parsedXML.getRecordsResponse;\n // Move results to top\n const elementSet = xmlRecords.searchResults.elementSet;\n const recordsFieldName = `${elementSet}Record`;\n xmlRecords.records = xmlRecords.searchResults[recordsFieldName];\n delete xmlRecords.searchResults[recordsFieldName];\n convertXMLFieldToArrayInPlace(xmlRecords, 'records');\n for (const record of xmlRecords.records) {\n record.boundingBoxes = record.boundingBox;\n delete record.boundingBox;\n convertXMLFieldToArrayInPlace(record, 'boundingBoxes');\n for (const boundingBox of record.boundingBoxes) {\n boundingBox.value = [\n boundingBox.upperCorner[0],\n boundingBox.upperCorner[1],\n boundingBox.lowerCorner[0],\n boundingBox.lowerCorner[1]\n ];\n delete boundingBox.upperCorner;\n delete boundingBox.lowerCorner;\n }\n }\n return xmlRecords;\n}\nexport function renameXMLTags(xml, renameKeys) {\n for (const [oldKey, newKey] of Object.entries(renameKeys)) {\n xml[newKey] = xml[oldKey];\n delete xml[oldKey];\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseCSWRecords } from \"./lib/parsers/csw/parse-csw-records.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the CSW GetCapability request\n */\nexport const CSWRecordsLoader = {\n dataType: null,\n batchType: null,\n id: 'csw-records',\n name: 'CSW Records',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.csw_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n csw: {}\n },\n parse: async (arrayBuffer, options) => parseCSWRecords(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseCSWRecords(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\n/**\n * Extract an error message from WMS error response XML\n * @param text\n * @param options\n * @returns a string with a human readable message\n */\nexport function parseWMSError(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, options);\n const serviceExceptionXML = parsedXML?.ServiceExceptionReport?.ServiceException ||\n parsedXML?.['ogc:ServiceExceptionReport']?.['ogc:ServiceException'];\n // Sigh, can be either a string or an object\n const message = typeof serviceExceptionXML === 'string'\n ? serviceExceptionXML\n : serviceExceptionXML.value || serviceExceptionXML.code || 'Unknown error';\n return message;\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseWMSError } from \"./lib/parsers/wms/parse-wms-error.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the WMS GetCapability request\n */\nexport const WMSErrorLoader = {\n dataType: null,\n batchType: null,\n id: 'wms-error',\n name: 'WMS Error',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.se_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n wms: {\n throwOnError: false\n }\n },\n parse: async (arrayBuffer, options) => parseTextSync(new TextDecoder().decode(arrayBuffer), options),\n parseSync: (arrayBuffer, options) => parseTextSync(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseTextSync(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\nfunction parseTextSync(text, options) {\n const wmsOptions = { ...WMSErrorLoader.options.wms, ...options?.wms };\n const error = parseWMSError(text, wmsOptions);\n const message = wmsOptions.minimalErrors ? error : `WMS Service error: ${error}`;\n if (wmsOptions.throwOnError) {\n throw new Error(message);\n }\n return message;\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\nimport { getXMLArray, getXMLStringArray, getXMLInteger, getXMLFloat, getXMLBoolean } from \"../xml/parse-xml-helpers.js\";\n/**\n * Parses a typed data structure from raw XML for `GetCapabilities` response\n * @note Error handlings is fairly weak\n */\nexport function parseWMSCapabilities(xmlText, options) {\n const parsedXML = XMLLoader.parseTextSync?.(xmlText, options);\n const xmlCapabilities = parsedXML.WMT_MS_Capabilities || parsedXML.WMS_Capabilities || parsedXML;\n const capabilities = extractCapabilities(xmlCapabilities);\n // In case the processed, normalized capabilities do not contain everything,\n // the user can get the parsed XML structure.\n if (options?.inheritedLayerProps) {\n // Traverse layers and inject missing props from parents\n for (const layer of capabilities.layers) {\n addInheritedLayerProps(layer, null);\n }\n // Not yet implemented\n }\n if (options?.includeRawJSON) {\n capabilities.json = xmlCapabilities;\n }\n if (options?.includeXMLText) {\n capabilities.xml = xmlText;\n }\n return capabilities;\n}\n/** Extract typed capability data from XML */\nfunction extractCapabilities(xml) {\n const capabilities = {\n version: String(xml.version || ''),\n name: String(xml.Service?.Name || 'unnamed'),\n title: xml.Service?.Title ? String(xml.Service?.Title) : undefined,\n abstract: xml.Service?.Abstract ? String(xml.Service?.Abstract) : undefined,\n keywords: getXMLStringArray(xml.Service?.KeywordList?.Keyword),\n fees: xml.Service?.Fees ? JSON.stringify(xml.Service?.Fees) : undefined,\n accessConstraints: xml.Service?.AccessConstraints\n ? JSON.stringify(xml.Service?.AccessConstraints)\n : undefined,\n layerLimit: getXMLInteger(xml.Service?.LayerLimit),\n maxWidth: getXMLInteger(xml.Service?.maxWidth),\n maxHeight: getXMLInteger(xml.Service?.maxHeight),\n layers: [],\n requests: extractRequests(xml.Capability?.Request),\n exceptions: extractExceptions(xml.Exception)\n // contact field is a mess of largely irrelevant information, put it last\n // contact: xml.Service?.Contact ? JSON.stringify(xml.Service?.Contact) : undefined,\n };\n // LAYERS\n const xmlLayers = getXMLArray(xml.Capability?.Layer);\n for (const xmlSubLayer of xmlLayers) {\n capabilities.layers.push(extractLayer(xmlSubLayer));\n }\n // Clean up object\n for (const [key, value] of Object.entries(capabilities)) {\n if (value === undefined) {\n delete capabilities[key];\n }\n }\n return capabilities;\n}\n/** Extract typed request metadata from XML requests field */\nfunction extractRequests(xmlRequests) {\n const requests = {};\n for (const [name, xmlRequest] of Object.entries(xmlRequests || {})) {\n const mimeTypes = getXMLStringArray(xmlRequest?.Format);\n requests[name] = { mimeTypes };\n }\n return requests;\n}\nfunction extractExceptions(xmlException) {\n const xmlExceptionFormats = getXMLArray(xmlException?.Format);\n if (xmlExceptionFormats.length > 0) {\n return {\n mimeTypes: getXMLStringArray(xmlException)\n };\n }\n return undefined;\n}\n/** Extract request data */\n// eslint-disable-next-line complexity, max-statements\nfunction extractLayer(xmlLayer) {\n const layer = {\n // All layers must have a title\n title: String(xmlLayer?.Title || ''),\n // Name is required only if renderable\n name: xmlLayer?.Name && String(xmlLayer?.Name),\n abstract: xmlLayer?.Name && String(xmlLayer?.Abstract),\n keywords: getXMLStringArray(xmlLayer.KeywordList?.Keyword)\n };\n // WMS 1.3.0 changes SRS to CRS\n const crs = xmlLayer?.CRS || xmlLayer?.SRS;\n if (crs && Array.isArray(crs) && crs.every((_) => typeof _ === 'string')) {\n layer.crs = crs;\n }\n // v1.3.0 extract simple geographic bounding box\n let geographicBoundingBox = xmlLayer?.EX_GeographicBoundingBox && extractEXBoundingBox(xmlLayer?.EX_GeographicBoundingBox);\n if (geographicBoundingBox) {\n layer.geographicBoundingBox = geographicBoundingBox;\n }\n // v1.1.1 extract simple geographic bounding box\n geographicBoundingBox =\n xmlLayer?.LatLonBoundingBox && extractLatLonBoundingBox(xmlLayer?.LatLonBoundingBox);\n if (geographicBoundingBox) {\n layer.geographicBoundingBox = geographicBoundingBox;\n }\n // Extract per-CRS bounding boxes\n const boundingBoxes = xmlLayer?.BoundingBox && extractWMSBoundingBoxes(xmlLayer?.BoundingBox);\n if (boundingBoxes && boundingBoxes.length > 0) {\n layer.boundingBoxes = boundingBoxes;\n }\n // Extract dimensions\n const xmlDimensions = getXMLArray(xmlLayer?.Dimension);\n const dimensions = xmlDimensions.map((xml) => extractDimension(xml));\n if (dimensions.length) {\n layer.dimensions = dimensions;\n }\n if (xmlLayer?.opaque) {\n layer.opaque = getXMLBoolean(xmlLayer?.opaque);\n }\n if (xmlLayer?.cascaded) {\n layer.cascaded = getXMLBoolean(xmlLayer?.cascaded);\n }\n if (xmlLayer?.queryable) {\n layer.queryable = getXMLBoolean(xmlLayer?.queryable);\n }\n // Single layer is not represented as array in XML\n const xmlLayers = getXMLArray(xmlLayer?.Layer);\n const layers = [];\n for (const xmlSubLayer of xmlLayers) {\n layers.push(extractLayer(xmlSubLayer));\n }\n if (layers.length > 0) {\n layer.layers = layers;\n }\n // Clean up object\n for (const [key, value] of Object.entries(layer)) {\n if (value === undefined) {\n delete layer[key];\n }\n }\n return layer;\n}\n/** WMS 1.3.0 Loosely defined geospatial bounding box in unspecified CRS for quick content searches */\nfunction extractEXBoundingBox(xmlBoundingBox) {\n const { westBoundLongitude: w, northBoundLatitude: n, eastBoundLongitude: e, southBoundLatitude: s } = xmlBoundingBox;\n return [\n [w, s],\n [e, n]\n ];\n}\n/** WMS 1.1.1 Loosely defined geospatial bounding box in unspecified CRS for quick content searches */\nfunction extractLatLonBoundingBox(xmlBoundingBox) {\n const { minx, miny, maxx, maxy } = xmlBoundingBox;\n return [\n [minx, miny],\n [maxx, maxy]\n ];\n}\n/** Loosely defined geospatial bounding box in unspecified CRS for quick content searches */\nfunction extractWMSBoundingBoxes(xmlBoundingBoxes) {\n const xmlBoxes = getXMLArray(xmlBoundingBoxes);\n return xmlBoxes.map((xmlBox) => extractWMSBoundingBox(xmlBox));\n}\n/** Loosely defined geospatial bounding box in unspecified CRS for quick content searches */\nfunction extractWMSBoundingBox(xmlBoundingBox) {\n const { CRS, SRS, minx, miny, maxx, maxy, resx, resy } = xmlBoundingBox;\n const boundingBox = {\n // CRS in 1.3.0, SRS in 1.1.1\n crs: CRS || SRS,\n boundingBox: [\n [getXMLFloat(minx), getXMLFloat(miny)],\n [getXMLFloat(maxx), getXMLFloat(maxy)]\n ]\n };\n if (resx) {\n boundingBox.xResolution = resx;\n }\n if (resy) {\n boundingBox.yResolution = resy;\n }\n return boundingBox;\n}\n/**\n * Extracts optional WMS Dimension layer field\n * @param xmlDimension\n * @example <Dimension name=\"time\" units=\"ISO8601\" default=\"2018-01-01\" nearestValue=\"0\">2001-01-01/2018-01-01/P1Y</Dimension>\n * @see https://mapserver.org/ogc/wms_dimension.html\n */\nfunction extractDimension(xmlDimension) {\n const { name, units, value: extent } = xmlDimension;\n const dimension = { name, units, extent };\n if (xmlDimension.unitSymbol) {\n dimension.unitSymbol = xmlDimension.unitSymbol;\n }\n if (xmlDimension.default) {\n dimension.defaultValue = xmlDimension.default;\n }\n if (xmlDimension.multipleValues) {\n dimension.multipleValues = getXMLBoolean(xmlDimension.multipleValues);\n }\n if (xmlDimension.nearestValue) {\n dimension.nearestValue = getXMLBoolean(xmlDimension.nearestValue);\n }\n if (xmlDimension.current) {\n dimension.current = getXMLBoolean(xmlDimension.current);\n }\n return dimension;\n}\n/** Traverse layers and inject missing props from parents */\n// eslint-disable-next-line complexity\nfunction addInheritedLayerProps(layer, parent) {\n if (parent?.geographicBoundingBox && !layer.geographicBoundingBox) {\n layer.geographicBoundingBox = [...parent.geographicBoundingBox];\n }\n if (parent?.crs && !layer.crs) {\n layer.crs = [...parent.crs];\n }\n if (parent?.boundingBoxes && !layer.boundingBoxes) {\n layer.boundingBoxes = [...parent.boundingBoxes];\n }\n if (parent?.dimensions && !layer.dimensions) {\n layer.dimensions = [...parent.dimensions];\n }\n for (const subLayer of layer.layers || []) {\n addInheritedLayerProps(subLayer, layer);\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n/** A single element of an array is not represented as an array in XML */\nexport function getXMLArray(xmlValue) {\n // Already an array, return as is\n if (Array.isArray(xmlValue)) {\n return xmlValue;\n }\n // Single value, wrap in array\n if (xmlValue) {\n return [xmlValue];\n }\n // nullish, return empty array\n return [];\n}\n/** Get a list of strings from XML */\nexport function getXMLStringArray(xmlValue) {\n const xmlArray = getXMLArray(xmlValue);\n if (xmlArray.length > 0 && xmlArray.every((_) => typeof _ === 'string')) {\n return xmlArray;\n }\n // TODO - error handling?\n return [];\n}\n/** Get XML float */\nexport function getXMLFloat(xmlValue, defaultValue = undefined) {\n switch (typeof xmlValue) {\n case 'number':\n return xmlValue;\n case 'string':\n return parseFloat(xmlValue);\n default:\n return undefined;\n }\n}\n/** Get XML integer */\nexport function getXMLInteger(xmlValue, defaultValue = undefined) {\n switch (typeof xmlValue) {\n case 'number':\n return xmlValue;\n case 'string':\n return parseInt(xmlValue, 10);\n default:\n return undefined;\n }\n}\n/** Somewhat arbitrary boolean parsing */\nexport function getXMLBoolean(xmlValue) {\n switch (xmlValue) {\n case 'true':\n return true;\n case 'false':\n return false;\n case '1':\n return true;\n case '0':\n return false;\n default:\n return false;\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseWMSCapabilities } from \"./lib/parsers/wms/parse-wms-capabilities.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the WMS GetCapability request\n */\nexport const WMSCapabilitiesLoader = {\n dataType: null,\n batchType: null,\n id: 'wms-capabilities',\n name: 'WMS Capabilities',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.wms_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n wms: {}\n },\n parse: async (arrayBuffer, options) => \n // TODO pass in XML options\n parseWMSCapabilities(new TextDecoder().decode(arrayBuffer), options?.wms),\n parseTextSync: (text, options) => \n // TODO pass in XML options\n parseWMSCapabilities(text, options?.wms)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\n/**\n * Parses a typed data structure from raw XML for `GetFeatureInfo` response\n * @note Error handlings is fairly weak\n */\nexport function parseWMSFeatureInfo(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, options);\n const xmlFeatureInfo = parsedXML.FeatureInfoResponse?.FIELDS || [];\n const xmlFeatures = Array.isArray(xmlFeatureInfo) ? xmlFeatureInfo : [xmlFeatureInfo];\n return {\n features: xmlFeatures.map((xmlFeature) => extractFeature(xmlFeature))\n };\n}\nfunction extractFeature(xmlFeature) {\n const xmlFields = xmlFeature || {};\n // TODO - not correct\n return {\n attributes: xmlFields,\n type: '',\n bounds: { bottom: 0, top: 0, left: 0, right: 0 }\n };\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright vis.gl contributors\nimport { WMSCapabilitiesLoader } from \"../wms-capabilities-loader.js\";\nimport { parseWMSFeatureInfo } from \"../lib/parsers/wms/parse-wms-features.js\";\n/**\n * Loader for the response to the WMS GetFeatureInfo request\n */\nexport const WMSFeatureInfoLoader = {\n ...WMSCapabilitiesLoader,\n dataType: null,\n id: 'wms-feature-info',\n name: 'WMS FeatureInfo',\n parse: async (arrayBuffer, options) => parseWMSFeatureInfo(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseWMSFeatureInfo(text, options)\n};\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\n/**\n * Parses a typed data structure from raw XML for `GetFeatureInfo` response\n * @note Error handlings is fairly weak\n */\nexport function parseWMSLayerDescription(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, options);\n // TODO - implement parser\n return parsedXML;\n}\n", "// loaders.gl, MIT license\nimport { WMSCapabilitiesLoader } from \"../wms-capabilities-loader.js\";\nimport { parseWMSLayerDescription } from \"../lib/parsers/wms/parse-wms-layer-description.js\";\n/**\n * Loader for the response to the WMS DescribeLayer request\n */\nexport const WMSLayerDescriptionLoader = {\n ...WMSCapabilitiesLoader,\n dataType: null,\n id: 'wms-layer-description',\n name: 'WMS DescribeLayer',\n parse: async (arrayBuffer, options) => parseWMSLayerDescription(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseWMSLayerDescription(text, options)\n};\n", "// loaders.gl, MIT license\nimport { XMLLoader } from '@loaders.gl/xml';\n/**\n * Parses a typed data structure from raw XML for `GetCapabilities` response\n * @note Error handlings is fairly weak\n */\nexport function parseWFSCapabilities(text, options) {\n const parsedXML = XMLLoader.parseTextSync?.(text, {\n ...options,\n xml: {\n ...options?.xml,\n removeNSPrefix: true,\n uncapitalizeKeys: true\n }\n });\n const xmlCapabilities = parsedXML.Capabilities || parsedXML;\n return xmlCapabilities;\n}\n", "// loaders.gl, MIT license\nimport { parseWFSCapabilities } from \"./lib/parsers/wfs/parse-wfs-capabilities.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the WFS GetCapability request\n * @deprecated Warning: this loader is still experimental and incomplete\n */\nexport const WFSCapabilitiesLoader = {\n dataType: null,\n batchType: null,\n id: 'wfs-capabilities',\n name: 'WFS Capabilities',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.wfs_xml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n wfs: {}\n },\n parse: async (arrayBuffer, options) => parseWFSCapabilities(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseWFSCapabilities(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\nexport const _typecheckWFSCapabilitiesLoader = WFSCapabilitiesLoader;\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { XMLLoader } from '@loaders.gl/xml';\nimport { deepStrictEqual } from \"./deep-strict-equal.js\";\nimport rewind from '@turf/rewind';\nfunction noTransform(...coords) {\n return coords;\n}\n/**\n * Parses a typed data structure from raw XML for GML features\n * @note Error handlings is fairly weak\n */\nexport function parseGML(text, options) {\n // GeoJSON | null {\n const parsedXML = XMLLoader.parseTextSync?.(text, options);\n options = { transformCoords: noTransform, stride: 2, ...options };\n const context = createChildContext(parsedXML, options, {});\n return parseGMLToGeometry(parsedXML, options, context);\n}\n/** Parse a GeoJSON geometry from GML XML */\nexport function parseGMLToGeometry(inputXML, options, context) {\n const childContext = createChildContext(inputXML, options, context);\n let geometry = null;\n const [name, xml] = getFirstKeyValue(inputXML);\n switch (name) {\n // case 'gml:MultiPoint':\n // geometry = {\n // type: 'MultiPoint',\n // coordinates: parseMultiPoint(xml, options, childContext)\n // };\n // break;\n case 'gml:LineString':\n geometry = {\n type: 'LineString',\n coordinates: parseLinearRingOrLineString(xml, options, childContext)\n };\n break;\n // case 'gml:MultiLineString':\n // geometry = {\n // type: 'MultiLineString',\n // coordinates: parseMultiLineString(xml, options, childContext)\n // };\n // break;\n case 'gml:Polygon':\n case 'gml:Rectangle':\n geometry = {\n type: 'Polygon',\n coordinates: parsePolygonOrRectangle(xml, options, childContext)\n };\n break;\n case 'gml:Surface':\n geometry = {\n type: 'MultiPolygon',\n coordinates: parseSurface(xml, options, childContext)\n };\n break;\n case 'gml:MultiSurface':\n geometry = {\n type: 'MultiPolygon',\n coordinates: parseMultiSurface(xml, options, childContext)\n };\n break;\n default:\n return null;\n }\n // todo\n return rewind(geometry, { mutate: true });\n}\n/** Parse a list of coordinates from a string */\nfunction parseCoords(s, options, context) {\n const stride = context.srsDimension || options.stride || 2;\n // Handle white space\n const coords = s.replace(/\\s+/g, ' ').trim().split(' ');\n if (coords.length === 0 || coords.length % stride !== 0) {\n throw new Error(`invalid coordinates list (stride ${stride})`);\n }\n const points = [];\n for (let i = 0; i < coords.length - 1; i += stride) {\n const point = coords.slice(i, i + stride).map(parseFloat);\n points.push(options.transformCoords?.(...point) || point);\n }\n return points;\n}\nexport function parsePosList(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n const coords = textOf(xml);\n if (!coords) {\n throw new Error('invalid gml:posList element');\n }\n return parseCoords(coords, options, childContext);\n}\nexport function parsePos(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n const coords = textOf(xml);\n if (!coords) {\n throw new Error('invalid gml:pos element');\n }\n const points = parseCoords(coords, options, childContext);\n if (points.length !== 1) {\n throw new Error('gml:pos must have 1 point');\n }\n return points[0];\n}\nexport function parsePoint(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n // TODO AV: Parse other gml:Point options\n const pos = findIn(xml, 'gml:pos');\n if (!pos) {\n throw new Error('invalid gml:Point element, expected a gml:pos subelement');\n }\n return parsePos(pos, options, childContext);\n}\nexport function parseLinearRingOrLineString(xml, options, context) {\n // or a LineStringSegment\n const childContext = createChildContext(xml, options, context);\n let points = [];\n const posList = findIn(xml, 'gml:posList');\n if (posList) {\n points = parsePosList(posList, options, childContext);\n }\n else {\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:Point':\n points.push(parsePoint(childXML, options, childContext));\n break;\n case 'gml:pos':\n points.push(parsePos(childXML, options, childContext));\n break;\n default:\n continue;\n }\n }\n }\n if (points.length === 0) {\n throw new Error(`${xml.name} must have > 0 points`);\n }\n return points;\n}\nexport function parseCurveSegments(xml, options, context) {\n const points = [];\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:LineStringSegment':\n const points2 = parseLinearRingOrLineString(childXML, options, context);\n // remove overlapping\n const end = points[points.length - 1];\n const start = points2[0];\n if (end && start && deepStrictEqual(end, start)) {\n points2.shift();\n }\n points.push(...points2);\n break;\n default:\n continue;\n }\n }\n if (points.length === 0) {\n throw new Error('gml:Curve > gml:segments must have > 0 points');\n }\n return points;\n}\nexport function parseRing(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n const points = [];\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:curveMember':\n let points2;\n const lineString = findIn(childXML, 'gml:LineString');\n if (lineString) {\n points2 = parseLinearRingOrLineString(lineString, options, childContext);\n }\n else {\n const segments = findIn(childXML, 'gml:Curve', 'gml:segments');\n if (!segments) {\n throw new Error(`invalid ${childName} element`);\n }\n points2 = parseCurveSegments(segments, options, childContext);\n }\n // remove overlapping\n const end = points[points.length - 1];\n const start = points2[0];\n if (end && start && deepStrictEqual(end, start)) {\n points2.shift();\n }\n points.push(...points2);\n break;\n }\n }\n if (points.length < 4) {\n throw new Error(`${xml.name} must have >= 4 points`);\n }\n return points;\n}\nexport function parseExteriorOrInterior(xml, options, context) {\n const linearRing = findIn(xml, 'gml:LinearRing');\n if (linearRing) {\n return parseLinearRingOrLineString(linearRing, options, context);\n }\n const ring = findIn(xml, 'gml:Ring');\n if (!ring) {\n throw new Error(`invalid ${xml.name} element`);\n }\n return parseRing(ring, options, context);\n}\nexport function parsePolygonOrRectangle(xml, options, context) {\n // or PolygonPatch\n const childContext = createChildContext(xml, options, context);\n const exterior = findIn(xml, 'gml:exterior');\n if (!exterior) {\n throw new Error(`invalid ${xml.name} element`);\n }\n const pointLists = [parseExteriorOrInterior(exterior, options, childContext)];\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:interior':\n pointLists.push(parseExteriorOrInterior(childXML, options, childContext));\n break;\n }\n }\n return pointLists;\n}\nexport function parseSurface(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n const patches = findIn(xml, 'gml:patches');\n if (!patches) {\n throw new Error(`invalid ${xml.name} element`);\n }\n const polygons = [];\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:PolygonPatch':\n case 'gml:Rectangle':\n polygons.push(parsePolygonOrRectangle(childXML, options, childContext));\n break;\n default:\n continue;\n }\n }\n if (polygons.length === 0) {\n throw new Error(`${xml.name} must have > 0 polygons`);\n }\n return polygons;\n}\nexport function parseCompositeSurface(xml, options, context) {\n const childContext = createChildContext(xml, options, context);\n const polygons = [];\n for (const [childName, childXML] of Object.entries(xml)) {\n switch (childName) {\n case 'gml:surfaceMember':\n case 'gml:surfaceMembers':\n const [c2Name, c2Xml] = getFirstKeyValue(childXML);\n switch (c2Name) {\n case 'gml:Surface':\n polygons.push(...parseSurface(c2Xml, options, childContext));\n break;\n case 'gml:Polygon':\n polygons.push(parsePolygonOrRectangle(c2Xml, options, childContext));\n break;\n }\n break;\n }\n }\n if (polygons.length === 0) {\n throw new Error(`${xml.name} must have > 0 polygons`);\n }\n return polygons;\n}\nexport function parseMultiSurface(xml, options, context) {\n let el = xml;\n const surfaceMembers = findIn(xml, 'gml:LinearRing');\n if (surfaceMembers) {\n el = surfaceMembers;\n }\n const polygons = [];\n for (const [childName, childXML] of Object.entries(el)) {\n switch (childName) {\n case 'gml:Surface':\n const polygons2 = parseSurface(childXML, options, context);\n polygons.push(...polygons2);\n break;\n case 'gml:surfaceMember':\n const polygons3 = parseSurfaceMember(childXML, options, context);\n polygons.push(...polygons3);\n break;\n case 'gml:surfaceMembers':\n const polygonXML = findIn(childXML, 'gml:Polygon');\n for (const surfaceMemberXML of polygonXML) {\n const polygons3 = parseSurfaceMember(surfaceMemberXML, options, context);\n polygons.push(...polygons3);\n }\n break;\n }\n }\n if (polygons.length === 0) {\n throw new Error(`${xml.name} must have > 0 polygons`);\n }\n return polygons;\n}\nfunction parseSurfaceMember(xml, options, context) {\n const [childName, childXml] = getFirstKeyValue(xml);\n switch (childName) {\n case 'gml:CompositeSurface':\n return parseCompositeSurface(childXml, options, context);\n case 'gml:Surface':\n return parseSurface(childXml, options, context);\n case 'gml:Polygon':\n return [parsePolygonOrRectangle(childXml, options, context)];\n }\n throw new Error(`${childName} must have polygons`);\n}\n// Helpers\nfunction textOf(el) {\n if (typeof el !== 'string') {\n throw new Error('expected string');\n }\n return el;\n}\nfunction findIn(root, ...tags) {\n let el = root;\n for (const tag of tags) {\n const child = el[tag];\n if (!child) {\n return null;\n }\n el = child;\n }\n return el;\n}\n/** @returns the first [key, value] pair in an object, or ['', null] if empty object */\nfunction getFirstKeyValue(object) {\n if (object && typeof object === 'object') {\n for (const [key, value] of Object.entries(object)) {\n return [key, value];\n }\n }\n return ['', null];\n}\n/** A bit heavyweight for just tracking dimension? */\nfunction createChildContext(xml, options, context) {\n const srsDimensionAttribute = xml.attributes && xml.attributes.srsDimension;\n if (srsDimensionAttribute) {\n const srsDimension = parseInt(srsDimensionAttribute);\n if (Number.isNaN(srsDimension) || srsDimension <= 0) {\n throw new Error(`invalid srsDimension attribute value \"${srsDimensionAttribute}\", expected a positive integer`);\n }\n const childContext = Object.create(context);\n childContext.srsDimension = srsDimension;\n return childContext;\n }\n return context;\n}\n", "// https://github.com/nodejs/node/commit/c1d82ac2ff15594840e2a1b9531b506ae067ed27;\n// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\n//\n// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\n//\n// Originally from narwhal.js (http://narwhaljs.org)\n// Copyright (c) 2009 Thomas Robinson <280north.com>\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the 'Software'), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n/** @todo replace this ridiculous choice of deepStrictEqual */\n// eslint-disable-next-line complexity\nexport function deepStrictEqual(actual, expected, strict) {\n // 7.1. All identical values are equivalent, as determined by ===.\n if (actual === expected) {\n return true;\n // } else if (actual instanceof Buffer && expected instanceof Buffer) {\n // return compare(actual, expected) === 0;\n // // 7.2. If the expected value is a Date object, the actual value is\n // // equivalent if it is also a Date object that refers to the same time.\n }\n else if (actual instanceof Date && expected instanceof Date) {\n return actual.getTime() === expected.getTime();\n // 7.3 If the expected value is a RegExp object, the actual value is\n // equivalent if it is also a RegExp object with the same source and\n // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).\n }\n else if (actual instanceof RegExp && expected instanceof RegExp) {\n return (actual.source === expected.source &&\n actual.global === expected.global &&\n actual.multiline === expected.multiline &&\n actual.lastIndex === expected.lastIndex &&\n actual.ignoreCase === expected.ignoreCase);\n // 7.4. Other pairs that do not both pass typeof value == 'object',\n // equivalence is determined by ==.\n }\n else if ((actual === null || typeof actual !== 'object') &&\n (expected === null || typeof expected !== 'object')) {\n // eslint-disable-next-line eqeqeq\n return strict ? actual === expected : actual == expected;\n // 7.5 For all other Object pairs, including Array objects, equivalence is\n // determined by having the same number of owned properties (as verified\n // with Object.prototype.hasOwnProperty.call), the same set of keys\n // (although not necessarily the same order), equivalent values for every\n // corresponding key, and an identical 'prototype' property. Note: this\n // accounts for both named and indexed properties on Arrays.\n }\n return objEquiv(actual, expected, strict);\n}\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst pSlice = Array.prototype.slice;\nfunction isPrimitive(arg) {\n return arg === null || (typeof arg !== 'object' && typeof arg !== 'function');\n}\nfunction isArguments(object) {\n // eslint-disable-next-line eqeqeq\n return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n// eslint-disable-next-line complexity\nfunction objEquiv(a, b, strict) {\n if (a === null || a === undefined || b === null || b === undefined)\n return false;\n // if one is a primitive, the other must be same\n if (isPrimitive(a) || isPrimitive(b))\n return a === b;\n if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))\n return false;\n const aIsArgs = isArguments(a);\n const bIsArgs = isArguments(b);\n if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))\n return false;\n if (aIsArgs) {\n a = pSlice.call(a);\n b = pSlice.call(b);\n return deepStrictEqual(a, b, strict);\n }\n const ka = Object.keys(a);\n const kb = Object.keys(b);\n let key;\n let i;\n // having the same number of owned properties (keys incorporates\n // hasOwnProperty)\n if (ka.length !== kb.length)\n return false;\n // the same set of keys (although not necessarily the same order),\n ka.sort();\n kb.sort();\n // ~~~cheap key test\n for (i = ka.length - 1; i >= 0; i--) {\n if (ka[i] !== kb[i])\n return false;\n }\n // equivalent values for every corresponding key, and\n // ~~~possibly expensive deep test\n for (i = ka.length - 1; i >= 0; i--) {\n key = ka[i];\n // @ts-ignore\n if (!deepStrictEqual(a[key], b[key], strict))\n return false;\n }\n return true;\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { parseGML } from \"./lib/parsers/gml/parse-gml.js\";\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof \"4.3.3\" !== 'undefined' ? \"4.3.3\" : 'latest';\n/**\n * Loader for the response to the GML GetCapability request\n */\nexport const GMLLoader = {\n dataType: null,\n batchType: null,\n name: 'GML',\n id: 'gml',\n module: 'wms',\n version: VERSION,\n worker: false,\n extensions: ['xml'],\n mimeTypes: ['application/vnd.ogc.gml', 'application/xml', 'text/xml'],\n testText: testXMLFile,\n options: {\n gml: {}\n },\n parse: async (arrayBuffer, options) => parseGML(new TextDecoder().decode(arrayBuffer), options),\n parseTextSync: (text, options) => parseGML(text, options)\n};\nfunction testXMLFile(text) {\n // TODO - There could be space first.\n return text.startsWith('<?xml');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { ImageLoader } from '@loaders.gl/images';\nimport { mergeLoaderOptions, ImageSource } from '@loaders.gl/loader-utils';\nimport { WMSCapabilitiesLoader } from \"../../wms-capabilities-loader.js\";\nimport { WMSFeatureInfoLoader } from \"../../wip/wms-feature-info-loader.js\";\nimport { WMSLayerDescriptionLoader } from \"../../wip/wms-layer-description-loader.js\";\nimport { WMSErrorLoader } from \"../../wms-error-loader.js\";\nexport const WMSSource = {\n name: 'Web Map Service (OGC WMS)',\n id: 'wms',\n module: 'wms',\n version: '0.0.0',\n extensions: [],\n mimeTypes: [],\n options: {\n wms: {\n // TODO - add options here\n }\n },\n type: 'wms',\n fromUrl: true,\n fromBlob: false,\n testURL: (url) => url.toLowerCase().includes('wms'),\n createDataS