diff --git a/.gitignore b/.gitignore index 1b977a25..7b92c6ec 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ /build /browser +# history +/.history + # misc .DS_Store .env.local diff --git a/src/SldParser.spec.ts b/src/SldParser.spec.ts new file mode 100644 index 00000000..b1643017 --- /dev/null +++ b/src/SldParser.spec.ts @@ -0,0 +1,54 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint camelcase: 0 */ + +import * as fs from 'fs'; +import SldStyleParser from './SldStyleParser'; +import { expect, it, describe } from 'vitest'; + +import point_simplepoint from '../data/styles/point_simplepoint'; + +describe('SldStyleParser implements StyleParser (reading from one version and writing to another version)', () => { + it('can read and write a SLD PointSymbolizer (from 1.0.0 version to 1.1.0 version)', async () => { + const styleParser = new SldStyleParser({sldVersion: '1.1.0'}); + + const sld = fs.readFileSync('./data/slds/1.0/point_simplepoint.sld', 'utf8'); + const { output: geoStylerStyle } = await styleParser.readStyle(sld); + expect(geoStylerStyle).toBeDefined(); + expect(geoStylerStyle).toEqual(point_simplepoint); + + // writing + const { + output: sldString, + errors + } = await styleParser.writeStyle(geoStylerStyle!); + expect(sldString).toBeDefined(); + expect(errors).toBeUndefined(); + + // As string comparison between two XML-Strings is awkward and nonsens + // we read it again and compare the json input with the parser output + const { output: readStyle } = await styleParser.readStyle(sldString!); + expect(readStyle).toEqual(point_simplepoint); + }); + it('can read and write a SLD PointSymbolizer (from 1.1.0 version to 1.0.0 version)', async () => { + const styleParser = new SldStyleParser({sldVersion: '1.0.0'}); + + const sld = fs.readFileSync('./data/slds/1.1/point_simplepoint.sld', 'utf8'); + const { output: geoStylerStyle } = await styleParser.readStyle(sld); + expect(geoStylerStyle).toBeDefined(); + expect(geoStylerStyle).toEqual(point_simplepoint); + + // writing + const { + output: sldString, + errors + } = await styleParser.writeStyle(geoStylerStyle!); + expect(sldString).toBeDefined(); + expect(errors).toBeUndefined(); + + // As string comparison between two XML-Strings is awkward and nonsens + // we read it again and compare the json input with the parser output + const { output: readStyle } = await styleParser.readStyle(sldString!); + expect(readStyle).toEqual(point_simplepoint); + }); +}); + diff --git a/src/SldStyleParser.ts b/src/SldStyleParser.ts index 3cbb74cd..d6187aa3 100644 --- a/src/SldStyleParser.ts +++ b/src/SldStyleParser.ts @@ -56,11 +56,14 @@ import { numberExpression } from './Util/SldUtil'; -export type SldVersion = '1.0.0' | '1.1.0'; +const SLD_VERSIONS = ['1.0.0', '1.1.0'] as const; + +export type SldVersion = (typeof SLD_VERSIONS)[number]; export type ConstructorParams = { numericFilterFields?: string[]; boolFilterFields?: string[]; + /* optional for reading style (it will be guessed from sld style) and mandatory for writing */ sldVersion?: SldVersion; symbolizerUnits?: string; parserOptions?: X2jOptionsOptional; @@ -271,7 +274,7 @@ export class SldStyleParser implements StyleParser { /** * String indicating the SLD version to use. 1.1.0 will make use of - * Symbology Encoding. Default ist to use SLD 1.0.0 + * Symbology Encoding. */ private _sldVersion: SldVersion = '1.0.0'; @@ -291,6 +294,28 @@ export class SldStyleParser implements StyleParser { this._sldVersion = sldVersion; } + + /** + * String indicating the SLD version used in reading mode + */ + private _readingSldVersion: SldVersion = '1.0.0'; + + /** + * Getter for _readingSldVersion + * @return + */ + get readingSldVersion(): SldVersion { + return this._readingSldVersion; + } + + /** + * Setter for _readingSldVersion + * @param sldVersion The _readingSldVersion value to set + */ + set readingSldVersion(sldVersion: SldVersion) { + this._readingSldVersion = sldVersion; + } + /** * Used to add a `uom` attribute to the symbolizer tag. Can be one of * `metre`, `foot` or `pixel`. Defaults to pixel. @@ -325,6 +350,13 @@ export class SldStyleParser implements StyleParser { return new Promise((resolve) => { try { const sldObject = this.parser.parse(sldString); + + const version = getAttribute(sldObject[0], 'version'); + if (!SLD_VERSIONS.includes(version)) { + throw new Error(`SLD version must be ${SLD_VERSIONS.toString()}`); + } + this._readingSldVersion = version; + const geoStylerStyle: Style = this.sldObjectToGeoStylerStyle(sldObject); resolve({ output: geoStylerStyle @@ -601,14 +633,14 @@ export class SldStyleParser implements StyleParser { const lineSymbolizer: GsLineSymbolizer = { kind: 'Line' }; - const strokeEl = get(sldSymbolizer, 'Stroke'); - const color = getParameterValue(strokeEl, 'stroke', this.sldVersion); - const width = getParameterValue(strokeEl, 'stroke-width', this.sldVersion); - const opacity = getParameterValue(strokeEl, 'stroke-opacity', this.sldVersion); - const lineJoin = getParameterValue(strokeEl, 'stroke-linejoin', this.sldVersion); - const lineCap = getParameterValue(strokeEl, 'stroke-linecap', this.sldVersion); - const dashArray = getParameterValue(strokeEl, 'stroke-dasharray', this.sldVersion); - const dashOffset = getParameterValue(strokeEl, 'stroke-dashoffset', this.sldVersion); + const strokeEl = get(sldSymbolizer, 'Stroke', this.readingSldVersion); + const color = getParameterValue(strokeEl, 'stroke', this.readingSldVersion); + const width = getParameterValue(strokeEl, 'stroke-width', this.readingSldVersion); + const opacity = getParameterValue(strokeEl, 'stroke-opacity', this.readingSldVersion); + const lineJoin = getParameterValue(strokeEl, 'stroke-linejoin', this.readingSldVersion); + const lineCap = getParameterValue(strokeEl, 'stroke-linecap', this.readingSldVersion); + const dashArray = getParameterValue(strokeEl, 'stroke-dasharray', this.readingSldVersion); + const dashOffset = getParameterValue(strokeEl, 'stroke-dashoffset', this.readingSldVersion); if (!isNil(color)) { lineSymbolizer.color = color; @@ -673,15 +705,15 @@ export class SldStyleParser implements StyleParser { const haloEl = get(sldSymbolizer, 'Halo'); const haloFillEl = get(haloEl, 'Fill'); - const color = getParameterValue(fillEl, 'fill', this.sldVersion); - const opacity = getParameterValue(fillEl, 'fill-opacity', this.sldVersion); + const color = getParameterValue(fillEl, 'fill', this.readingSldVersion); + const opacity = getParameterValue(fillEl, 'fill-opacity', this.readingSldVersion); - const fontFamily = getParameterValue(fontEl, 'font-family', this.sldVersion); - const fontStyle = getParameterValue(fontEl, 'font-style', this.sldVersion); - const fontSize = getParameterValue(fontEl, 'font-size', this.sldVersion); - const fontWeight = getParameterValue(fontEl, 'font-weight', this.sldVersion); + const fontFamily = getParameterValue(fontEl, 'font-family', this.readingSldVersion); + const fontStyle = getParameterValue(fontEl, 'font-style', this.readingSldVersion); + const fontSize = getParameterValue(fontEl, 'font-size', this.readingSldVersion); + const fontWeight = getParameterValue(fontEl, 'font-weight', this.readingSldVersion); - const haloColor = getParameterValue(haloFillEl, 'fill', this.sldVersion); + const haloColor = getParameterValue(haloFillEl, 'fill', this.readingSldVersion); if (!isNil(labelEl)) { textSymbolizer.label = this.getTextSymbolizerLabelFromSldSymbolizer(labelEl); @@ -694,7 +726,7 @@ export class SldStyleParser implements StyleParser { if (!isNil(haloRadius)) { textSymbolizer.haloWidth = numberExpression(haloRadius); } - const haloOpacity = getParameterValue(haloFillEl, 'fill-opacity', this.sldVersion); + const haloOpacity = getParameterValue(haloFillEl, 'fill-opacity', this.readingSldVersion); if (!isNil(haloOpacity)) { textSymbolizer.haloOpacity = numberExpression(haloOpacity); } @@ -815,16 +847,16 @@ export class SldStyleParser implements StyleParser { const strokeEl = get(sldSymbolizer, 'Stroke'); const fillEl = get(sldSymbolizer, 'Fill'); - const fillOpacity = getParameterValue(fillEl, 'fill-opacity', this.sldVersion); - const color = getParameterValue(fillEl, 'fill', this.sldVersion); + const fillOpacity = getParameterValue(fillEl, 'fill-opacity', this.readingSldVersion); + const color = getParameterValue(fillEl, 'fill', this.readingSldVersion); - const outlineColor = getParameterValue(strokeEl, 'stroke', this.sldVersion); - const outlineWidth = getParameterValue(strokeEl, 'stroke-width', this.sldVersion); - const outlineOpacity = getParameterValue(strokeEl, 'stroke-opacity', this.sldVersion); - const outlineDashArray = getParameterValue(strokeEl, 'stroke-dasharray', this.sldVersion); - const outlineCap = getParameterValue(strokeEl, 'stroke-linecap', this.sldVersion); - const outlineJoin = getParameterValue(strokeEl, 'stroke-linejoin', this.sldVersion); - // const outlineDashOffset = getParameterValue(strokeEl, 'stroke-dashoffset', this.sldVersion); + const outlineColor = getParameterValue(strokeEl, 'stroke', this.readingSldVersion); + const outlineWidth = getParameterValue(strokeEl, 'stroke-width', this.readingSldVersion); + const outlineOpacity = getParameterValue(strokeEl, 'stroke-opacity', this.readingSldVersion); + const outlineDashArray = getParameterValue(strokeEl, 'stroke-dasharray', this.readingSldVersion); + const outlineCap = getParameterValue(strokeEl, 'stroke-linecap', this.readingSldVersion); + const outlineJoin = getParameterValue(strokeEl, 'stroke-linejoin', this.readingSldVersion); + // const outlineDashOffset = getParameterValue(strokeEl, 'stroke-dashoffset', this.readingSldVersion); const graphicFill = get(sldSymbolizer, 'Fill.GraphicFill'); if (!isNil(graphicFill)) { @@ -916,8 +948,8 @@ export class SldStyleParser implements StyleParser { const opacity = get(sldSymbolizer, 'Graphic.Opacity.#text'); const size = get(sldSymbolizer, 'Graphic.Size.#text'); const rotation = get(sldSymbolizer, 'Graphic.Rotation.#text'); - const fillOpacity = getParameterValue(fillEl, 'fill-opacity', this.sldVersion); - const color = getParameterValue(fillEl, 'fill', this.sldVersion); + const fillOpacity = getParameterValue(fillEl, 'fill-opacity', this.readingSldVersion); + const color = getParameterValue(fillEl, 'fill', this.readingSldVersion); const displacement = get(sldSymbolizer, 'Graphic.Displacement'); const markSymbolizer: GsMarkSymbolizer = { @@ -976,15 +1008,15 @@ export class SldStyleParser implements StyleParser { throw new Error('MarkSymbolizer cannot be parsed. Unsupported WellKnownName.'); } - const strokeColor = getParameterValue(strokeEl, 'stroke', this.sldVersion); + const strokeColor = getParameterValue(strokeEl, 'stroke', this.readingSldVersion); if (!isNil(strokeColor)) { markSymbolizer.strokeColor = strokeColor; } - const strokeWidth = getParameterValue(strokeEl, 'stroke-width', this.sldVersion); + const strokeWidth = getParameterValue(strokeEl, 'stroke-width', this.readingSldVersion); if (!isNil(strokeWidth)) { markSymbolizer.strokeWidth = numberExpression(strokeWidth); } - const strokeOpacity = getParameterValue(strokeEl, 'stroke-opacity', this.sldVersion); + const strokeOpacity = getParameterValue(strokeEl, 'stroke-opacity', this.readingSldVersion); if (!isNil(strokeOpacity)) { markSymbolizer.strokeOpacity = numberExpression(strokeOpacity); } diff --git a/src/SldStyleParser.v1.0.spec.ts b/src/SldStyleParser.v1.0.spec.ts index 19d13c13..576eb990 100644 --- a/src/SldStyleParser.v1.0.spec.ts +++ b/src/SldStyleParser.v1.0.spec.ts @@ -51,7 +51,7 @@ it('SldStyleParser is defined', () => { expect(SldStyleParser).toBeDefined(); }); -describe('SldStyleParser implements StyleParser', () => { +describe('SldStyleParser implements StyleParser (reading)', () => { let styleParser: SldStyleParser; beforeEach(() => { @@ -361,6 +361,14 @@ describe('SldStyleParser implements StyleParser', () => { }); }); }); +}); + +describe('SldStyleParser implements StyleParser (writing)', () => { + let styleParser: SldStyleParser; + + beforeEach(() => { + styleParser = new SldStyleParser(); + }); describe('#writeStyle', () => { it('is defined', () => { diff --git a/src/SldStyleParser.v1.1.spec.ts b/src/SldStyleParser.v1.1.spec.ts index f9333a70..b213a492 100644 --- a/src/SldStyleParser.v1.1.spec.ts +++ b/src/SldStyleParser.v1.1.spec.ts @@ -52,13 +52,11 @@ it('SldStyleParser is defined', () => { expect(SldStyleParser).toBeDefined(); }); -describe('SldStyleParser with Symbology Encoding implements StyleParser', () => { +describe('SldStyleParser with Symbology Encoding implements StyleParser (reading)', () => { let styleParser: SldStyleParser; beforeEach(() => { - styleParser = new SldStyleParser({ - sldVersion: '1.1.0' - }); + styleParser = new SldStyleParser(); }); describe('#readStyle', () => { @@ -370,11 +368,20 @@ describe('SldStyleParser with Symbology Encoding implements StyleParser', () => }); }); }); +}); + +describe('SldStyleParser with Symbology Encoding implements StyleParser (writing)', () => { + let styleParser: SldStyleParser; + + beforeEach(() => { + styleParser = new SldStyleParser({sldVersion: '1.1.0'}); + }); describe('#writeStyle', () => { it('is defined', () => { expect(styleParser.writeStyle).toBeDefined(); }); + it('can write a SLD 1.1 PointSymbolizer', async () => { const { output: sldString } = await styleParser.writeStyle(point_simplepoint); expect(sldString).toBeDefined();