@emasoft/svg-matrix 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/bin/svg-matrix.js +67 -3
- package/bin/svglinter.cjs +84 -0
- package/bin/svgm.js +37 -0
- package/dist/svg-matrix.global.min.js +2 -2
- package/dist/svg-matrix.min.js +2 -2
- package/dist/svg-toolbox.global.min.js +110 -110
- package/dist/svg-toolbox.min.js +110 -110
- package/dist/svgm.min.js +112 -112
- package/dist/version.json +8 -8
- package/package.json +1 -1
- package/src/animation-optimization.js +29 -0
- package/src/index.js +2 -2
- package/src/inkscape-support.js +768 -0
- package/src/svg-matrix-lib.js +2 -2
- package/src/svg-toolbox-lib.js +2 -2
- package/src/svg-toolbox.js +290 -3
- package/src/svg-validation-data.js +1 -0
- package/src/svgm-lib.js +2 -2
package/README.md
CHANGED
|
@@ -333,6 +333,46 @@ svgm --export --export-prefix myapp_ input.svg -o output.svg --export-dir ./asse
|
|
|
333
333
|
| `--export-dry-run` | Preview extraction without writing files |
|
|
334
334
|
| `--export-ids <ids>` | Only export from specific element IDs |
|
|
335
335
|
|
|
336
|
+
### Inkscape Conversion
|
|
337
|
+
|
|
338
|
+
Convert Inkscape SVG files to plain/standard SVG by removing editor-specific metadata while preserving SVG 2 features:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# Using svgm
|
|
342
|
+
svgm --to-plain-svg inkscape-drawing.svg -o plain.svg
|
|
343
|
+
|
|
344
|
+
# Keep SVG 1.2 flowText elements (normally removed)
|
|
345
|
+
svgm --to-plain-svg --keep-flow-text inkscape-drawing.svg -o plain.svg
|
|
346
|
+
|
|
347
|
+
# Using svg-matrix CLI
|
|
348
|
+
svg-matrix to-plain inkscape-drawing.svg -o plain.svg
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**What gets removed:**
|
|
352
|
+
- `sodipodi:*` elements and attributes (guide lines, named views)
|
|
353
|
+
- `inkscape:*` elements and attributes (layers, path effects, version)
|
|
354
|
+
- SVG 1.2 flowText elements (not browser-supported)
|
|
355
|
+
- Namespace declarations (xmlns:inkscape, xmlns:sodipodi)
|
|
356
|
+
|
|
357
|
+
**What gets preserved:**
|
|
358
|
+
- Mesh gradients and hatches (SVG 2 features)
|
|
359
|
+
- All standard SVG elements and attributes
|
|
360
|
+
- Document structure and styling
|
|
361
|
+
|
|
362
|
+
### Run Without Installing
|
|
363
|
+
|
|
364
|
+
Use `bunx` or `npx` to run the CLI tools without installing the package:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
# Using bunx (faster)
|
|
368
|
+
bunx @emasoft/svg-matrix svgm input.svg -o output.svg
|
|
369
|
+
bunx @emasoft/svg-matrix svg-matrix flatten input.svg -o output.svg
|
|
370
|
+
|
|
371
|
+
# Using npx
|
|
372
|
+
npx @emasoft/svg-matrix svgm input.svg -o output.svg
|
|
373
|
+
npx @emasoft/svg-matrix svg-matrix to-plain inkscape.svg -o plain.svg
|
|
374
|
+
```
|
|
375
|
+
|
|
336
376
|
### YAML Configuration
|
|
337
377
|
|
|
338
378
|
Instead of CLI flags, you can use a YAML configuration file:
|
|
@@ -600,6 +640,22 @@ const layers = InkscapeSupport.findLayers(doc);
|
|
|
600
640
|
const settings = InkscapeSupport.getNamedViewSettings(doc);
|
|
601
641
|
```
|
|
602
642
|
|
|
643
|
+
### Plain SVG Conversion
|
|
644
|
+
|
|
645
|
+
```javascript
|
|
646
|
+
import { convertToPlainSVG } from '@emasoft/svg-matrix';
|
|
647
|
+
|
|
648
|
+
// Convert Inkscape SVG to plain/standard SVG
|
|
649
|
+
const plainSVG = await convertToPlainSVG(inkscapeSVG);
|
|
650
|
+
|
|
651
|
+
// With options
|
|
652
|
+
const plainSVG = await convertToPlainSVG(inkscapeSVG, {
|
|
653
|
+
removeFlowText: true, // Remove SVG 1.2 flowText (default: true)
|
|
654
|
+
removeEmptyDefs: true, // Clean up empty defs (default: true)
|
|
655
|
+
removeEmptyGroups: false, // Keep empty groups with IDs (default: false)
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
603
659
|
### SVG 2.0 Polyfills Module
|
|
604
660
|
|
|
605
661
|
```javascript
|
package/bin/svg-matrix.js
CHANGED
|
@@ -881,6 +881,9 @@ ${boxLine(` ${colors.dim}Ideal for animation and path morphing${col
|
|
|
881
881
|
${boxLine("", W)}
|
|
882
882
|
${boxLine(` ${colors.green}info${colors.reset} Show SVG file information and element counts`, W)}
|
|
883
883
|
${boxLine("", W)}
|
|
884
|
+
${boxLine(` ${colors.green}to-plain${colors.reset} Convert Inkscape SVG to plain/standard SVG`, W)}
|
|
885
|
+
${boxLine(` ${colors.dim}Removes all sodipodi:* and inkscape:* data${colors.reset}`, W)}
|
|
886
|
+
${boxLine("", W)}
|
|
884
887
|
${boxLine(` ${colors.green}test-toolbox${colors.reset} Test all svg-toolbox functions on an SVG file`, W)}
|
|
885
888
|
${boxLine(` ${colors.dim}Creates timestamped folder with all processed versions${colors.reset}`, W)}
|
|
886
889
|
${boxLine("", W)}
|
|
@@ -921,6 +924,14 @@ ${boxLine(` ${colors.dim}--no-minify-polyfills${colors.reset} Use full (non-m
|
|
|
921
924
|
${boxLine("", W)}
|
|
922
925
|
${boxDivider(W)}
|
|
923
926
|
${boxLine("", W)}
|
|
927
|
+
${boxHeader("TO-PLAIN OPTIONS", W)}
|
|
928
|
+
${boxLine("", W)}
|
|
929
|
+
${boxLine(` ${colors.yellow}${B.dot} Converts Inkscape SVG to plain/standard SVG${colors.reset}`, W)}
|
|
930
|
+
${boxLine(` ${colors.yellow}${B.dot} Removes: sodipodi:*, inkscape:*, SVG 1.2 flowText${colors.reset}`, W)}
|
|
931
|
+
${boxLine(` ${colors.yellow}${B.dot} Preserves: mesh gradients, hatches, standard SVG 2${colors.reset}`, W)}
|
|
932
|
+
${boxLine("", W)}
|
|
933
|
+
${boxDivider(W)}
|
|
934
|
+
${boxLine("", W)}
|
|
924
935
|
${boxHeader("PRECISION OPTIONS", W)}
|
|
925
936
|
${boxLine("", W)}
|
|
926
937
|
${boxLine(` ${colors.dim}--clip-segments <n>${colors.reset} Polygon samples for clipping (default: 64)`, W)}
|
|
@@ -945,6 +956,7 @@ ${boxLine(` ${colors.green}svg-matrix flatten${colors.reset} ./svgs/ -o ./out/
|
|
|
945
956
|
${boxLine(` ${colors.green}svg-matrix flatten${colors.reset} --list files.txt -o ./out/ --no-patterns`, W)}
|
|
946
957
|
${boxLine(` ${colors.green}svg-matrix flatten${colors.reset} input.svg -o out.svg --preserve-ns inkscape,sodipodi`, W)}
|
|
947
958
|
${boxLine(` ${colors.green}svg-matrix convert${colors.reset} input.svg -o output.svg -p 10`, W)}
|
|
959
|
+
${boxLine(` ${colors.green}svg-matrix to-plain${colors.reset} inkscape.svg -o plain.svg`, W)}
|
|
948
960
|
${boxLine(` ${colors.green}svg-matrix info${colors.reset} input.svg`, W)}
|
|
949
961
|
${boxLine("", W)}
|
|
950
962
|
${boxDivider(W)}
|
|
@@ -1644,6 +1656,52 @@ function processNormalize(inputPath, outputPath) {
|
|
|
1644
1656
|
}
|
|
1645
1657
|
}
|
|
1646
1658
|
|
|
1659
|
+
/**
|
|
1660
|
+
* Convert Inkscape SVG to plain/standard SVG.
|
|
1661
|
+
* Removes all Inkscape-specific and Sodipodi-specific content while preserving
|
|
1662
|
+
* standard SVG elements like mesh gradients, hatches, and other SVG 2 features.
|
|
1663
|
+
*
|
|
1664
|
+
* @param {string} inputPath - Input file path
|
|
1665
|
+
* @param {string} outputPath - Output file path
|
|
1666
|
+
* @returns {Promise<boolean>} True if successful
|
|
1667
|
+
*/
|
|
1668
|
+
async function processToPlain(inputPath, outputPath) {
|
|
1669
|
+
// Why: Validate parameters to prevent crashes
|
|
1670
|
+
if (!inputPath || typeof inputPath !== "string") {
|
|
1671
|
+
logError("Invalid input path: must be a non-empty string");
|
|
1672
|
+
return false;
|
|
1673
|
+
}
|
|
1674
|
+
if (!outputPath || typeof outputPath !== "string") {
|
|
1675
|
+
logError("Invalid output path: must be a non-empty string");
|
|
1676
|
+
return false;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
try {
|
|
1680
|
+
logDebug(`Converting to plain SVG: ${inputPath}`);
|
|
1681
|
+
const content = readFileSync(inputPath, "utf8");
|
|
1682
|
+
|
|
1683
|
+
// Apply convertToPlainSVG function
|
|
1684
|
+
// Why: This removes inkscape:* and sodipodi:* elements/attributes
|
|
1685
|
+
// but preserves mesh gradients, hatches, and other standard SVG features
|
|
1686
|
+
// Note: createOperation wrapper makes this async and handles parsing internally
|
|
1687
|
+
const result = await SVGToolbox.convertToPlainSVG(content, {
|
|
1688
|
+
removeFlowText: true, // SVG 1.2 flowText is Inkscape-only
|
|
1689
|
+
removeEmptyDefs: true, // Clean up defs after removing Inkscape content
|
|
1690
|
+
removeEmptyGroups: false, // Keep groups even if empty (may have id refs)
|
|
1691
|
+
});
|
|
1692
|
+
|
|
1693
|
+
if (!config.dryRun) {
|
|
1694
|
+
ensureDir(dirname(outputPath));
|
|
1695
|
+
writeFileSync(outputPath, result, "utf8");
|
|
1696
|
+
}
|
|
1697
|
+
logSuccess(`${basename(inputPath)} -> ${basename(outputPath)}`);
|
|
1698
|
+
return true;
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
logError(`Failed: ${inputPath}: ${error.message}`);
|
|
1701
|
+
return false;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1647
1705
|
/**
|
|
1648
1706
|
* Display information about SVG file.
|
|
1649
1707
|
* @param {string} inputPath - Input file path
|
|
@@ -2250,6 +2308,7 @@ function parseArgs(args) {
|
|
|
2250
2308
|
"convert",
|
|
2251
2309
|
"normalize",
|
|
2252
2310
|
"info",
|
|
2311
|
+
"to-plain",
|
|
2253
2312
|
"test-toolbox",
|
|
2254
2313
|
"help",
|
|
2255
2314
|
"version",
|
|
@@ -2373,7 +2432,8 @@ async function main() {
|
|
|
2373
2432
|
}
|
|
2374
2433
|
case "flatten":
|
|
2375
2434
|
case "convert":
|
|
2376
|
-
case "normalize":
|
|
2435
|
+
case "normalize":
|
|
2436
|
+
case "to-plain": {
|
|
2377
2437
|
const files = gatherInputFiles();
|
|
2378
2438
|
if (files.length === 0) {
|
|
2379
2439
|
logError("No input files");
|
|
@@ -2407,9 +2467,13 @@ async function main() {
|
|
|
2407
2467
|
? processFlatten
|
|
2408
2468
|
: config.command === "convert"
|
|
2409
2469
|
? processConvert
|
|
2410
|
-
:
|
|
2470
|
+
: config.command === "to-plain"
|
|
2471
|
+
? processToPlain
|
|
2472
|
+
: processNormalize;
|
|
2411
2473
|
|
|
2412
|
-
|
|
2474
|
+
// Why: processToPlain is async, so we need to await it
|
|
2475
|
+
const fnResult = await fn(f, out);
|
|
2476
|
+
if (fnResult) {
|
|
2413
2477
|
// Verify write if not dry run
|
|
2414
2478
|
if (!config.dryRun) {
|
|
2415
2479
|
// Why: Simple empty check instead of full verifyWriteSuccess because:
|
package/bin/svglinter.cjs
CHANGED
|
@@ -583,6 +583,73 @@ const RULES = {
|
|
|
583
583
|
description: "Missing lang/xml:lang attribute on SVG with text content",
|
|
584
584
|
fixable: false,
|
|
585
585
|
},
|
|
586
|
+
|
|
587
|
+
// === INKSCAPE RULES (I###) ===
|
|
588
|
+
// Namespace errors (I001-I099)
|
|
589
|
+
I001: {
|
|
590
|
+
type: "inkscape-invalid_namespace_uri",
|
|
591
|
+
severity: "error",
|
|
592
|
+
description: "Invalid Inkscape or Sodipodi namespace URI",
|
|
593
|
+
fixable: false,
|
|
594
|
+
},
|
|
595
|
+
I002: {
|
|
596
|
+
type: "inkscape-unknown_inkscape_element",
|
|
597
|
+
severity: "error",
|
|
598
|
+
description: "Unknown inkscape: element (not in namespace schema)",
|
|
599
|
+
fixable: false,
|
|
600
|
+
},
|
|
601
|
+
I003: {
|
|
602
|
+
type: "inkscape-unknown_sodipodi_element",
|
|
603
|
+
severity: "error",
|
|
604
|
+
description: "Unknown sodipodi: element (not in namespace schema)",
|
|
605
|
+
fixable: false,
|
|
606
|
+
},
|
|
607
|
+
|
|
608
|
+
// Attribute errors (I100-I199)
|
|
609
|
+
I101: {
|
|
610
|
+
type: "inkscape-invalid_inkscape_attribute",
|
|
611
|
+
severity: "error",
|
|
612
|
+
description: "Invalid value for inkscape: attribute",
|
|
613
|
+
fixable: false,
|
|
614
|
+
},
|
|
615
|
+
I102: {
|
|
616
|
+
type: "inkscape-invalid_sodipodi_attribute",
|
|
617
|
+
severity: "error",
|
|
618
|
+
description: "Invalid value for sodipodi: attribute",
|
|
619
|
+
fixable: false,
|
|
620
|
+
},
|
|
621
|
+
I103: {
|
|
622
|
+
type: "inkscape-unknown_inkscape_attribute",
|
|
623
|
+
severity: "error",
|
|
624
|
+
description: "Unknown inkscape: attribute (not in namespace schema)",
|
|
625
|
+
fixable: false,
|
|
626
|
+
},
|
|
627
|
+
I104: {
|
|
628
|
+
type: "inkscape-unknown_sodipodi_attribute",
|
|
629
|
+
severity: "error",
|
|
630
|
+
description: "Unknown sodipodi: attribute (not in namespace schema)",
|
|
631
|
+
fixable: false,
|
|
632
|
+
},
|
|
633
|
+
|
|
634
|
+
// Compatibility warnings (I200-I299)
|
|
635
|
+
I201: {
|
|
636
|
+
type: "inkscape-flowtext_compatibility",
|
|
637
|
+
severity: "warning",
|
|
638
|
+
description: "flowRoot/flowPara elements require polyfill for browser rendering",
|
|
639
|
+
fixable: false,
|
|
640
|
+
},
|
|
641
|
+
I202: {
|
|
642
|
+
type: "inkscape-mesh_gradient",
|
|
643
|
+
severity: "warning",
|
|
644
|
+
description: "Mesh gradient requires polyfill for browser rendering",
|
|
645
|
+
fixable: false,
|
|
646
|
+
},
|
|
647
|
+
I203: {
|
|
648
|
+
type: "inkscape-hatch_paint",
|
|
649
|
+
severity: "warning",
|
|
650
|
+
description: "Hatch paint server requires polyfill for browser rendering",
|
|
651
|
+
fixable: false,
|
|
652
|
+
},
|
|
586
653
|
};
|
|
587
654
|
|
|
588
655
|
// Create reverse lookup: type -> code
|
|
@@ -1330,6 +1397,8 @@ function parseArgs(argv) {
|
|
|
1330
1397
|
verbose: false, // Enable verbose debug output
|
|
1331
1398
|
stdin: false, // Read from stdin instead of files
|
|
1332
1399
|
severityOverrides: {}, // Map of rule code -> 'error'|'warning' for severity customization
|
|
1400
|
+
validateInkscape: false, // Enable Inkscape namespace validation
|
|
1401
|
+
inkscapeStrict: false, // Strict Inkscape validation (unknown attributes are errors)
|
|
1333
1402
|
};
|
|
1334
1403
|
|
|
1335
1404
|
let i = 2;
|
|
@@ -1752,6 +1821,9 @@ function parseArgs(argv) {
|
|
|
1752
1821
|
args.verbose = true;
|
|
1753
1822
|
} else if (arg === "--stdin" || arg === "-") {
|
|
1754
1823
|
args.stdin = true;
|
|
1824
|
+
} else if (arg === "--validate-inkscape" || arg === "--inkscape" || arg === "--inkscape-strict") {
|
|
1825
|
+
// All Inkscape validation is now strict by default (spec compliance)
|
|
1826
|
+
args.validateInkscape = true;
|
|
1755
1827
|
} else if (!arg.startsWith("-")) {
|
|
1756
1828
|
args.files.push(arg);
|
|
1757
1829
|
} else {
|
|
@@ -1835,6 +1907,12 @@ ${c("bold", "FORMATS")}
|
|
|
1835
1907
|
sarif SARIF 2.1.0 for security tools (CodeQL, Snyk, etc.)
|
|
1836
1908
|
github GitHub Actions annotations (::error, ::warning)
|
|
1837
1909
|
|
|
1910
|
+
${c("bold", "INKSCAPE SUPPORT")}
|
|
1911
|
+
${c("cyan", "--validate-inkscape")} Enable Inkscape namespace validation (strict mode)
|
|
1912
|
+
${c("cyan", "--inkscape")} Alias for --validate-inkscape
|
|
1913
|
+
${c("dim", "All unknown elements/attributes are errors (spec compliance)")}
|
|
1914
|
+
${c("dim", "Polyfill requirements (flowText, mesh, hatch) are warnings")}
|
|
1915
|
+
|
|
1838
1916
|
${c("bold", "CONFIGURATION")}
|
|
1839
1917
|
${c("cyan", "-c, --config")} <file> Path to config file
|
|
1840
1918
|
${c("cyan", "--init")}[=format] Create config file (json, yaml, toml; default: json)
|
|
@@ -4269,6 +4347,8 @@ async function main() {
|
|
|
4269
4347
|
const result = await validateSVGAsync(content, {
|
|
4270
4348
|
errorsOnly: args.errorsOnly,
|
|
4271
4349
|
includeSource: true,
|
|
4350
|
+
validateInkscape: args.validateInkscape,
|
|
4351
|
+
inkscapeStrict: args.inkscapeStrict,
|
|
4272
4352
|
});
|
|
4273
4353
|
|
|
4274
4354
|
// Add invalid character issues
|
|
@@ -4426,6 +4506,8 @@ async function main() {
|
|
|
4426
4506
|
const result = await validateSVGAsync(file, {
|
|
4427
4507
|
errorsOnly: args.errorsOnly,
|
|
4428
4508
|
includeSource: true,
|
|
4509
|
+
validateInkscape: args.validateInkscape,
|
|
4510
|
+
inkscapeStrict: args.inkscapeStrict,
|
|
4429
4511
|
});
|
|
4430
4512
|
|
|
4431
4513
|
// Add invalid character issues
|
|
@@ -4836,6 +4918,8 @@ async function lintFile(filePath, options = {}) {
|
|
|
4836
4918
|
const result = await validateSVGAsync(filePath, {
|
|
4837
4919
|
errorsOnly: options.errorsOnly || false,
|
|
4838
4920
|
includeSource: options.includeSource !== false,
|
|
4921
|
+
validateInkscape: options.validateInkscape || false,
|
|
4922
|
+
inkscapeStrict: options.inkscapeStrict || false,
|
|
4839
4923
|
});
|
|
4840
4924
|
|
|
4841
4925
|
// Add invalid character issues
|
package/bin/svgm.js
CHANGED
|
@@ -109,6 +109,9 @@ const DEFAULT_CONFIG = {
|
|
|
109
109
|
embedMaxRecursionDepth: 10,
|
|
110
110
|
embedTimeout: 30000,
|
|
111
111
|
embedOnMissingResource: "warn",
|
|
112
|
+
// Plain SVG conversion
|
|
113
|
+
toPlainSVG: false,
|
|
114
|
+
removeFlowText: true,
|
|
112
115
|
};
|
|
113
116
|
|
|
114
117
|
let config = { ...DEFAULT_CONFIG };
|
|
@@ -529,6 +532,20 @@ async function optimizeSvg(content, options = {}) {
|
|
|
529
532
|
}
|
|
530
533
|
}
|
|
531
534
|
|
|
535
|
+
// Convert to plain SVG if requested (remove all Inkscape/Sodipodi content)
|
|
536
|
+
// Why: This must run AFTER the optimization pipeline but BEFORE polyfills
|
|
537
|
+
if (options.toPlainSVG) {
|
|
538
|
+
try {
|
|
539
|
+
SVGToolbox.convertToPlainSVG(doc, {
|
|
540
|
+
removeFlowText: options.removeFlowText !== false,
|
|
541
|
+
removeEmptyDefs: true,
|
|
542
|
+
removeEmptyGroups: false,
|
|
543
|
+
});
|
|
544
|
+
} catch (err) {
|
|
545
|
+
logWarn(`convertToPlainSVG failed: ${err.message}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
532
549
|
// Inject SVG 2 polyfills if requested (using pre-detected features)
|
|
533
550
|
if (options.svg2Polyfills && svg2Features) {
|
|
534
551
|
if (
|
|
@@ -843,6 +860,12 @@ Embed Options:
|
|
|
843
860
|
--embed-timeout <ms> Timeout for external resources (default: 30000)
|
|
844
861
|
--embed-on-missing <mode> Handle missing resources: 'warn', 'fail', 'skip'
|
|
845
862
|
|
|
863
|
+
Inkscape Conversion:
|
|
864
|
+
--to-plain-svg Convert Inkscape SVG to plain/standard SVG
|
|
865
|
+
(removes sodipodi:*, inkscape:* elements and attributes)
|
|
866
|
+
--keep-flow-text Keep SVG 1.2 flowText elements when using --to-plain-svg
|
|
867
|
+
(by default they are removed as browsers don't support them)
|
|
868
|
+
|
|
846
869
|
Examples:
|
|
847
870
|
svgm input.svg -o output.svg
|
|
848
871
|
svgm -f ./icons/ -o ./optimized/
|
|
@@ -850,6 +873,7 @@ Examples:
|
|
|
850
873
|
svgm -p 2 --multipass input.svg
|
|
851
874
|
svgm input.svg --embed-all -o output.svg
|
|
852
875
|
svgm input.svg --config svgm.yml -o output.svg
|
|
876
|
+
svgm inkscape.svg --to-plain-svg -o plain.svg
|
|
853
877
|
|
|
854
878
|
Docs: https://github.com/Emasoft/SVG-MATRIX#readme`);
|
|
855
879
|
}
|
|
@@ -1320,6 +1344,16 @@ function parseArgs(args) {
|
|
|
1320
1344
|
i++;
|
|
1321
1345
|
break;
|
|
1322
1346
|
|
|
1347
|
+
case "--to-plain-svg":
|
|
1348
|
+
// Why: Enable conversion from Inkscape SVG to plain/standard SVG
|
|
1349
|
+
cfg.toPlainSVG = true;
|
|
1350
|
+
break;
|
|
1351
|
+
|
|
1352
|
+
case "--keep-flow-text":
|
|
1353
|
+
// Why: When using --to-plain-svg, keep SVG 1.2 flowText elements
|
|
1354
|
+
cfg.removeFlowText = false;
|
|
1355
|
+
break;
|
|
1356
|
+
|
|
1323
1357
|
default:
|
|
1324
1358
|
if (arg.startsWith("-")) {
|
|
1325
1359
|
logError(`Unknown option: ${arg}`);
|
|
@@ -1471,6 +1505,9 @@ async function main() {
|
|
|
1471
1505
|
embedMaxRecursionDepth: config.embedMaxRecursionDepth,
|
|
1472
1506
|
embedTimeout: config.embedTimeout,
|
|
1473
1507
|
embedOnMissingResource: config.embedOnMissingResource,
|
|
1508
|
+
// Plain SVG conversion options
|
|
1509
|
+
toPlainSVG: config.toPlainSVG,
|
|
1510
|
+
removeFlowText: config.removeFlowText,
|
|
1474
1511
|
};
|
|
1475
1512
|
|
|
1476
1513
|
// Handle string input
|