diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 625f077..4a0ad7c 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,7 +1,9 @@ module.exports = { - extends: '@terrestris/eslint-config-typescript', + extends: [ + '@terrestris/eslint-config-typescript', + 'prettier' + ], rules: { - 'no-underscore-dangle': 'off', 'no-shadow': 'off', '@typescript-eslint/no-shadow': ['error'], camelcase: [ diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000..0c83ac4 --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/README.md b/README.md index 15e0323..d8bf269 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ Geostyler Style Parser for ArcGIS Pro layer file format `.lyrx` This is **pre-alpha version**, without correct type, and no test. Be careful. -This project is originally based on the GeoCat/bridge-style (MIT license). \ No newline at end of file +This project is originally based on the GeoCat/bridge-style (MIT license). diff --git a/package-lock.json b/package-lock.json index b805f6b..4586c76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,8 @@ "conventional-changelog-conventionalcommits": "^8.0.0", "coveralls": "^3.1.1", "eslint": "^8.40.0", + "eslint-config-prettier": "^9.1.0", + "prettier": "^3.3.3", "typescript": "^5.4.5", "vitest": "^2.0.0" }, @@ -3910,6 +3912,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -5135,6 +5149,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 8580040..3b3dc4f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ "scripts": { "build": "babel src -d dist --source-maps --extensions '.ts' && tsc --declaration", "typecheck": " tsc --project tsconfig-typecheck.json", - "lint": "eslint -c .eslintrc.cjs src/**/*.ts", + "lint": "eslint -c .eslintrc.cjs src/**/*.ts && npm run prettier:check", + "prettier:check": "prettier src --write", + "prettier": "prettier src --write", "prepublishOnly": "npm run build", "release": "np --no-yarn", "test": "vitest", @@ -50,6 +52,8 @@ "conventional-changelog-conventionalcommits": "^8.0.0", "coveralls": "^3.1.1", "eslint": "^8.40.0", + "eslint-config-prettier": "^9.1.0", + "prettier": "^3.3.3", "typescript": "^5.4.5", "vitest": "^2.0.0" }, diff --git a/src/constants.ts b/src/constants.ts index 4626493..a0bee32 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,15 +1,15 @@ -export const ESRI_SYMBOLS_FONT: string = 'ESRI Default Marker'; +export const ESRI_SYMBOLS_FONT: string = "ESRI Default Marker"; export const POLYGON_FILL_RESIZE_FACTOR: number = 2 / 3; export const OFFSET_FACTOR: number = 4 / 3; export enum MarkerPlacementPosition { - START = 'startPoint', - END = 'endPoint' + START = "startPoint", + END = "endPoint", } export enum MarkerPlacementAngle { - START = 'startAngle', - END = 'endAngle' + START = "startAngle", + END = "endAngle", } export const ptToPx = (pt: number): number => { diff --git a/src/esri/types/CIMFeatureTable.ts b/src/esri/types/CIMFeatureTable.ts index f53bb0d..d39b6f2 100644 --- a/src/esri/types/CIMFeatureTable.ts +++ b/src/esri/types/CIMFeatureTable.ts @@ -1,4 +1 @@ - -export type CIMFeatureTable = { - -}; +export type CIMFeatureTable = {}; diff --git a/src/esri/types/CIMLayerAction.ts b/src/esri/types/CIMLayerAction.ts index 888c2c4..dccdca3 100644 --- a/src/esri/types/CIMLayerAction.ts +++ b/src/esri/types/CIMLayerAction.ts @@ -1,18 +1,17 @@ - type CIMActivity = {}; type CIMCondition = {}; export type CIMLayerAction = { - /** - * Gets or sets the name. - */ - name?: null | string; - /** - * Gets or sets activities. - */ - activities?: CIMActivity[] | null; - /** - * Gets or sets conditions. - */ - conditions?: CIMCondition[] | null; + /** + * Gets or sets the name. + */ + name?: null | string; + /** + * Gets or sets activities. + */ + activities?: CIMActivity[] | null; + /** + * Gets or sets conditions. + */ + conditions?: CIMCondition[] | null; }; diff --git a/src/esri/types/CIMLayerDocument.ts b/src/esri/types/CIMLayerDocument.ts index 7ac526b..f0afce2 100644 --- a/src/esri/types/CIMLayerDocument.ts +++ b/src/esri/types/CIMLayerDocument.ts @@ -1,7 +1,6 @@ -import { CIMLayerDefinition } from './layers/CIMLayerDefinition.ts'; - +import { CIMLayerDefinition } from "./layers/CIMLayerDefinition.ts"; export type CIMLayerDocument = { - name: string; - layerDefinitions: CIMLayerDefinition[]; + name: string; + layerDefinitions: CIMLayerDefinition[]; }; diff --git a/src/esri/types/CIMObject.ts b/src/esri/types/CIMObject.ts index 3240d99..eb1bff4 100644 --- a/src/esri/types/CIMObject.ts +++ b/src/esri/types/CIMObject.ts @@ -1,4 +1,3 @@ - export type CIMObject = { - type: string; + type: string; }; diff --git a/src/esri/types/index.ts b/src/esri/types/index.ts index 96dab8b..88f84e3 100644 --- a/src/esri/types/index.ts +++ b/src/esri/types/index.ts @@ -1,5 +1,4 @@ - -export * from './CIMLayerDocument.ts'; -export * from './labeling/index.ts'; -export * from './layers/index.ts'; -export * from './renderers/index.ts'; +export * from "./CIMLayerDocument.ts"; +export * from "./labeling/index.ts"; +export * from "./layers/index.ts"; +export * from "./renderers/index.ts"; diff --git a/src/esri/types/labeling/CIMLabelClass.ts b/src/esri/types/labeling/CIMLabelClass.ts index ed561d0..ef8671b 100644 --- a/src/esri/types/labeling/CIMLabelClass.ts +++ b/src/esri/types/labeling/CIMLabelClass.ts @@ -1,15 +1,15 @@ -import { CIMObject } from '../CIMObject.ts'; -import { CIMMaplexLabelPlacementProperties } from './CIMMaplexLabelPlacementProperties.ts'; -import { CIMStandardLabelPlacementProperties } from './CIMStandardLabelPlacementProperties.ts'; -import { CIMSymbolReference } from './CIMSymbolReference.ts'; +import { CIMObject } from "../CIMObject.ts"; +import { CIMMaplexLabelPlacementProperties } from "./CIMMaplexLabelPlacementProperties.ts"; +import { CIMStandardLabelPlacementProperties } from "./CIMStandardLabelPlacementProperties.ts"; +import { CIMSymbolReference } from "./CIMSymbolReference.ts"; type FeaturesToLabel = {}; export enum LabelExpressionEngine { - VBScript = 'VBScript', - JScript = 'JScript', - Python = 'Python', - Arcade = 'Arcade', + VBScript = "VBScript", + JScript = "JScript", + Python = "Python", + Arcade = "Arcade", } /** diff --git a/src/esri/types/labeling/CIMMaplexLabelPlacementProperties.ts b/src/esri/types/labeling/CIMMaplexLabelPlacementProperties.ts index 91ab56c..dc9679c 100644 --- a/src/esri/types/labeling/CIMMaplexLabelPlacementProperties.ts +++ b/src/esri/types/labeling/CIMMaplexLabelPlacementProperties.ts @@ -515,7 +515,7 @@ export type CIMMaplexLabelPlacementProperties = CIMObject & { * Gets or sets the unit of the inset value for perimeter polygon anchor points. */ polygonAnchorPointPerimeterInsetUnit?: MaplexUnit; -} +}; /** * Represents the properties required for authoring an Arcade expression. */ @@ -536,7 +536,7 @@ export type CIMExpressionInfo = { * Gets or sets the ReturnType of the expression. */ returnType?: ExpressionReturnType; -} +}; /** * Represents Maplex label stacking properties. * @@ -566,7 +566,7 @@ export type CIMMaplexLabelStackingProperties = CIMObject & { * Gets or sets a value indicating whether leading and trailing stacking separators are trimmed from the label string. */ trimStackingSeparators?: boolean; -} +}; /** * Represents a Maplex stacking separator. * diff --git a/src/esri/types/labeling/CIMMaplexRotationProperties.ts b/src/esri/types/labeling/CIMMaplexRotationProperties.ts index 2a2d22f..a7a98cf 100644 --- a/src/esri/types/labeling/CIMMaplexRotationProperties.ts +++ b/src/esri/types/labeling/CIMMaplexRotationProperties.ts @@ -1,9 +1,9 @@ -import { CIMObject } from '../CIMObject.ts'; +import { CIMObject } from "../CIMObject.ts"; import { MaplexLabelRotationType, MaplexRotationAlignmentType, - CIMExpressionInfo -} from './CIMMaplexLabelPlacementProperties.ts'; + CIMExpressionInfo, +} from "./CIMMaplexLabelPlacementProperties.ts"; /** * Represents Maplex rotation properties. diff --git a/src/esri/types/labeling/CIMMaplexStrategyPriorities.ts b/src/esri/types/labeling/CIMMaplexStrategyPriorities.ts index 88431cd..ba08dbe 100644 --- a/src/esri/types/labeling/CIMMaplexStrategyPriorities.ts +++ b/src/esri/types/labeling/CIMMaplexStrategyPriorities.ts @@ -1,4 +1,4 @@ -import { CIMObject } from '../CIMObject.ts'; +import { CIMObject } from "../CIMObject.ts"; /** * Represents Maplex strategy priorities. diff --git a/src/esri/types/labeling/CIMStandardLabelPlacementProperties.ts b/src/esri/types/labeling/CIMStandardLabelPlacementProperties.ts index 532cb23..9e40560 100644 --- a/src/esri/types/labeling/CIMStandardLabelPlacementProperties.ts +++ b/src/esri/types/labeling/CIMStandardLabelPlacementProperties.ts @@ -116,7 +116,7 @@ export type CIMStandardLabelPlacementProperties = CIMObject & { * Gets or sets a value indicating whether or not to allow overlapping labels. */ allowOverlappingLabels?: boolean; -} +}; /** * Represents standard label engine line label position. * diff --git a/src/esri/types/labeling/CIMSymbolReference.ts b/src/esri/types/labeling/CIMSymbolReference.ts index 298e47d..41d6920 100644 --- a/src/esri/types/labeling/CIMSymbolReference.ts +++ b/src/esri/types/labeling/CIMSymbolReference.ts @@ -1,13 +1,12 @@ -import { CIMSymbol } from '../symbols/index.ts'; +import { CIMSymbol } from "../symbols/index.ts"; type CIMPrimitiveOverride = {}; type CIMScaleDependentSizeVariation = {}; - export type Geometry = { - rings?: number[][][]; - paths?: number[][][]; - curveRings?: { a?: number[][]; c?: number[][] }[][]; + rings?: number[][][]; + paths?: number[][][]; + curveRings?: { a?: number[][]; c?: number[][] }[][]; }; /** @@ -15,41 +14,41 @@ export type Geometry = { * */ export type CIMSymbolReference = { - geometry: Geometry; - /** - * Gets or sets the primitive overrides. Typically set by renderers at draw time. - */ - primitiveOverrides?: CIMPrimitiveOverride[] | null; - /** - * Gets or sets the style path. Reserved for future use. - */ - stylePath?: null | string; - /** - * Gets or sets the symbol. - */ - symbol?: null | CIMSymbol; - /** - * Gets or sets the symbol name. - */ - symbolName?: null | string; - /** - * Gets or sets the minimum scale range the symbol reference should be displayed at. - */ - minScale?: number; - /** - * Gets or sets the maximum scale range the symbol reference should be displayed at. - */ - maxScale?: number; - /** - * Gets or sets an array of scale dependent sizes. - */ - scaleDependentSizeVariation?: CIMScaleDependentSizeVariation[] | null; - /** - * Gets or sets the minimum distance at which symbols are visible. Objects closer than this don't get rendered. - */ - minDistance?: number; - /** - * Gets or sets the maximum distance at which symbols are visible. Objects beyond this point don't get rendered. - */ - maxDistance?: number; - }; + geometry: Geometry; + /** + * Gets or sets the primitive overrides. Typically set by renderers at draw time. + */ + primitiveOverrides?: CIMPrimitiveOverride[] | null; + /** + * Gets or sets the style path. Reserved for future use. + */ + stylePath?: null | string; + /** + * Gets or sets the symbol. + */ + symbol?: null | CIMSymbol; + /** + * Gets or sets the symbol name. + */ + symbolName?: null | string; + /** + * Gets or sets the minimum scale range the symbol reference should be displayed at. + */ + minScale?: number; + /** + * Gets or sets the maximum scale range the symbol reference should be displayed at. + */ + maxScale?: number; + /** + * Gets or sets an array of scale dependent sizes. + */ + scaleDependentSizeVariation?: CIMScaleDependentSizeVariation[] | null; + /** + * Gets or sets the minimum distance at which symbols are visible. Objects closer than this don't get rendered. + */ + minDistance?: number; + /** + * Gets or sets the maximum distance at which symbols are visible. Objects beyond this point don't get rendered. + */ + maxDistance?: number; +}; diff --git a/src/esri/types/labeling/LabelFeatureType.ts b/src/esri/types/labeling/LabelFeatureType.ts index df53da9..0d6c6c5 100644 --- a/src/esri/types/labeling/LabelFeatureType.ts +++ b/src/esri/types/labeling/LabelFeatureType.ts @@ -1,5 +1,5 @@ export enum LabelFeatureType { - Point = 'Point' , - Line = 'Line', - Polygon = 'Polygon' + Point = "Point", + Line = "Line", + Polygon = "Polygon", } diff --git a/src/esri/types/labeling/index.ts b/src/esri/types/labeling/index.ts index 4ca3ff3..3dbf0c1 100644 --- a/src/esri/types/labeling/index.ts +++ b/src/esri/types/labeling/index.ts @@ -1,3 +1,3 @@ -export * from './CIMLabelClass.ts'; -export * from './CIMSymbolReference.ts'; -export * from './LabelFeatureType.ts'; +export * from "./CIMLabelClass.ts"; +export * from "./CIMSymbolReference.ts"; +export * from "./LabelFeatureType.ts"; diff --git a/src/esri/types/layers/CIMFeatureLayer.ts b/src/esri/types/layers/CIMFeatureLayer.ts index f38e86c..c8a2277 100644 --- a/src/esri/types/layers/CIMFeatureLayer.ts +++ b/src/esri/types/layers/CIMFeatureLayer.ts @@ -1,8 +1,8 @@ -import { CIMLayerAction } from '../CIMLayerAction.ts'; -import { CIMLayerDefinition } from './CIMLayerDefinition.ts'; -import { CIMLabelClass } from '../labeling/CIMLabelClass.ts'; -import { CIMSymbolReference } from '../labeling/CIMSymbolReference.ts'; -import {CIMRenderer} from '../renderers'; +import { CIMLayerAction } from "../CIMLayerAction.ts"; +import { CIMLayerDefinition } from "./CIMLayerDefinition.ts"; +import { CIMLabelClass } from "../labeling/CIMLabelClass.ts"; +import { CIMSymbolReference } from "../labeling/CIMSymbolReference.ts"; +import { CIMRenderer } from "../renderers"; type CIMDataConnection = {}; type CIMSymbolLayerMasking = {}; diff --git a/src/esri/types/layers/CIMLayerDefinition.ts b/src/esri/types/layers/CIMLayerDefinition.ts index 6c9e7e4..5897bd6 100644 --- a/src/esri/types/layers/CIMLayerDefinition.ts +++ b/src/esri/types/layers/CIMLayerDefinition.ts @@ -1,5 +1,5 @@ -import { CIMObject } from '../CIMObject.ts'; +import { CIMObject } from "../CIMObject.ts"; export type CIMLayerDefinition = CIMObject & { - name: string; + name: string; }; diff --git a/src/esri/types/layers/CIMRasterLayer.ts b/src/esri/types/layers/CIMRasterLayer.ts index c95bce2..4483c82 100644 --- a/src/esri/types/layers/CIMRasterLayer.ts +++ b/src/esri/types/layers/CIMRasterLayer.ts @@ -1,5 +1,3 @@ -import { CIMLayerDefinition } from './CIMLayerDefinition.ts'; +import { CIMLayerDefinition } from "./CIMLayerDefinition.ts"; -export type CIMRasterLayer = CIMLayerDefinition & { - -}; +export type CIMRasterLayer = CIMLayerDefinition & {}; diff --git a/src/esri/types/layers/index.ts b/src/esri/types/layers/index.ts index 996be80..3222ee7 100644 --- a/src/esri/types/layers/index.ts +++ b/src/esri/types/layers/index.ts @@ -1,4 +1,3 @@ - -export * from './CIMLayerDefinition.ts'; -export * from './CIMFeatureLayer.ts'; -export * from './CIMRasterLayer.ts'; +export * from "./CIMLayerDefinition.ts"; +export * from "./CIMFeatureLayer.ts"; +export * from "./CIMRasterLayer.ts"; diff --git a/src/esri/types/renderers/CIMBreaksRenderer.ts b/src/esri/types/renderers/CIMBreaksRenderer.ts index 3dfa458..9a856a5 100644 --- a/src/esri/types/renderers/CIMBreaksRenderer.ts +++ b/src/esri/types/renderers/CIMBreaksRenderer.ts @@ -1,17 +1,17 @@ -import {CIMRenderer, Group } from './CIMRenderer.ts'; -import {CIMSymbolReference} from '../labeling'; +import { CIMRenderer, Group } from "./CIMRenderer.ts"; +import { CIMSymbolReference } from "../labeling"; export type CIMBreaksRenderer = CIMRenderer & { - classBreakType: string; - defaultSymbol?: CIMSymbolReference; - field: string; - groups?: Group[]; - showInAscendingOrder: boolean; - breaks: { - type: string; - fieldValues: string[]; - label: string; - symbol: CIMSymbolReference; - upperBound: number; - }[]; + classBreakType: string; + defaultSymbol?: CIMSymbolReference; + field: string; + groups?: Group[]; + showInAscendingOrder: boolean; + breaks: { + type: string; + fieldValues: string[]; + label: string; + symbol: CIMSymbolReference; + upperBound: number; + }[]; }; diff --git a/src/esri/types/renderers/CIMRenderer.ts b/src/esri/types/renderers/CIMRenderer.ts index 0d1709c..59f0526 100644 --- a/src/esri/types/renderers/CIMRenderer.ts +++ b/src/esri/types/renderers/CIMRenderer.ts @@ -1,38 +1,37 @@ -import {CIMObject} from '../CIMObject.ts'; -import {CIMSymbolReference} from '../labeling'; - +import { CIMObject } from "../CIMObject.ts"; +import { CIMSymbolReference } from "../labeling"; export type Class = { - alternateSymbols: CIMSymbolReference[]; - label: string; - filter: string; - symbol: CIMSymbolReference; - minValue?: number; - maxValue?: number; - breakCount?: number; - breakValues?: number[]; - breakLabels?: string[]; - breakSymbols?: CIMSymbolReference[]; - values: { - type: string; - fieldValues: string[]; - }[]; + alternateSymbols: CIMSymbolReference[]; + label: string; + filter: string; + symbol: CIMSymbolReference; + minValue?: number; + maxValue?: number; + breakCount?: number; + breakValues?: number[]; + breakLabels?: string[]; + breakSymbols?: CIMSymbolReference[]; + values: { + type: string; + fieldValues: string[]; + }[]; }; export type Group = { - classes: Class[]; + classes: Class[]; }; export type VisualVariable = CIMObject & { - rotationTypeZ: string; - visualVariableInfoZ: { - expression: string; - valueExpressionInfo: { - expression: string; - }; - }; + rotationTypeZ: string; + visualVariableInfoZ: { + expression: string; + valueExpressionInfo: { + expression: string; + }; + }; }; export type CIMRenderer = CIMObject & { - visualVariables?: VisualVariable[]; + visualVariables?: VisualVariable[]; }; diff --git a/src/esri/types/renderers/CIMSimpleRenderer.ts b/src/esri/types/renderers/CIMSimpleRenderer.ts index 608c135..9a6e47d 100644 --- a/src/esri/types/renderers/CIMSimpleRenderer.ts +++ b/src/esri/types/renderers/CIMSimpleRenderer.ts @@ -1,7 +1,7 @@ -import {CIMRenderer} from './CIMRenderer.ts'; -import {CIMSymbolReference} from '../labeling'; +import { CIMRenderer } from "./CIMRenderer.ts"; +import { CIMSymbolReference } from "../labeling"; export type CIMSimpleRenderer = CIMRenderer & { - label: string; - symbol: CIMSymbolReference; + label: string; + symbol: CIMSymbolReference; }; diff --git a/src/esri/types/renderers/CIMUniqueValueRenderer.ts b/src/esri/types/renderers/CIMUniqueValueRenderer.ts index b6d35be..2a2dc93 100644 --- a/src/esri/types/renderers/CIMUniqueValueRenderer.ts +++ b/src/esri/types/renderers/CIMUniqueValueRenderer.ts @@ -1,8 +1,8 @@ -import {CIMRenderer, Group} from './CIMRenderer.ts'; -import {CIMSymbolReference} from '../labeling'; +import { CIMRenderer, Group } from "./CIMRenderer.ts"; +import { CIMSymbolReference } from "../labeling"; export type CIMUniqueValueRenderer = CIMRenderer & { - defaultSymbol?: CIMSymbolReference; - fields?: string[]; - groups?: Group[]; + defaultSymbol?: CIMSymbolReference; + fields?: string[]; + groups?: Group[]; }; diff --git a/src/esri/types/renderers/index.ts b/src/esri/types/renderers/index.ts index 1f20e9f..91c5095 100644 --- a/src/esri/types/renderers/index.ts +++ b/src/esri/types/renderers/index.ts @@ -1,2 +1,2 @@ -export * from './CIMRenderer.ts'; -export * from './CIMUniqueValueRenderer.ts'; +export * from "./CIMRenderer.ts"; +export * from "./CIMUniqueValueRenderer.ts"; diff --git a/src/esri/types/symbols/CIMSymbol.ts b/src/esri/types/symbols/CIMSymbol.ts index 65c02a6..dce43a1 100644 --- a/src/esri/types/symbols/CIMSymbol.ts +++ b/src/esri/types/symbols/CIMSymbol.ts @@ -1,41 +1,41 @@ -import { CIMObject } from '../CIMObject.ts'; -import {CIMColor} from './CIMTextSymbol.ts'; -import {CIMSymbolReference} from '../labeling'; +import { CIMObject } from "../CIMObject.ts"; +import { CIMColor } from "./CIMTextSymbol.ts"; +import { CIMSymbolReference } from "../labeling"; export type CIMColorType = CIMColor & CIMObject; export type CIMMarkerPlacement = CIMObject & { - angleToLine: boolean; - extremityPlacement: string; - flipFirst: boolean; - placementTemplate: number[]; - positionArray: number[]; + angleToLine: boolean; + extremityPlacement: string; + flipFirst: boolean; + placementTemplate: number[]; + positionArray: number[]; }; export type CIMEffect = CIMObject & { - dashTemplate: number[]; - offset: number; + dashTemplate: number[]; + offset: number; }; export type SymbolLayer = CIMObject & { - capStyle: string; - characterIndex: number; - color: CIMColorType; - effects: CIMEffect[]; - enable: boolean; - fontFamilyName: string; - joinStyle: string; - lineSymbol: CIMSymbol; - markerPlacement: CIMMarkerPlacement; - markerGraphics: CIMSymbolReference[]; - rotateClockwise: boolean; - rotation: number; - separation: number; - size: number; - symbol: CIMSymbol; + capStyle: string; + characterIndex: number; + color: CIMColorType; + effects: CIMEffect[]; + enable: boolean; + fontFamilyName: string; + joinStyle: string; + lineSymbol: CIMSymbol; + markerPlacement: CIMMarkerPlacement; + markerGraphics: CIMSymbolReference[]; + rotateClockwise: boolean; + rotation: number; + separation: number; + size: number; + symbol: CIMSymbol; }; export type CIMSymbol = CIMObject & { - enabled: boolean; - symbolLayers?: SymbolLayer[]; + enabled: boolean; + symbolLayers?: SymbolLayer[]; }; diff --git a/src/esri/types/symbols/CIMTextSymbol.ts b/src/esri/types/symbols/CIMTextSymbol.ts index 715c3e1..97b696f 100644 --- a/src/esri/types/symbols/CIMTextSymbol.ts +++ b/src/esri/types/symbols/CIMTextSymbol.ts @@ -281,7 +281,7 @@ export type CIMTextSymbol = CIMSymbol & { * Gets or sets a value indicating whether or not the symbol should overprint in press printing. */ overprint?: boolean; -} +}; /** * Represents a callout. */ diff --git a/src/esri/types/symbols/index.ts b/src/esri/types/symbols/index.ts index 771b68c..17de9c5 100644 --- a/src/esri/types/symbols/index.ts +++ b/src/esri/types/symbols/index.ts @@ -1,3 +1,2 @@ - -export * from './CIMSymbol.ts'; -export * from './CIMTextSymbol.ts'; +export * from "./CIMSymbol.ts"; +export * from "./CIMTextSymbol.ts"; diff --git a/src/expressions.ts b/src/expressions.ts index 85fa38d..041c9c2 100644 --- a/src/expressions.ts +++ b/src/expressions.ts @@ -1,44 +1,56 @@ -import { LabelExpressionEngine } from './esri/types/index.ts'; +import { LabelExpressionEngine } from "./esri/types/index.ts"; import { CombinationFilter, ComparisonOperator, Filter, Fproperty, - GeoStylerNumberFunction -} from 'geostyler-style'; -import {WARNINGS} from './toGeostylerUtils.ts'; + GeoStylerNumberFunction, +} from "geostyler-style"; +import { WARNINGS } from "./toGeostylerUtils.ts"; -export const fieldToFProperty = (field: string, toLowerCase: boolean): Fproperty => { +export const fieldToFProperty = ( + field: string, + toLowerCase: boolean, +): Fproperty => { return { args: [toLowerCase ? field.toLowerCase() : field], - name: 'property', + name: "property", }; }; export const andFilter = (filters: Filter[]): CombinationFilter => { - return ['&&', ...filters]; + return ["&&", ...filters]; }; export const orFilter = (conditions: Filter[]): CombinationFilter => { - return ['||', ...conditions]; + return ["||", ...conditions]; }; -export const equalFilter = (name: string, val: string, toLowerCase: boolean): Filter => { - return getSimpleFilter('==', name, val, toLowerCase); +export const equalFilter = ( + name: string, + val: string, + toLowerCase: boolean, +): Filter => { + return getSimpleFilter("==", name, val, toLowerCase); }; export const getSimpleFilter = ( operator: ComparisonOperator, value1: string, value2: string, - toLowerCase=true + toLowerCase = true, ): Filter => { - return [operator, stringToParameter(value1, toLowerCase), stringToParameter(value2, toLowerCase)]; + return [ + operator, + stringToParameter(value1, toLowerCase), + stringToParameter(value2, toLowerCase), + ]; }; export const convertExpression = ( - rawExpression: string, engine: LabelExpressionEngine, - toLowerCase: boolean + rawExpression: string, + engine: LabelExpressionEngine, + toLowerCase: boolean, ): string => { let expression: string = rawExpression; if (engine === LabelExpressionEngine.Arcade) { @@ -47,56 +59,63 @@ export const convertExpression = ( if (toLowerCase) { expression = rawExpression.toLowerCase(); } - if (expression.includes('+') || expression.includes('&')) { - const tokens = expression.includes('+') ? expression.split('+') : expression.split('&'); + if (expression.includes("+") || expression.includes("&")) { + const tokens = expression.includes("+") + ? expression.split("+") + : expression.split("&"); const parsedExpression = tokens.map((token) => { token = token.trimStart().trimEnd(); - if (token.includes('[')) { + if (token.includes("[")) { return processPropertyName(token); } else { - const literal = token.replaceAll('"', ''); + const literal = token.replaceAll('"', ""); return replaceSpecialLiteral(literal); } }); - return parsedExpression.join(''); + return parsedExpression.join(""); } return processPropertyName(expression); }; -export const convertWhereClause = (clause: string, toLowerCase: boolean): Filter => { - clause = clause.replace('(', '').replace(')', ''); - if (clause.includes(' AND ')) { - const subexpressions = clause.split(' AND ').map(s => s.trim()); - return andFilter(subexpressions.map(s => convertWhereClause(s, toLowerCase))); +export const convertWhereClause = ( + clause: string, + toLowerCase: boolean, +): Filter => { + clause = clause.replace("(", "").replace(")", ""); + if (clause.includes(" AND ")) { + const subexpressions = clause.split(" AND ").map((s) => s.trim()); + return andFilter( + subexpressions.map((s) => convertWhereClause(s, toLowerCase)), + ); } - if (clause.includes('=')) { - const tokens = clause.split('=').map(t => t.trim()); - return getSimpleFilter('==', tokens[0], tokens[1], toLowerCase); + if (clause.includes("=")) { + const tokens = clause.split("=").map((t) => t.trim()); + return getSimpleFilter("==", tokens[0], tokens[1], toLowerCase); } - if (clause.includes('<>')) { - const tokens = clause.split('<>').map(t => t.trim()); - return getSimpleFilter('!=', tokens[0], tokens[1], toLowerCase); + if (clause.includes("<>")) { + const tokens = clause.split("<>").map((t) => t.trim()); + return getSimpleFilter("!=", tokens[0], tokens[1], toLowerCase); } - if (clause.includes('>')) { - const tokens = clause.split('>').map(t => t.trim()); - return getSimpleFilter('>', tokens[0], tokens[1], toLowerCase); + if (clause.includes(">")) { + const tokens = clause.split(">").map((t) => t.trim()); + return getSimpleFilter(">", tokens[0], tokens[1], toLowerCase); } - if (clause.toLowerCase().includes(' in ')) { - clause = clause.replace(' IN ', ' in '); - const tokens = clause.split(' in '); + if (clause.toLowerCase().includes(" in ")) { + clause = clause.replace(" IN ", " in "); + const tokens = clause.split(" in "); const attribute = tokens[0]; let values: string[] = []; - if (tokens[1].startsWith('() ')) { - values = tokens[1].substring(3).split(','); + if (tokens[1].startsWith("() ")) { + values = tokens[1].substring(3).split(","); } const subexpressions: Filter[] = []; - values.forEach(value => { + values.forEach((value) => { subexpressions.push( getSimpleFilter( - '==', + "==", `${stringToParameter(attribute, toLowerCase)}`, - `${stringToParameter(value, toLowerCase)}` - ) + `${stringToParameter(value, toLowerCase)}`, + ), ); }); if (values.length === 1) { @@ -108,50 +127,58 @@ export const convertWhereClause = (clause: string, toLowerCase: boolean): Filter } return accum; } - WARNINGS.push(`Clause skipped because it is not supported as filter: ${clause}}`); - return ['==', 0, 0]; + WARNINGS.push( + `Clause skipped because it is not supported as filter: ${clause}}`, + ); + return ["==", 0, 0]; }; export const processRotationExpression = ( expression: string, rotationType: string, - toLowerCase: boolean): GeoStylerNumberFunction | null => { - const field = expression.includes('$feature') ? convertArcadeExpression(expression) : processPropertyName(expression); + toLowerCase: boolean, +): GeoStylerNumberFunction | null => { + const field = expression.includes("$feature") + ? convertArcadeExpression(expression) + : processPropertyName(expression); const fProperty: Fproperty = fieldToFProperty(field, toLowerCase); - if (rotationType === 'Arithmetic') { - return { args: [fProperty, -1], name: 'mul' }; - } else if (rotationType === 'Geographic') { - return { args: [fProperty, 90], name: 'sub' }; + if (rotationType === "Arithmetic") { + return { args: [fProperty, -1], name: "mul" }; + } else if (rotationType === "Geographic") { + return { args: [fProperty, 90], name: "sub" }; } return null; }; const replaceSpecialLiteral = (literal: string): string => { - if (literal === 'vbnewline') { - return '/n'; + if (literal === "vbnewline") { + return "/n"; } return literal; }; const processPropertyName = (token: string): string => { - return token.replace('[', '{{').replace(']', '}}').trim(); + return token.replace("[", "{{").replace("]", "}}").trim(); }; const convertArcadeExpression = (expression: string): string => { - return expression.replace('$feature.', ''); + return expression.replace("$feature.", ""); }; -const stringToParameter = (s: string, toLowerCase: boolean): string|null => { +const stringToParameter = (s: string, toLowerCase: boolean): string | null => { s = s.trim(); - if ((s.startsWith('\'') && s.endsWith('\'')) || (s.startsWith('"') && s.endsWith('"'))) { + if ( + (s.startsWith("'") && s.endsWith("'")) || + (s.startsWith('"') && s.endsWith('"')) + ) { // Removes quote around and returns. - return s.substring(1).substring(0, s.length -2); + return s.substring(1).substring(0, s.length - 2); } // Lowercase if it's wanted and alphabetical only. if (toLowerCase && s.match(/^[A-Z]*$/i)) { s = s.toLowerCase(); } - if (s === '') { + if (s === "") { return null; } // Returns as is. diff --git a/src/index.spec.ts b/src/index.spec.ts index b149545..7fda954 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -1,10 +1,16 @@ -import { expect, it, describe, beforeAll } from 'vitest'; -import fs from 'fs'; -import { LyrxParser } from './index.ts'; -import {FillSymbolizer, MarkSymbolizer, ReadStyleResult, Rule, TextSymbolizer} from 'geostyler-style'; -import {CIMLayerDocument} from './esri/types'; - -describe('LyrxParser should parse ae_netzbetreiber.lyrx', () => { +import { expect, it, describe, beforeAll } from "vitest"; +import fs from "fs"; +import { LyrxParser } from "./index.ts"; +import { + FillSymbolizer, + MarkSymbolizer, + ReadStyleResult, + Rule, + TextSymbolizer, +} from "geostyler-style"; +import { CIMLayerDocument } from "./esri/types"; + +describe("LyrxParser should parse ae_netzbetreiber.lyrx", () => { let lyrx: CIMLayerDocument; let lyrxParser: LyrxParser; let geostylerStyle: ReadStyleResult; @@ -12,44 +18,46 @@ describe('LyrxParser should parse ae_netzbetreiber.lyrx', () => { beforeAll(async () => { lyrxParser = new LyrxParser(); lyrx = JSON.parse( - fs.readFileSync('./data/lyrx/ae_netzbetreiber_02.lyrx', 'utf8') + fs.readFileSync("./data/lyrx/ae_netzbetreiber_02.lyrx", "utf8"), ); geostylerStyle = await lyrxParser.readStyle(lyrx); }); - it('should create the geostyler style', async () => { + it("should create the geostyler style", async () => { expect(geostylerStyle.output!).toBeDefined(); }); - it('should have correct number of rules', () => { + it("should have correct number of rules", () => { expect(geostylerStyle.output!.rules.length).toEqual(118); }); - it('should set simple filter for rule AEW Energie AG', () => { + it("should set simple filter for rule AEW Energie AG", () => { const rule = geostylerStyle.output!.rules.find( - (x: Rule) => x.name === 'AEW Energie AG' + (x: Rule) => x.name === "AEW Energie AG", ); expect(rule?.filter).toBeDefined(); - const expectedFilter = ['==', 'anbieter', 'AEW Energie AG']; + const expectedFilter = ["==", "anbieter", "AEW Energie AG"]; expect(rule?.filter).toEqual(expectedFilter); }); - it('should set symbolizers for rule AEW Energie AG', () => { + it("should set symbolizers for rule AEW Energie AG", () => { const rule = geostylerStyle.output!.rules.find( - (x: Rule) => x.name === 'AEW Energie AG' + (x: Rule) => x.name === "AEW Energie AG", ); expect(rule).toBeDefined(); - if (!rule) {return;} + if (!rule) { + return; + } expect(rule.symbolizers).toBeDefined(); expect(rule.symbolizers.length).toEqual(1); const symbolizer = rule.symbolizers[0] as FillSymbolizer; - expect(symbolizer.kind).toEqual('Fill'); - expect(symbolizer.color).toEqual('#ffffbe'); + expect(symbolizer.kind).toEqual("Fill"); + expect(symbolizer.color).toEqual("#ffffbe"); expect(symbolizer.fillOpacity).toEqual(1); }); }); -describe('LyrxParser should parse feature-layer-polygon-simple-renderer.lyrx', () => { +describe("LyrxParser should parse feature-layer-polygon-simple-renderer.lyrx", () => { let lyrx: CIMLayerDocument; let lyrxParser: LyrxParser; let geostylerStyle: ReadStyleResult; @@ -58,33 +66,32 @@ describe('LyrxParser should parse feature-layer-polygon-simple-renderer.lyrx', ( lyrxParser = new LyrxParser(); lyrx = JSON.parse( fs.readFileSync( - './data/lyrx/feature-layer-polygon-simple-renderer.lyrx', - 'utf8' - ) + "./data/lyrx/feature-layer-polygon-simple-renderer.lyrx", + "utf8", + ), ); geostylerStyle = await lyrxParser.readStyle(lyrx); }); - - it('should set symbolizers', () => { - const rule = geostylerStyle.output!.rules.find( - (x: Rule) => x.name === '' - ); + it("should set symbolizers", () => { + const rule = geostylerStyle.output!.rules.find((x: Rule) => x.name === ""); expect(rule).toBeDefined(); - if (!rule) {return;} + if (!rule) { + return; + } expect(rule.symbolizers).toHaveLength(2); const symbolizer1 = rule.symbolizers[0] as FillSymbolizer; - expect(symbolizer1.kind).toEqual('Fill'); - expect(symbolizer1.color).toEqual('#d1cffc'); + expect(symbolizer1.kind).toEqual("Fill"); + expect(symbolizer1.color).toEqual("#d1cffc"); expect(symbolizer1.fillOpacity).toEqual(1); const symbolizer2 = rule.symbolizers[1] as FillSymbolizer; - expect(symbolizer2.kind).toEqual('Fill'); + expect(symbolizer2.kind).toEqual("Fill"); expect(symbolizer2.outlineWidth).toEqual(0.9333333333333332); expect(symbolizer2.outlineOpacity).toEqual(1); }); }); -describe('LyrxParser should parse feature-layer-point-graduated-colors-renderer.lyrx', () => { +describe("LyrxParser should parse feature-layer-point-graduated-colors-renderer.lyrx", () => { let lyrx: CIMLayerDocument; let lyrxParser: LyrxParser; let geostylerStyle: ReadStyleResult; @@ -93,72 +100,74 @@ describe('LyrxParser should parse feature-layer-point-graduated-colors-renderer. lyrxParser = new LyrxParser(); lyrx = JSON.parse( fs.readFileSync( - './data/lyrx/feature-layer-point-graduated-colors-renderer.lyrx', - 'utf8' - ) + "./data/lyrx/feature-layer-point-graduated-colors-renderer.lyrx", + "utf8", + ), ); geostylerStyle = await lyrxParser.readStyle(lyrx); }); - it('should have correct number of rules', () => { + it("should have correct number of rules", () => { expect(geostylerStyle.output!.rules.length).toEqual(5); }); - it('should set filters', () => { + it("should set filters", () => { const rule = geostylerStyle.output!.rules.find( - (x: Rule) => x.name === '6 - 35' + (x: Rule) => x.name === "6 - 35", ); expect(rule).toBeDefined(); - if (!rule) {return;} + if (!rule) { + return; + } expect(rule.filter).toBeDefined(); - const expectedFilter = ['<=', 'fragebogennr', 35]; + const expectedFilter = ["<=", "fragebogennr", 35]; expect(rule.filter).toEqual(expectedFilter); }); - it('should set symbolizers', () => { + it("should set symbolizers", () => { const rule = geostylerStyle.output!.rules.find( - (x: Rule) => x.name === '6 - 35' + (x: Rule) => x.name === "6 - 35", ); expect(rule).toBeDefined(); - if (!rule) {return;} + if (!rule) { + return; + } expect(rule.symbolizers).toHaveLength(1); const symbolizer = rule.symbolizers[0] as MarkSymbolizer; - expect(symbolizer.kind).toEqual('Mark'); - expect(symbolizer.wellKnownName).toEqual('circle'); + expect(symbolizer.kind).toEqual("Mark"); + expect(symbolizer.wellKnownName).toEqual("circle"); expect(symbolizer.opacity).toEqual(1); expect(symbolizer.fillOpacity).toEqual(1); - expect(symbolizer.color).toEqual('#f4f400'); + expect(symbolizer.color).toEqual("#f4f400"); expect(symbolizer.rotate).toEqual(0); expect(symbolizer.radius).toEqual(2.6666666666666665); - expect(symbolizer.strokeColor).toEqual('#000000'); + expect(symbolizer.strokeColor).toEqual("#000000"); expect(symbolizer.strokeWidth).toEqual(0.9333333333333332); expect(symbolizer.strokeOpacity).toEqual(1); }); }); -describe('LyrxParser should parse afu_gwn_02.lyrx', () => { +describe("LyrxParser should parse afu_gwn_02.lyrx", () => { let lyrx: CIMLayerDocument; let lyrxParser: LyrxParser; let geostylerStyle: ReadStyleResult; beforeAll(async () => { lyrxParser = new LyrxParser(); - lyrx = JSON.parse( - fs.readFileSync('./data/lyrx/afu_gwn_02.lyrx', 'utf8') - ); + lyrx = JSON.parse(fs.readFileSync("./data/lyrx/afu_gwn_02.lyrx", "utf8")); geostylerStyle = await lyrxParser.readStyle(lyrx); }); - it('should have parse label expression', () => { + it("should have parse label expression", () => { const rules = geostylerStyle.output!.rules; expect(rules.length).toEqual(6); const textSymbolizer = rules[5].symbolizers[0] as TextSymbolizer; - expect(textSymbolizer.kind).toEqual('Text'); - expect(textSymbolizer.label).toEqual('{{bew_nr}} / {{bew_foerde}} l/s'); + expect(textSymbolizer.kind).toEqual("Text"); + expect(textSymbolizer.label).toEqual("{{bew_nr}} / {{bew_foerde}} l/s"); }); }); -describe('LyrxParser should parse kai_blattpk100_01.lyrx', () => { +describe("LyrxParser should parse kai_blattpk100_01.lyrx", () => { let lyrx: CIMLayerDocument; let lyrxParser: LyrxParser; let geostylerStyle: ReadStyleResult; @@ -166,14 +175,14 @@ describe('LyrxParser should parse kai_blattpk100_01.lyrx', () => { beforeAll(async () => { lyrxParser = new LyrxParser(); lyrx = JSON.parse( - fs.readFileSync('./data/lyrx/kai_blattpk100_01.lyrx', 'utf8') + fs.readFileSync("./data/lyrx/kai_blattpk100_01.lyrx", "utf8"), ); geostylerStyle = await lyrxParser.readStyle(lyrx); }); - it('should have parse whereClause expression', () => { + it("should have parse whereClause expression", () => { const rules = geostylerStyle.output!.rules; expect(rules.length).toEqual(7); - expect(rules[6].filter).toEqual(['>', 'stand', '0']); + expect(rules[6].filter).toEqual([">", "stand", "0"]); }); }); diff --git a/src/index.ts b/src/index.ts index bd3f4c7..c972532 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,10 +3,10 @@ import { Style, StyleParser, UnsupportedProperties, - WriteStyleResult -} from 'geostyler-style'; -import { convert } from './toGeostyler.ts'; -import { CIMLayerDocument } from './esri/types/CIMLayerDocument.ts'; + WriteStyleResult, +} from "geostyler-style"; +import { convert } from "./toGeostyler.ts"; +import { CIMLayerDocument } from "./esri/types/CIMLayerDocument.ts"; /** * This parser can be used with the GeoStyler. @@ -17,8 +17,8 @@ import { CIMLayerDocument } from './esri/types/CIMLayerDocument.ts'; * @implements StyleParser */ export class LyrxParser implements StyleParser { - static title = 'ArcGIS Pro lyrx parser'; - title = 'ArcGIS Pro lyrx parser'; + static title = "ArcGIS Pro lyrx parser"; + title = "ArcGIS Pro lyrx parser"; unsupportedProperties: UnsupportedProperties = {}; diff --git a/src/processSymbolLayer.ts b/src/processSymbolLayer.ts index b538443..a254926 100644 --- a/src/processSymbolLayer.ts +++ b/src/processSymbolLayer.ts @@ -1,24 +1,25 @@ -import {Effect, Options} from './types.ts'; -import { toWKT } from './wktGeometries.ts'; -import { ESRI_SYMBOLS_FONT, OFFSET_FACTOR, ptToPx } from './constants.ts'; -import { processColor, processOpacity } from './processUtils.ts'; +import { Effect, Options } from "./types.ts"; +import { toWKT } from "./wktGeometries.ts"; +import { ESRI_SYMBOLS_FONT, OFFSET_FACTOR, ptToPx } from "./constants.ts"; +import { processColor, processOpacity } from "./processUtils.ts"; import { esriFontToStandardSymbols, extractFillColor, extractFillOpacity, extractStroke, - ptToPxProp, toHex, + ptToPxProp, + toHex, WARNINGS, -} from './toGeostylerUtils.ts'; -import { processSymbolReference } from './processSymbolReference.ts'; +} from "./toGeostylerUtils.ts"; +import { processSymbolReference } from "./processSymbolReference.ts"; import { FillSymbolizer, LineSymbolizer, MarkSymbolizer, Symbolizer, - WellKnownName -} from 'geostyler-style'; -import {CIMEffect, SymbolLayer} from './esri/types/symbols'; + WellKnownName, +} from "geostyler-style"; +import { CIMEffect, SymbolLayer } from "./esri/types/symbols"; // import { writeFileSync, existsSync, mkdirSync } from 'fs'; // import uuid from 'uuid'; // import { tmpdir } from 'os'; @@ -27,38 +28,41 @@ import {CIMEffect, SymbolLayer} from './esri/types/symbols'; export const processSymbolLayer = ( layer: SymbolLayer, symboltype: string, - options: Options + options: Options, ): Symbolizer | undefined => { let layerType: string = layer.type; switch (layerType) { - case 'CIMSolidStroke': + case "CIMSolidStroke": return processSymbolSolidStroke(layer, symboltype); - case 'CIMSolidFill': + case "CIMSolidFill": return processSymbolSolidFill(layer); - case 'CIMCharacterMarker': + case "CIMCharacterMarker": return processSymbolCharacterMarker(layer, options); - case 'CIMVectorMarker': + case "CIMVectorMarker": return processSymbolVectorMarker(layer); - case 'CIMHatchFill': + case "CIMHatchFill": return processSymbolHatchFill(layer); - case 'CIMPictureFill': - case 'CIMPictureMarker': + case "CIMPictureFill": + case "CIMPictureMarker": return processSymbolPicture(layer); default: return; } }; -const processSymbolSolidStroke = (layer: SymbolLayer, symboltype: string): Symbolizer => { +const processSymbolSolidStroke = ( + layer: SymbolLayer, + symboltype: string, +): Symbolizer => { const effects = extractEffect(layer); - if (symboltype === 'CIMPolygonSymbol') { + if (symboltype === "CIMPolygonSymbol") { const fillSymbolizer: FillSymbolizer = { - kind: 'Fill', + kind: "Fill", outlineColor: processColor(layer.color), outlineOpacity: processOpacity(layer.color), - outlineWidth: ptToPxProp(layer, 'width', 0), + outlineWidth: ptToPxProp(layer, "width", 0), }; - if ('dasharray' in effects) { + if ("dasharray" in effects) { fillSymbolizer.outlineDasharray = effects.dasharray; } return fillSymbolizer; @@ -66,30 +70,36 @@ const processSymbolSolidStroke = (layer: SymbolLayer, symboltype: string): Symbo const cap = layer.capStyle.toLowerCase(); const join = layer.joinStyle.toLowerCase(); const stroke: LineSymbolizer = { - kind: 'Line', + kind: "Line", color: processColor(layer.color), opacity: processOpacity(layer.color), - width: ptToPxProp(layer, 'width', 0), + width: ptToPxProp(layer, "width", 0), perpendicularOffset: 0, - cap: ['butt', 'round', 'square'].includes(cap) ? cap as ('butt' | 'round' | 'square'): undefined, - join: ['round', 'bevel', 'miter'].includes(join) ? join as ('round' | 'bevel' | 'miter') : undefined + cap: ["butt", "round", "square"].includes(cap) + ? (cap as "butt" | "round" | "square") + : undefined, + join: ["round", "bevel", "miter"].includes(join) + ? (join as "round" | "bevel" | "miter") + : undefined, }; - if ('dasharray' in effects) { + if ("dasharray" in effects) { stroke.dasharray = effects.dasharray; } - if ('offset' in effects) { + if ("offset" in effects) { stroke.perpendicularOffset = effects.offset; } return stroke; }; -const processSymbolSolidFill = (layer: SymbolLayer): FillSymbolizer | undefined => { +const processSymbolSolidFill = ( + layer: SymbolLayer, +): FillSymbolizer | undefined => { let color = layer.color; if (color === undefined) { return; } return { - kind: 'Fill', + kind: "Fill", opacity: processOpacity(color), color: processColor(color), fillOpacity: 1.0, @@ -98,13 +108,13 @@ const processSymbolSolidFill = (layer: SymbolLayer): FillSymbolizer | undefined const processSymbolCharacterMarker = ( layer: SymbolLayer, - options: Options + options: Options, ): MarkSymbolizer => { const replaceesri = !!options.replaceesri; const fontFamily = layer.fontFamilyName; const charindex = layer.characterIndex; const hexcode = toHex(charindex); - const size = ptToPxProp(layer, 'size', 12); + const size = ptToPxProp(layer, "size", 12); let name: WellKnownName; if (fontFamily === ESRI_SYMBOLS_FONT && replaceesri) { @@ -120,9 +130,9 @@ const processSymbolCharacterMarker = ( rotate *= -1; } - let fillColor = '#000000'; + let fillColor = "#000000"; let fillOpacity = 1; - let strokeColor = '#000000'; + let strokeColor = "#000000"; let strokeWidth = 0; let strokeOpacity = 0; const symbolLayers = layer.symbol.symbolLayers; @@ -140,7 +150,7 @@ const processSymbolCharacterMarker = ( strokeOpacity: strokeOpacity, strokeWidth: strokeWidth, rotate: rotate, - kind: 'Mark', + kind: "Mark", color: fillColor, wellKnownName: name, radius: size / 2, @@ -149,15 +159,15 @@ const processSymbolCharacterMarker = ( const processSymbolVectorMarker = (layer: SymbolLayer): MarkSymbolizer => { if (layer.size) { - layer.size = ptToPxProp(layer, 'size', 3); + layer.size = ptToPxProp(layer, "size", 3); } // Default values - let fillColor = '#ff0000'; - let strokeColor = '#000000'; + let fillColor = "#ff0000"; + let strokeColor = "#000000"; let strokeWidth = 1.0; let markerSize = 10; let strokeOpacity = 1; - let wellKnownName: WellKnownName = 'circle'; + let wellKnownName: WellKnownName = "circle"; let maxX: number | null = null; let maxY: number | null = null; @@ -170,33 +180,36 @@ const processSymbolVectorMarker = (layer: SymbolLayer): MarkSymbolizer => { if (markerGraphic.symbol && markerGraphic.symbol.symbolLayers) { symbol = processSymbolReference(markerGraphic, {})[0] as MarkSymbolizer; const subLayers = markerGraphic.symbol.symbolLayers.filter( - (sublayer: SymbolLayer) => sublayer.enable + (sublayer: SymbolLayer) => sublayer.enable, ); fillColor = extractFillColor(subLayers); [strokeColor, strokeWidth, strokeOpacity] = extractStroke(subLayers); const layerSize = layer.size !== undefined ? layer.size : 10; - markerSize = typeof symbol.radius === 'number' ? symbol.radius : layerSize; - if (markerGraphic.symbol.type === 'CIMPointSymbol') { + markerSize = + typeof symbol.radius === "number" ? symbol.radius : layerSize; + if (markerGraphic.symbol.type === "CIMPointSymbol") { wellKnownName = symbol.wellKnownName ?? wellKnownName; } else if ( - ['CIMLineSymbol', 'CIMPolygonSymbol'].includes(markerGraphic.symbol.type) + ["CIMLineSymbol", "CIMPolygonSymbol"].includes( + markerGraphic.symbol.type, + ) ) { const geometry = markerGraphic.geometry; if (geometry) { const shape = toWKT(geometry); wellKnownName = shape.wellKnownName; - maxX = ptToPxProp(shape, 'maxX', 0); - maxY = ptToPxProp(shape, 'maxY', 0); + maxX = ptToPxProp(shape, "maxX", 0); + maxY = ptToPxProp(shape, "maxY", 0); } } } } // TODO marker should support outlineDasharray ? - const marker: MarkSymbolizer= { + const marker: MarkSymbolizer = { opacity: 1, rotate: 0, - kind: 'Mark', + kind: "Mark", color: fillColor, wellKnownName: wellKnownName, radius: markerSize / 2, @@ -222,13 +235,13 @@ const processSymbolVectorMarker = (layer: SymbolLayer): MarkSymbolizer => { // Conversion of dash arrays is made on a case-by-case basis if (JSON.stringify(markerPlacement) === JSON.stringify([12, 3])) { // @ts-ignore FIXME see issue #63 - marker.outlineDasharray = '4 0 4 7'; + marker.outlineDasharray = "4 0 4 7"; marker.radius = 3; // @ts-ignore FIXME see issue #63 marker.perpendicularOffset = -3.5; } else if (JSON.stringify(markerPlacement) === JSON.stringify([15])) { // @ts-ignore FIXME see issue #63 - marker.outlineDasharray = '0 5 9 1'; + marker.outlineDasharray = "0 5 9 1"; marker.radius = 5; } @@ -238,7 +251,7 @@ const processSymbolVectorMarker = (layer: SymbolLayer): MarkSymbolizer => { const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { const rotation = layer.rotation || 0; const symbolLayers = layer.lineSymbol.symbolLayers; - let color = '#000000'; + let color = "#000000"; let width = 0; let opacity = 0; if (symbolLayers) { @@ -249,7 +262,7 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { let wellKnowName = hatchMarkerForAngle(rotation); if (rotation % 45) { WARNINGS.push( - 'Rotation value different than a multiple of 45° is not possible. The nearest value is taken instead.' + "Rotation value different than a multiple of 45° is not possible. The nearest value is taken instead.", ); } @@ -261,7 +274,7 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { : rawSeparation * 2; const markSymbolizer: MarkSymbolizer = { - kind: 'Mark', + kind: "Mark", color: color, wellKnownName: wellKnowName, radius: separation, @@ -272,7 +285,7 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { }; const fillSymbolizer: FillSymbolizer = { - kind: 'Fill', + kind: "Fill", opacity: 1.0, graphicFill: markSymbolizer, }; @@ -282,7 +295,7 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { } let effects = extractEffect(symbolLayers[0]); - if ('dasharray' in effects) { + if ("dasharray" in effects) { // @ts-ignore FIXME see issue #63 fillSymbolizer.graphicFill!.outlineDasharray = effects.dasharray; @@ -295,16 +308,26 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer => { let negativeMargin = ((neededSize - separation) / 2) * -1; if (wellKnowName === getStraightHatchMarker()[0]) { // @ts-ignore FIXME see issue #64 - fillSymbolizer.graphicFillMargin = [negativeMargin, 0, negativeMargin, 0]; + fillSymbolizer.graphicFillMargin = [ + negativeMargin, + 0, + negativeMargin, + 0, + ]; } else { // @ts-ignore FIXME see issue #64 - fillSymbolizer.graphicFillMargin = [0, negativeMargin, 0, negativeMargin]; + fillSymbolizer.graphicFillMargin = [ + 0, + negativeMargin, + 0, + negativeMargin, + ]; } } else { // In case of tilted lines, the trick with the margin is not possible without cropping the pattern. neededSize = separation; WARNINGS.push( - 'Unable to keep the original size of CIMHatchFill for line with rotation' + "Unable to keep the original size of CIMHatchFill for line with rotation", ); } markSymbolizer.radius = neededSize; @@ -334,21 +357,21 @@ const processSymbolPicture = (layer: SymbolLayer): Symbolizer => { // } // } - let size = ptToPxProp(layer, 'height', ptToPxProp(layer, 'size', 0)); + let size = ptToPxProp(layer, "height", ptToPxProp(layer, "size", 0)); return { opacity: 1.0, rotate: 0.0, - kind: 'Icon', + kind: "Icon", color: undefined, // image: url, - image: 'http://FIXME', + image: "http://FIXME", size: size, }; }; const extractEffect = (layer: SymbolLayer): Effect => { let effects: Effect = {}; - if ('effects' in layer) { + if ("effects" in layer) { layer.effects.forEach((effect: CIMEffect) => { effects = { ...effects, ...processEffect(effect) }; }); @@ -361,7 +384,7 @@ const processEffect = (effect: CIMEffect): Effect => { return Math.ceil(ptToPx(v)); }; - if (effect.type === 'CIMGeometricEffectDashes') { + if (effect.type === "CIMGeometricEffectDashes") { let dasharrayValues = effect.dashTemplate?.map(ptToPxAndCeil) || []; if (dasharrayValues.length > 1) { return { @@ -369,7 +392,7 @@ const processEffect = (effect: CIMEffect): Effect => { dasharray: dasharrayValues, // TODO was a string, can be simplified now }; } - } else if (effect.type === 'CIMGeometricEffectOffset') { + } else if (effect.type === "CIMGeometricEffectOffset") { return { offset: ptToPxAndCeil(effect.offset || 0) * -1, }; @@ -378,11 +401,11 @@ const processEffect = (effect: CIMEffect): Effect => { }; const getStraightHatchMarker = (): WellKnownName[] => { - return ['shape://horline', 'shape://vertline']; + return ["shape://horline", "shape://vertline"]; }; const getTiltedHatchMarker = (): WellKnownName[] => { - return ['shape://slash', 'shape://backslash']; + return ["shape://slash", "shape://backslash"]; }; const hatchMarkerForAngle = (angle: number): WellKnownName => { @@ -398,9 +421,11 @@ const hatchMarkerForAngle = (angle: number): WellKnownName => { ][quadrant]; }; -const extractOffset = (symbolLayer: SymbolLayer): undefined | [number, number] => { - let offsetX = ptToPxProp(symbolLayer, 'offsetX', 0) * OFFSET_FACTOR; - let offsetY = ptToPxProp(symbolLayer, 'offsetY', 0) * OFFSET_FACTOR * -1; +const extractOffset = ( + symbolLayer: SymbolLayer, +): undefined | [number, number] => { + let offsetX = ptToPxProp(symbolLayer, "offsetX", 0) * OFFSET_FACTOR; + let offsetY = ptToPxProp(symbolLayer, "offsetY", 0) * OFFSET_FACTOR * -1; if (offsetX === 0 && offsetY !== 0) { return undefined; diff --git a/src/processSymbolReference.ts b/src/processSymbolReference.ts index 248fcc9..dc596b6 100644 --- a/src/processSymbolReference.ts +++ b/src/processSymbolReference.ts @@ -1,33 +1,33 @@ -import { - ESRI_SYMBOLS_FONT, - POLYGON_FILL_RESIZE_FACTOR, -} from './constants.ts'; +import { ESRI_SYMBOLS_FONT, POLYGON_FILL_RESIZE_FACTOR } from "./constants.ts"; import { esriFontToStandardSymbols, extractFillColor, extractFillOpacity, extractStroke, - ptToPxProp, toHex, -} from './toGeostylerUtils.ts'; -import { - Options, -} from './types.ts'; -import { processSymbolLayer } from './processSymbolLayer.ts'; + ptToPxProp, + toHex, +} from "./toGeostylerUtils.ts"; +import { Options } from "./types.ts"; +import { processSymbolLayer } from "./processSymbolLayer.ts"; import { FillSymbolizer, LineSymbolizer, MarkSymbolizer, PointSymbolizer, Symbolizer, - WellKnownName -} from 'geostyler-style'; -import {CIMSymbolReference} from './esri/types/labeling/CIMSymbolReference.ts'; -import {CIMMarkerPlacement, CIMSymbol, SymbolLayer} from './esri/types/symbols'; -import {fieldToFProperty} from './expressions.ts'; + WellKnownName, +} from "geostyler-style"; +import { CIMSymbolReference } from "./esri/types/labeling/CIMSymbolReference.ts"; +import { + CIMMarkerPlacement, + CIMSymbol, + SymbolLayer, +} from "./esri/types/symbols"; +import { fieldToFProperty } from "./expressions.ts"; export const processSymbolReference = ( symbolref: CIMSymbolReference, - options: Options + options: Options, ): Symbolizer[] => { const symbol = symbolref.symbol; const symbolizers: Symbolizer[] = []; @@ -46,11 +46,11 @@ export const processSymbolReference = ( if (!symbolizer) { return; } - if ([ - 'CIMVectorMarker', - 'CIMPictureFill', - 'CIMCharacterMarker' - ].includes(layer.type)) { + if ( + ["CIMVectorMarker", "CIMPictureFill", "CIMCharacterMarker"].includes( + layer.type, + ) + ) { processSymbolLayerIfCharacterMarker(symbol, layer, symbolizer, options); } symbolizers.push(symbolizer); @@ -62,24 +62,27 @@ const processSymbolLayerIfCharacterMarker = ( symbol: CIMSymbol, layer: SymbolLayer, symbolizer: Symbolizer, - options: Options + options: Options, ): Symbolizer[] => { const symbolizers: Symbolizer[] = []; - if (symbol.type === 'CIMPolygonSymbol') { + if (symbol.type === "CIMPolygonSymbol") { const markerPlacement = layer.markerPlacement || {}; - const polygonSymbolizer = formatPolygonSymbolizer(symbolizer as MarkSymbolizer, markerPlacement); + const polygonSymbolizer = formatPolygonSymbolizer( + symbolizer as MarkSymbolizer, + markerPlacement, + ); if (polygonSymbolizer) { symbolizers.push(polygonSymbolizer); } return symbolizers; } - if (symbol.type === 'CIMLineSymbol') { - if (layer.type === 'CIMCharacterMarker') { + if (symbol.type === "CIMLineSymbol") { + if (layer.type === "CIMCharacterMarker") { if (orientedMarkerAtStartOfLine(layer.markerPlacement)) { const startSymbolizer = processOrientedMarkerAtEndOfLine( layer, - 'start', - options + "start", + options, ); if (startSymbolizer) { symbolizers.push(startSymbolizer); @@ -88,8 +91,8 @@ const processSymbolLayerIfCharacterMarker = ( if (orientedMarkerAtEndOfLine(layer.markerPlacement)) { const endSymbolizer = processOrientedMarkerAtEndOfLine( layer, - 'end', - options + "end", + options, ); if (endSymbolizer) { symbolizers.push(endSymbolizer); @@ -107,41 +110,40 @@ const processSymbolLayerIfCharacterMarker = ( const formatLineSymbolizer = (symbolizer: PointSymbolizer): LineSymbolizer => { return { - kind: 'Line', + kind: "Line", opacity: 1.0, perpendicularOffset: 0.0, graphicStroke: symbolizer, // @ts-ignore FIXME see issue #65 - graphicStrokeInterval: ptToPxProp(symbolizer, 'size', 0) * 2, + graphicStrokeInterval: ptToPxProp(symbolizer, "size", 0) * 2, graphicStrokeOffset: 0.0, - }; }; const formatPolygonSymbolizer = ( symbolizer: MarkSymbolizer, - markerPlacement: CIMMarkerPlacement + markerPlacement: CIMMarkerPlacement, ): FillSymbolizer | LineSymbolizer | null => { const markerPlacementType = markerPlacement.type; - if (markerPlacementType === 'CIMMarkerPlacementInsidePolygon') { + if (markerPlacementType === "CIMMarkerPlacementInsidePolygon") { const margin = processMarkerPlacementInsidePolygon( symbolizer, - markerPlacement + markerPlacement, ); return { - kind: 'Fill', + kind: "Fill", opacity: 1.0, graphicFill: symbolizer, // @ts-ignore FIXME see issue #64 graphicFillMargin: margin, }; } - if (markerPlacementType === 'CIMMarkerPlacementAlongLineSameSize') { + if (markerPlacementType === "CIMMarkerPlacementAlongLineSameSize") { return { - kind: 'Line', + kind: "Line", opacity: 1.0, - width: ptToPxProp(symbolizer, 'size', 10), - perpendicularOffset: ptToPxProp(symbolizer, 'perpendicularOffset', 0.0), + width: ptToPxProp(symbolizer, "size", 10), + perpendicularOffset: ptToPxProp(symbolizer, "perpendicularOffset", 0.0), graphicStroke: symbolizer, }; } @@ -151,17 +153,17 @@ const formatPolygonSymbolizer = ( const processOrientedMarkerAtEndOfLine = ( layer: SymbolLayer, orientedMarker: string, - options: Options + options: Options, ): MarkSymbolizer | undefined => { // let markerPositionFnc: string; // let markerRotationFnc: string; let rotation: number; - if (orientedMarker === 'start') { + if (orientedMarker === "start") { // markerPositionFnc = MarkerPlacementPosition.START; // markerRotationFnc = MarkerPlacementAngle.START; rotation = layer?.rotation ?? 180; - } else if (orientedMarker === 'end') { + } else if (orientedMarker === "end") { // markerPositionFnc = MarkerPlacementPosition.END; // markerRotationFnc = MarkerPlacementAngle.END; rotation = layer?.rotation ?? 0; @@ -194,14 +196,14 @@ const processOrientedMarkerAtEndOfLine = ( fillOpacity = extractFillOpacity(symbolLayers); [strokeColor, strokeWidth, strokeOpacity] = extractStroke(symbolLayers); } catch (error) { - fillColor = '#000000'; + fillColor = "#000000"; fillOpacity = 1.0; strokeOpacity = 0.0; - strokeColor = '#000000'; + strokeColor = "#000000"; strokeWidth = 0.0; } - const fProperty = fieldToFProperty('shape', true); + const fProperty = fieldToFProperty("shape", true); return { opacity: 1.0, fillOpacity: fillOpacity, @@ -210,27 +212,27 @@ const processOrientedMarkerAtEndOfLine = ( strokeWidth: strokeWidth, // FIXME see issue #66 use markerRotationFnc ? Previous code was: // rotate: ['Add', [markerRotationFnc, ['PropertyName', 'shape']], rotation], - rotate: { args: [fProperty, rotation], name: 'add' }, - kind: 'Mark', + rotate: { args: [fProperty, rotation], name: "add" }, + kind: "Mark", color: fillColor, wellKnownName: name, - radius: ptToPxProp(layer, 'size', 10), + radius: ptToPxProp(layer, "size", 10), // @ts-ignore FIXME see issue #66 - geometry: [markerPositionFnc, ['PropertyName', 'shape']], + geometry: [markerPositionFnc, ["PropertyName", "shape"]], // @ts-ignore FIXME see issue #66 - inclusion: 'mapOnly', + inclusion: "mapOnly", }; }; const processMarkerPlacementInsidePolygon = ( symbolizer: MarkSymbolizer, - markerPlacement: CIMMarkerPlacement + markerPlacement: CIMMarkerPlacement, ): number[] => { - const resizeFactor = symbolizer?.wellKnownName?.startsWith('wkt://POLYGON') + const resizeFactor = symbolizer?.wellKnownName?.startsWith("wkt://POLYGON") ? 1 : POLYGON_FILL_RESIZE_FACTOR; - const radius = typeof symbolizer.radius === 'number' ? symbolizer.radius : 0; + const radius = typeof symbolizer.radius === "number" ? symbolizer.radius : 0; const size = Math.round(radius * resizeFactor) || 1; symbolizer.radius = size; @@ -245,8 +247,8 @@ const processMarkerPlacementInsidePolygon = ( maxY = Math.floor(symMaxY * resizeFactor) || 1; } - let stepX = ptToPxProp(markerPlacement, 'stepX', 0); - let stepY = ptToPxProp(markerPlacement, 'stepY', 0); + let stepX = ptToPxProp(markerPlacement, "stepX", 0); + let stepY = ptToPxProp(markerPlacement, "stepY", 0); if (stepX < maxX) { stepX += maxX * 2; @@ -256,8 +258,8 @@ const processMarkerPlacementInsidePolygon = ( stepY += maxY * 2; } - const offsetX = ptToPxProp(markerPlacement, 'offsetX', 0); - const offsetY = ptToPxProp(markerPlacement, 'offsetY', 0); + const offsetX = ptToPxProp(markerPlacement, "offsetX", 0); + const offsetY = ptToPxProp(markerPlacement, "offsetY", 0); const right = Math.round(stepX / 2 - maxX - offsetX); const left = Math.round(stepX / 2 - maxX + offsetX); @@ -267,18 +269,20 @@ const processMarkerPlacementInsidePolygon = ( return [top, right, bottom, left]; }; -const orientedMarkerAtStartOfLine = (markerPlacement: CIMMarkerPlacement): boolean => { +const orientedMarkerAtStartOfLine = ( + markerPlacement: CIMMarkerPlacement, +): boolean => { if (markerPlacement?.angleToLine) { if ( - markerPlacement.type === 'CIMMarkerPlacementAtRatioPositions' && + markerPlacement.type === "CIMMarkerPlacementAtRatioPositions" && markerPlacement.positionArray[0] === 0 && markerPlacement.flipFirst ) { return true; - } else if (markerPlacement.type === 'CIMMarkerPlacementAtExtremities') { + } else if (markerPlacement.type === "CIMMarkerPlacementAtExtremities") { return ( - markerPlacement.extremityPlacement === 'Both' || - markerPlacement.extremityPlacement === 'JustBegin' + markerPlacement.extremityPlacement === "Both" || + markerPlacement.extremityPlacement === "JustBegin" ); } } @@ -286,18 +290,18 @@ const orientedMarkerAtStartOfLine = (markerPlacement: CIMMarkerPlacement): boole }; const orientedMarkerAtEndOfLine = ( - markerPlacement: CIMMarkerPlacement + markerPlacement: CIMMarkerPlacement, ): boolean => { if (markerPlacement?.angleToLine) { if ( - markerPlacement.type === 'CIMMarkerPlacementAtRatioPositions' && + markerPlacement.type === "CIMMarkerPlacementAtRatioPositions" && markerPlacement.positionArray[0] === 1 ) { return true; - } else if (markerPlacement.type === 'CIMMarkerPlacementAtExtremities') { + } else if (markerPlacement.type === "CIMMarkerPlacementAtExtremities") { return ( - markerPlacement.extremityPlacement === 'Both' || - markerPlacement.extremityPlacement === 'JustEnd' + markerPlacement.extremityPlacement === "Both" || + markerPlacement.extremityPlacement === "JustEnd" ); } } diff --git a/src/processUtils.ts b/src/processUtils.ts index 918c3b5..67439d0 100644 --- a/src/processUtils.ts +++ b/src/processUtils.ts @@ -1,4 +1,4 @@ -import {CIMColor, CIMColorType} from './esri/types/symbols'; +import { CIMColor, CIMColorType } from "./esri/types/symbols"; export const processOpacity = (color: CIMColor | null): number => { if (color === null || !color.values) { @@ -9,26 +9,26 @@ export const processOpacity = (color: CIMColor | null): number => { export const processColor = (color: CIMColorType): string => { if (color === null) { - return '#000000'; + return "#000000"; } let values = color.values ?? [0, 0, 0]; - if (color.type === 'CIMRGBColor') { + if (color.type === "CIMRGBColor") { return rgbaToHex(values); - } else if (color.type === 'CIMCMYKColor') { + } else if (color.type === "CIMCMYKColor") { return rgbaToHex(cmyk2Rgb(values)); - } else if (color.type === 'CIMHSVColor') { + } else if (color.type === "CIMHSVColor") { return rgbaToHex(hsv2rgb(values)); - } else if (color.type === 'CIMGrayColor') { + } else if (color.type === "CIMGrayColor") { return rgbaToHex(hsv2rgb(values)); } else { - return '#000000'; + return "#000000"; } }; const rgbaToHex = (rgba: number[]): string => { // eslint-disable-next-line no-bitwise - const value = (1<<24)+(rgba[0]<<16)+(rgba[1]<<8)+rgba[2]; - return (`#${value.toString(16).slice(1).split('.')[0]}`); + const value = (1 << 24) + (rgba[0] << 16) + (rgba[1] << 8) + rgba[2]; + return `#${value.toString(16).slice(1).split(".")[0]}`; }; const cmyk2Rgb = (cmykArray: number[]): [number, number, number] => { @@ -55,7 +55,7 @@ const hsv2rgb = (hsvArray: number[]): [number, number, number] => { } let i = Math.floor(h * 6.0); - let f = (h * 6.0) - i; + let f = h * 6.0 - i; let p = 255 * (v * (1.0 - s)); let q = 255 * (v * (1.0 - s * f)); let t = 255 * (v * (1.0 - s * (1.0 - f))); @@ -64,11 +64,23 @@ const hsv2rgb = (hsvArray: number[]): [number, number, number] => { i %= 6; - if (i === 0) {return [v, t, p];} - if (i === 1) {return [q, v, p];} - if (i === 2) {return [p, v, t];} - if (i === 3) {return [p, q, v];} - if (i === 4) {return [t, p, v];} - if (i === 5) {return [v, p, q];} + if (i === 0) { + return [v, t, p]; + } + if (i === 1) { + return [q, v, p]; + } + if (i === 2) { + return [p, v, t]; + } + if (i === 3) { + return [p, q, v]; + } + if (i === 4) { + return [t, p, v]; + } + if (i === 5) { + return [v, p, q]; + } return [-1, -1, -1]; }; diff --git a/src/toGeostyler.ts b/src/toGeostyler.ts index 8973d64..e0ea229 100644 --- a/src/toGeostyler.ts +++ b/src/toGeostyler.ts @@ -1,55 +1,68 @@ -import {Filter, GeoStylerNumberFunction, Rule, Style, Symbolizer} from 'geostyler-style'; +import { + Filter, + GeoStylerNumberFunction, + Rule, + Style, + Symbolizer, +} from "geostyler-style"; import { andFilter, convertExpression, - convertWhereClause, equalFilter, + convertWhereClause, + equalFilter, fieldToFProperty, orFilter, processRotationExpression, -} from './expressions.ts'; -import {Options} from './types.ts'; -import {extractFillColor, extractFontWeight, ptToPxProp, WARNINGS,} from './toGeostylerUtils.ts'; -import {processSymbolReference} from './processSymbolReference.ts'; +} from "./expressions.ts"; +import { Options } from "./types.ts"; +import { + extractFillColor, + extractFontWeight, + ptToPxProp, + WARNINGS, +} from "./toGeostylerUtils.ts"; +import { processSymbolReference } from "./processSymbolReference.ts"; import { CIMFeatureLayer, CIMLabelClass, CIMLayerDefinition, - CIMLayerDocument, CIMRasterLayer, CIMRenderer, CIMUniqueValueRenderer, Group, + CIMLayerDocument, + CIMRasterLayer, + CIMRenderer, + CIMUniqueValueRenderer, + Group, LabelExpressionEngine, LabelFeatureType, -} from './esri/types/index.ts'; -import {CIMTextSymbol} from './esri/types/symbols/index.ts'; -import {CIMBreaksRenderer} from './esri/types/renderers/CIMBreaksRenderer.ts'; -import {CIMSimpleRenderer} from './esri/types/renderers/CIMSimpleRenderer.ts'; -import {CIMMaplexRotationProperties} from './esri/types/labeling/CIMMaplexRotationProperties.ts'; +} from "./esri/types/index.ts"; +import { CIMTextSymbol } from "./esri/types/symbols/index.ts"; +import { CIMBreaksRenderer } from "./esri/types/renderers/CIMBreaksRenderer.ts"; +import { CIMSimpleRenderer } from "./esri/types/renderers/CIMSimpleRenderer.ts"; +import { CIMMaplexRotationProperties } from "./esri/types/labeling/CIMMaplexRotationProperties.ts"; const usedIcons: string[] = []; export const convert = ( layerDocument: CIMLayerDocument, - options: Options = {} + options: Options = {}, ): [Style, string[], string[]] => { const geoStyler = processLayer(layerDocument?.layerDefinitions?.[0], options); return [geoStyler, usedIcons, WARNINGS]; }; -const processLayer = ( - layer: CIMLayerDefinition, - options: Options -): Style => { +const processLayer = (layer: CIMLayerDefinition, options: Options): Style => { const style: Style = { name: layer.name, rules: [], }; options = { - ...{ toLowerCase: true, replaceesri: false}, + ...{ toLowerCase: true, replaceesri: false }, ...options, }; - if (layer.type === 'CIMFeatureLayer') { + if (layer.type === "CIMFeatureLayer") { style.rules = processFeatureLayer(layer as CIMFeatureLayer, options); - } else if (layer.type === 'CIMRasterLayer') { + } else if (layer.type === "CIMRasterLayer") { style.rules = processRasterLayer(layer as CIMRasterLayer); } @@ -58,7 +71,7 @@ const processLayer = ( const processFeatureLayer = ( layer: CIMFeatureLayer, - options: Options = {} + options: Options = {}, ): Rule[] => { const toLowerCase = !!options.toLowerCase; const renderer = layer.renderer; @@ -86,23 +99,23 @@ const processFeatureLayer = ( const processRenderer = (renderer: CIMRenderer, options: Options): Rule[] => { const rules: Rule[] = []; // CIMSimpleRenderer - if (renderer.type === 'CIMSimpleRenderer') { + if (renderer.type === "CIMSimpleRenderer") { rules.push(processSimpleRenderer(renderer as CIMSimpleRenderer, options)); return rules; } // CIMUniqueValueRenderer - if (renderer.type === 'CIMUniqueValueRenderer') { + if (renderer.type === "CIMUniqueValueRenderer") { const uvRenderer = renderer as CIMUniqueValueRenderer; if (uvRenderer.groups) { uvRenderer.groups.forEach((group) => { rules.push( - ...processUniqueValueGroup(uvRenderer.fields!, group, options) + ...processUniqueValueGroup(uvRenderer.fields!, group, options), ); }); } else if (uvRenderer.defaultSymbol) { // This is really a simple renderer const rule: Rule = { - name: '', + name: "", symbolizers: processSymbolReference(uvRenderer.defaultSymbol, options), }; rules.push(rule); @@ -110,9 +123,13 @@ const processRenderer = (renderer: CIMRenderer, options: Options): Rule[] => { return rules; } // CIMClassBreaksRenderer - if (renderer.type === 'CIMClassBreaksRenderer') { + if (renderer.type === "CIMClassBreaksRenderer") { const breaksRenderer = renderer as CIMBreaksRenderer; - if (['GraduatedColor', 'GraduatedSymbol'].includes(breaksRenderer.classBreakType)) { + if ( + ["GraduatedColor", "GraduatedSymbol"].includes( + breaksRenderer.classBreakType, + ) + ) { rules.push(...processClassBreaksRenderer(breaksRenderer, options)); return rules; } @@ -122,25 +139,31 @@ const processRenderer = (renderer: CIMRenderer, options: Options): Rule[] => { }; const processRasterLayer = (_layer: CIMRasterLayer): [] => { - WARNINGS.push('CIMRasterLayer are not supported yet.'); + WARNINGS.push("CIMRasterLayer are not supported yet."); // const rules = [{ name: layer.name, symbolizers: [rasterSymbolizer(layer)] }]; // geostyler.rules = rules; return []; }; -const assignRotation = (rotation: GeoStylerNumberFunction, symbolizers: Symbolizer[]) => { - symbolizers.filter(symbolizer => - symbolizer.kind === 'Text' || - symbolizer.kind === 'Icon' || - symbolizer.kind === 'Mark' - ).forEach(symbolizer => { - symbolizer.rotate = rotation; - }); +const assignRotation = ( + rotation: GeoStylerNumberFunction, + symbolizers: Symbolizer[], +) => { + symbolizers + .filter( + (symbolizer) => + symbolizer.kind === "Text" || + symbolizer.kind === "Icon" || + symbolizer.kind === "Mark", + ) + .forEach((symbolizer) => { + symbolizer.rotate = rotation; + }); }; const processClassBreaksRenderer = ( renderer: CIMBreaksRenderer, - options: Options = {} + options: Options = {}, ): Rule[] => { const rules: Rule[] = []; const symbolsAscending: Symbolizer[][] = []; @@ -157,24 +180,12 @@ const processClassBreaksRenderer = ( let filter: Filter; if (lastbound !== null) { filter = [ - '&&', - [ - '>', - toLowerCase ? field.toLowerCase() : field, - lastbound, - ], - [ - '<=', - toLowerCase ? field.toLowerCase() : field, - upperbound, - ], + "&&", + [">", toLowerCase ? field.toLowerCase() : field, lastbound], + ["<=", toLowerCase ? field.toLowerCase() : field, upperbound], ]; } else { - filter = [ - '<=', - toLowerCase ? field.toLowerCase() : field, - upperbound, - ]; + filter = ["<=", toLowerCase ? field.toLowerCase() : field, upperbound]; } lastbound = upperbound; @@ -185,7 +196,7 @@ const processClassBreaksRenderer = ( const ruleDef: Rule = { filter, symbolizers, - name: rBreak.label || 'classbreak', + name: rBreak.label || "classbreak", }; symbolsAscending.push(symbolizers); @@ -207,28 +218,29 @@ const processLabelClass = ( toLowerCase: boolean, ): Rule => { // TODO ConvertTextSymbol: - if (labelClass.textSymbol?.symbol?.type !== 'CIMTextSymbol') { - return { name: '', symbolizers: [] }; + if (labelClass.textSymbol?.symbol?.type !== "CIMTextSymbol") { + return { name: "", symbolizers: [] }; } const textSymbol = labelClass.textSymbol?.symbol as CIMTextSymbol; const expression = convertExpression( - labelClass?.expression ?? '', + labelClass?.expression ?? "", labelClass.expressionEngine ?? LabelExpressionEngine.Arcade, - toLowerCase + toLowerCase, ); - const fontFamily = textSymbol?.fontFamilyName || 'Arial'; - const fontSize = ptToPxProp(textSymbol, 'height', 12, true); + const fontFamily = textSymbol?.fontFamilyName || "Arial"; + const fontSize = ptToPxProp(textSymbol, "height", 12, true); // @ts-ignore FIXME see issue #68 const color = extractFillColor(textSymbol?.symbol?.symbolLayers ?? []); const fontWeight = extractFontWeight(textSymbol); const rotationProps = - labelClass.maplexLabelPlacementProperties?.rotationProperties || {} as CIMMaplexRotationProperties; + labelClass.maplexLabelPlacementProperties?.rotationProperties || + ({} as CIMMaplexRotationProperties); const rotationField = rotationProps.rotationField; const symbolizer: Symbolizer = { - kind: 'Text', - anchor: 'right', + kind: "Text", + anchor: "right", rotate: 0.0, color: color, font: [fontFamily], @@ -244,8 +256,8 @@ const processLabelClass = ( const maplexPlacementType = maplexProperties?.featureType; const maplexPrimaryOffset = ptToPxProp( maplexProperties ?? {}, - 'primaryOffset', - 0 + "primaryOffset", + 0, ); const maplexPointPlacementMethod = maplexProperties?.pointPlacementMethod; @@ -253,18 +265,18 @@ const processLabelClass = ( stdPlacementType === LabelFeatureType.Line && maplexPlacementType === LabelFeatureType.Line ) { - const primaryOffset = ptToPxProp(textSymbol, 'primaryOffset', 0); + const primaryOffset = ptToPxProp(textSymbol, "primaryOffset", 0); // @ts-ignore FIXME see issue #63 symbolizer.perpendicularOffset = primaryOffset + fontSize; } else if ( maplexPlacementType === LabelFeatureType.Point && - maplexPointPlacementMethod === 'AroundPoint' + maplexPointPlacementMethod === "AroundPoint" ) { const offset = maplexPrimaryOffset + fontSize / 2; symbolizer.offset = [offset, offset]; } else if ( stdPlacementType === LabelFeatureType.Point && - stdPointPlacementType === 'AroundPoint' + stdPointPlacementType === "AroundPoint" ) { const offset = maplexPrimaryOffset + fontSize / 2; symbolizer.offset = [offset, offset]; @@ -274,15 +286,16 @@ const processLabelClass = ( if (rotationField) { const fProperty = fieldToFProperty(rotationField, toLowerCase); - symbolizer.rotate = { args: [fProperty, -1], name: 'mul' }; + symbolizer.rotate = { args: [fProperty, -1], name: "mul" }; } else { symbolizer.rotate = 0; } - const haloSize = ptToPxProp(textSymbol, 'haloSize', 0); + const haloSize = ptToPxProp(textSymbol, "haloSize", 0); if (haloSize && textSymbol.haloSymbol) { - // @ts-ignore FIXME see issue #68 - const haloColor = extractFillColor(textSymbol?.haloSymbol?.symbolLayers ?? [] + const haloColor = extractFillColor( + // @ts-ignore FIXME see issue #68 + textSymbol?.haloSymbol?.symbolLayers ?? [], ); Object.assign(symbolizer, { haloColor: haloColor, @@ -296,13 +309,13 @@ const processLabelClass = ( labelClass.maplexLabelPlacementProperties?.thinDuplicateLabels || (maplexPlacementType === LabelFeatureType.Polygon && labelClass.standardLabelPlacementProperties?.numLabelsOption === - 'OneLabelPerName'); + "OneLabelPerName"); - const rule: Rule = { name: '', symbolizers: [symbolizer] }; + const rule: Rule = { name: "", symbolizers: [symbolizer] }; const scaleDenominator = processScaleDenominator( labelClass.minimumScale, - labelClass.maximumScale + labelClass.maximumScale, ); if (scaleDenominator) { rule.scaleDenominator = scaleDenominator; @@ -315,9 +328,12 @@ const processLabelClass = ( return rule; }; -const processSimpleRenderer = (renderer: CIMSimpleRenderer, options: Options): Rule => { +const processSimpleRenderer = ( + renderer: CIMSimpleRenderer, + options: Options, +): Rule => { return { - name: renderer.label || '', + name: renderer.label || "", symbolizers: processSymbolReference(renderer.symbol, options), }; }; @@ -325,33 +341,36 @@ const processSimpleRenderer = (renderer: CIMSimpleRenderer, options: Options): R const processUniqueValueGroup = ( fields: string[], group: Group, - options: Options + options: Options, ): Rule[] => { const toLowerCase = options.toLowerCase || false; const rules: Rule[] = []; group.classes = group.classes || []; group.classes.forEach((oneClass) => { - const name = oneClass.label || 'label'; + const name = oneClass.label || "label"; const values = oneClass.values; const conditions: Filter[] = []; values - .filter((value) => 'fieldValues' in value) + .filter((value) => "fieldValues" in value) .forEach((value) => { const fieldValues = value.fieldValues; let condition = equalFilter(fields[0], fieldValues[0], toLowerCase); for (const [fieldValue, fieldName] of fieldValues .slice(1) .map((fv: unknown, idx: number) => [fv, fields[idx + 1]])) { - condition = andFilter([condition, equalFilter(`${fieldName}`, `${fieldValue}`, toLowerCase)]); + condition = andFilter([ + condition, + equalFilter(`${fieldName}`, `${fieldValue}`, toLowerCase), + ]); } conditions.push(condition); }); - let ruleFilter: Filter | null = null; if (conditions.length) { - ruleFilter = conditions.length === 1 ? conditions[0] : orFilter(conditions); + ruleFilter = + conditions.length === 1 ? conditions[0] : orFilter(conditions); const rule: Rule = { name, filter: ruleFilter, @@ -359,7 +378,7 @@ const processUniqueValueGroup = ( }; const scaleDenominator = processScaleDenominator( oneClass.symbol.minScale, - oneClass.symbol.maxScale + oneClass.symbol.maxScale, ); if (scaleDenominator) { rule.scaleDenominator = scaleDenominator; @@ -370,14 +389,14 @@ const processUniqueValueGroup = ( alternateSymbols.forEach((symbolRef) => { const altRule: Rule = { name, - symbolizers: processSymbolReference(symbolRef, options) + symbolizers: processSymbolReference(symbolRef, options), }; if (ruleFilter) { altRule.filter = ruleFilter; } const scaleDenominator = processScaleDenominator( symbolRef.minScale, - symbolRef.maxScale + symbolRef.maxScale, ); if (scaleDenominator) { altRule.scaleDenominator = scaleDenominator; @@ -391,11 +410,11 @@ const processUniqueValueGroup = ( const getSymbolRotationFromVisualVariables = ( renderer: CIMRenderer | null, - toLowerCase: boolean + toLowerCase: boolean, ): GeoStylerNumberFunction | null => { const visualVariables = renderer?.visualVariables ?? []; - visualVariables.find(visualVariable => { - if (visualVariable.type !== 'CIMRotationVisualVariable') { + visualVariables.find((visualVariable) => { + if (visualVariable.type !== "CIMRotationVisualVariable") { return false; } const expression = @@ -409,7 +428,7 @@ const getSymbolRotationFromVisualVariables = ( const processScaleDenominator = ( minimumScale?: number, - maximumScale?: number + maximumScale?: number, ): { [key: string]: number } | null => { if (minimumScale === undefined && maximumScale === undefined) { return null; diff --git a/src/toGeostylerUtils.ts b/src/toGeostylerUtils.ts index 419e31d..5ca8932 100644 --- a/src/toGeostylerUtils.ts +++ b/src/toGeostylerUtils.ts @@ -1,7 +1,7 @@ -import {ptToPx} from './constants.ts'; -import {processColor, processOpacity} from './processUtils.ts'; -import {CIMTextSymbol, SymbolLayer} from './esri/types/symbols'; -import {WellKnownName} from 'geostyler-style'; +import { ptToPx } from "./constants.ts"; +import { processColor, processOpacity } from "./processUtils.ts"; +import { CIMTextSymbol, SymbolLayer } from "./esri/types/symbols"; +import { WellKnownName } from "geostyler-style"; export const WARNINGS: string[] = []; @@ -11,25 +11,25 @@ export const toHex = (value: number): string => { export const esriFontToStandardSymbols = (charIndex: number): WellKnownName => { const mapping: { [index: number]: WellKnownName } = { - 33: 'circle', - 34: 'square', - 35: 'triangle', - 40: 'circle', - 41: 'square', - 42: 'triangle', - 94: 'star', - 95: 'star', - 203: 'cross', - 204: 'cross', + 33: "circle", + 34: "square", + 35: "triangle", + 40: "circle", + 41: "square", + 42: "triangle", + 94: "star", + 95: "star", + 203: "cross", + 204: "cross", }; if (mapping.hasOwnProperty(charIndex)) { return mapping[charIndex]; } else { WARNINGS.push( - `Unsupported symbol from ESRI font (character index ${charIndex}) replaced by default marker` + `Unsupported symbol from ESRI font (character index ${charIndex}) replaced by default marker`, ); - return 'circle'; + return "circle"; } }; @@ -37,9 +37,9 @@ export const ptToPxProp = ( obj: unknown, prop: string, defaultValue: number, - asFloat: boolean = true + asFloat: boolean = true, ): number => { - if (!(obj !== null && typeof obj === 'object' && obj.hasOwnProperty(prop))) { + if (!(obj !== null && typeof obj === "object" && obj.hasOwnProperty(prop))) { return defaultValue; } const validObj = obj as Record; @@ -52,29 +52,29 @@ export const ptToPxProp = ( }; export const extractStroke = ( - symbolLayers: SymbolLayer[] + symbolLayers: SymbolLayer[], ): [string, number, number] => { for (let sl of symbolLayers) { - if (sl.type === 'CIMSolidStroke') { - let color = processColor(sl.color ?? ''); - let width = ptToPxProp(sl, 'width', 0); - let opacity = processOpacity(sl.color ?? ''); + if (sl.type === "CIMSolidStroke") { + let color = processColor(sl.color ?? ""); + let width = ptToPxProp(sl, "width", 0); + let opacity = processOpacity(sl.color ?? ""); return [color, width, opacity]; } } - return ['#000000', 0, 0]; + return ["#000000", 0, 0]; }; export const extractFillColor = (symbolLayers: SymbolLayer[]): string => { - let color: string = '#ffffff'; - symbolLayers.some(sl => { + let color: string = "#ffffff"; + symbolLayers.some((sl) => { if (!sl.type) { return false; } - if (sl.type === 'CIMSolidFill') { - color = processColor(sl.color ?? ''); + if (sl.type === "CIMSolidFill") { + color = processColor(sl.color ?? ""); return true; - } else if (sl.type === 'CIMCharacterMarker') { + } else if (sl.type === "CIMCharacterMarker") { if (sl.symbol.symbolLayers) { color = extractFillColor(sl.symbol.symbolLayers); return true; @@ -86,13 +86,15 @@ export const extractFillColor = (symbolLayers: SymbolLayer[]): string => { }; export const extractFillOpacity = (symbolLayers: SymbolLayer[]): number => { - const symbolLayer = symbolLayers.find(sl => sl.type === 'CIMSolidFill'); + const symbolLayer = symbolLayers.find((sl) => sl.type === "CIMSolidFill"); if (symbolLayer) { return processOpacity(symbolLayer.color); } return 1.0; }; -export const extractFontWeight = (textSymbol: CIMTextSymbol): ('bold'|'normal') => { - return textSymbol.fontStyleName === 'Bold' ? 'bold' : 'normal'; +export const extractFontWeight = ( + textSymbol: CIMTextSymbol, +): "bold" | "normal" => { + return textSymbol.fontStyleName === "Bold" ? "bold" : "normal"; }; diff --git a/src/types.ts b/src/types.ts index d210946..495bfc5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,10 +1,10 @@ export interface Options { - [key: string]: unknown; - toLowerCase?: boolean; + [key: string]: unknown; + toLowerCase?: boolean; } export interface Effect { - dasharrayValues?: number[]; - dasharray?: number[]; - offset?: number; + dasharrayValues?: number[]; + dasharray?: number[]; + offset?: number; } diff --git a/src/wktGeometries.ts b/src/wktGeometries.ts index 4c8de1f..40dde36 100644 --- a/src/wktGeometries.ts +++ b/src/wktGeometries.ts @@ -1,30 +1,42 @@ -import {WellKnownName} from 'geostyler-style'; -import {Geometry} from './esri/types'; +import { WellKnownName } from "geostyler-style"; +import { Geometry } from "./esri/types"; -export const toWKT = (geometry: Geometry): { wellKnownName: WellKnownName; maxX?: number; maxY?: number } => { - const defaultMarker = {wellKnownName: 'circle' as WellKnownName}; +export const toWKT = ( + geometry: Geometry, +): { wellKnownName: WellKnownName; maxX?: number; maxY?: number } => { + const defaultMarker = { wellKnownName: "circle" as WellKnownName }; if (geometry.rings) { let [rings] = geometry.rings; rings = heightNormalized(rings); - let coordinates = rings.map(j => j.join(' ')).join(', '); + let coordinates = rings.map((j) => j.join(" ")).join(", "); return { wellKnownName: `wkt://POLYGON((${coordinates}))` as WellKnownName, - maxX: Math.max(...rings.map(coord => coord[0])), - maxY: Math.max(...rings.map(coord => coord[1])), + maxX: Math.max(...rings.map((coord) => coord[0])), + maxY: Math.max(...rings.map((coord) => coord[1])), }; } const path = geometry?.paths?.[0]; - if (path && path[0][0] === 2 && path[0][1] === 0 && path[1][0] -2 && path[1][1] === 0) { - return {wellKnownName: 'wkt://MULTILINESTRING((0 2, 0 0))' as WellKnownName}; + if ( + path && + path[0][0] === 2 && + path[0][1] === 0 && + path[1][0] - 2 && + path[1][1] === 0 + ) { + return { + wellKnownName: "wkt://MULTILINESTRING((0 2, 0 0))" as WellKnownName, + }; } if (geometry.curveRings) { const [curveRing] = geometry.curveRings; const startPoint = curveRing[0]; const curve = curveRing[1]?.a || curveRing[1]?.c; - if (!curve) {return defaultMarker;} + if (!curve) { + return defaultMarker; + } const endPoint = curve[0]; const centerPoint = curve[1]; if (endPoint !== startPoint) { @@ -32,7 +44,7 @@ export const toWKT = (geometry: Geometry): { wellKnownName: WellKnownName; maxX? } const radius = distanceBetweenPoints(startPoint as number[], centerPoint); return { - wellKnownName: 'circle' as WellKnownName, + wellKnownName: "circle" as WellKnownName, maxX: radius, maxY: radius, }; @@ -42,8 +54,10 @@ export const toWKT = (geometry: Geometry): { wellKnownName: WellKnownName; maxX? }; const heightNormalized = (coords: number[][]): number[][] => { - const height = Math.max(...coords.map(coord => coord[1])) - Math.min(...coords.map(coord => coord[1])); - return coords.map(coord => [coord[0] / height, coord[1] / height]); + const height = + Math.max(...coords.map((coord) => coord[1])) - + Math.min(...coords.map((coord) => coord[1])); + return coords.map((coord) => [coord[0] / height, coord[1] / height]); }; const distanceBetweenPoints = (a: number[], b: number[]): number => {