Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add geostyler style as a format #416

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 71 additions & 84 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
readdirSync
} from 'fs';
import minimist from 'minimist';
import { StyleParser } from 'geostyler-style';
import { StyleParser, ReadStyleResult, WriteStyleResult } from 'geostyler-style';
import ora, { Ora } from 'ora';
import {
logHelp,
Expand Down Expand Up @@ -48,33 +48,26 @@ const getParserFromFormat = (inputString: string): StyleParser | undefined => {
case 'qgis':
case 'qml':
return new QGISParser();
default:
case 'geostyler':
return undefined;
default:
throw new Error(`Unrecognized format: ${inputString}`)
}
};

const getParserFromFilename = (fileName: string): StyleParser | undefined => {
const getFormatFromFilename = (fileName: string): string | undefined => {
if (!fileName) {
return undefined;
}
const fileEnding = fileName.split('.')[1];
let fileEnding = fileName.split('.').pop();
if (!fileEnding) {
return undefined;
}
switch (fileEnding.toLowerCase()) {
case 'lyrx':
return new LyrxParser();
case 'mapbox':
return new MapboxParser();
case 'map':
return new MapfileParser();
case 'sld':
return new SLDParser();
case 'qml':
return new QGISParser();
default:
return undefined;
fileEnding = fileEnding.toLowerCase();
if (['lyrx', 'mapbox', 'map', 'sld', 'qml', 'geostyler'].includes(fileEnding)) {
return fileEnding;
}
return undefined;
};

const getExtensionFromFormat = (format: string): string => {
Expand Down Expand Up @@ -156,75 +149,61 @@ function collectPaths(basePath: string, isFile: boolean): string[] {
}
}

function handleResult(result: ReadStyleResult | WriteStyleResult, parser: StyleParser, stage: 'Source' | 'Target') {
const { output, errors, warnings, unsupportedProperties } = result;
if (errors && errors.length > 0) {
throw errors;
}
if (warnings) {
warnings.map(console.warn);
}
if (unsupportedProperties) {
console.log(`${stage} parser ${parser.title} does not support the following properties:`);
console.log(unsupportedProperties);
}
return output;
}

async function writeFile(
sourceFile: string, sourceParser: StyleParser,
sourceFile: string, sourceParser: StyleParser | undefined,
targetFile: string, targetParser: StyleParser | undefined,
oraIndicator: Ora
) {
if (targetParser instanceof LyrxParser) {
throw new Error('LyrxParser is not supported as target parser.');
}
if (targetParser instanceof MapfileParser) {
throw new Error('MapfileParser is not supported as target parser.');
}

let inputFileData = await promises.readFile(sourceFile, 'utf-8');
const indicator = oraIndicator; // for linter.

// LyrxParser expects a JSON object as input
if (sourceParser instanceof LyrxParser) {
// If no sourceParser is set, just parse it as JSON - it should already be in geostyler format.
// LyrxParser expects a JSON object as input, so we need to parse it as an extra step.
if (!sourceParser || sourceParser instanceof LyrxParser) {
inputFileData = JSON.parse(inputFileData);
}

try {
indicator.text = `Reading from ${sourceFile}`;
const {
errors: readErrors,
warnings: readWarnings,
unsupportedProperties: readUnsupportedProperties,
output: readOutput
} = await sourceParser.readStyle(inputFileData);
if (readErrors && readErrors.length > 0) {
throw readErrors;
}
if (readWarnings) {
readWarnings.map(console.warn);
}
if (readUnsupportedProperties) {
console.log(`Source parser ${sourceParser.title} does not support the following properties:`);
console.log(readUnsupportedProperties);
}
if (readOutput) {
let output;
indicator.text = `Writing to ${targetFile}`;
if (targetParser) {
if (targetParser instanceof LyrxParser) {
throw new Error('LyrxParser is not supported as target parser.');
}
if (targetParser instanceof MapfileParser) {
throw new Error('MapfileParser is not supported as target parser.');
}

const {
output: writeOutput,
errors: writeErrors,
warnings: writeWarnings,
unsupportedProperties: writeUnsupportedProperties
} = await targetParser.writeStyle(readOutput);
if (writeErrors) {
throw writeErrors;
}
if (writeWarnings) {
writeWarnings.map(console.warn);
}
if (writeUnsupportedProperties) {
console.log(`Target parser ${targetParser.title} does not support the following properties:`);
console.log(writeUnsupportedProperties);
}
output = typeof writeOutput === 'object' ? JSON.stringify(writeOutput, undefined, 2) : writeOutput;
} else {
output = JSON.stringify(readOutput, undefined, 2);
}
if (targetFile) {
await promises.writeFile(targetFile, output, 'utf-8');
indicator.succeed(`File "${sourceFile}" translated successfully. Output written to ${targetFile}`);
} else {
indicator.succeed(`File "${sourceFile}" translated successfully. Output written to stdout:\n`);
console.log(output);
}
const readOutput = sourceParser
? handleResult(await sourceParser.readStyle(inputFileData as any), sourceParser, 'Source')
: inputFileData;

indicator.text = `Writing to ${targetFile}`;
const writeOutput = targetParser
? handleResult(await targetParser.writeStyle(readOutput), targetParser, 'Target')
: readOutput;

const finalOutput = typeof writeOutput === 'object' ? JSON.stringify(writeOutput, undefined, 2) : writeOutput;

if (targetFile) {
await promises.writeFile(targetFile, finalOutput, 'utf-8');
indicator.succeed(`File "${sourceFile}" translated successfully. Output written to ${targetFile}`);
} else {
indicator.succeed(`File "${sourceFile}" translated successfully. Output written to stdout:\n`);
console.log(finalOutput);
}
} catch (error) {
indicator.fail(`Error during translation of file "${sourceFile}": ${error}`);
Expand Down Expand Up @@ -260,8 +239,8 @@ async function main() {

// Assign args
const sourcePath: string = unnamedArgs[0];
const sourceFormat: string = s || source || sourcePath;
const targetFormat: string = t || target;
let sourceFormat: string | undefined = s || source;
let targetFormat: string | undefined = t || target;
const outputPath: string = o || output;

// Instantiate progress indicator
Expand Down Expand Up @@ -290,17 +269,25 @@ async function main() {
return;
}

// Get source and target parser.
const sourceParser = sourceFormat && getParserFromFormat(sourceFormat)
|| (sourceIsFile && getParserFromFilename(sourcePath));
const targetParser = targetFormat && getParserFromFormat(targetFormat) || getParserFromFilename(outputPath);
if (!sourceParser) {
indicator.fail('No sourceparser was specified.');
return;
// Get source parser.
if (!sourceFormat && sourceIsFile) {
sourceFormat = getFormatFromFilename(sourcePath)
}
if (!sourceFormat) {
indicator.info('No sourceparser was specified. Input will be parsed as a GeoStyler object.');
sourceFormat = 'geostyler';
}
const sourceParser = getParserFromFormat(sourceFormat)

// Get target parser.
if (!targetFormat && targetIsFile) {
targetFormat = getFormatFromFilename(outputPath)
}
if (!targetParser) {
if (!targetFormat) {
indicator.info('No targetparser was specified. Output will be a GeoStyler object.');
targetFormat = 'geostyler';
}
const targetParser = getParserFromFormat(targetFormat);

// Get source(s) path(s).
const sourcePaths = collectPaths(sourcePath, sourceIsFile);
Expand Down
9 changes: 9 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ function runAllTests() {
success = false;
}

// test geostyler to mapbox
outputFile = 'output.mapbox';
args = ['start', '--', '-s', 'geostyler', '-o', outputFile, 'testdata/point_simplepoint.geostyler'];
runTest(args, outputFile);

if (checkFileCreated(outputFile) === false) {
success = false;
}

// test folder output
args = ['start', '--', '-s', 'sld', '-t', 'qgis', '-o', './output-bulk', 'testdata/sld'];
runTest(args, outputFile);
Expand Down
Loading